Skip to content

Commit

Permalink
Fix file upload progress (#985)
Browse files Browse the repository at this point in the history
**Background**
This PR aims to improve new file manager uploading reactivity and fix ui
for multiple files

**Changes**

- Remove upload screen and replace it with component
- Add callbacks for uploaded file progreess - will now be updated in
items list
- Fix multiple files upload display 

**Test plan**

- Try upload one file fully and see it will appear in list instantly
- Try upload one file but cancel it in progress. See it also appeared,
but with non-full upload size
- Try upload multiple files
  • Loading branch information
makeevrserg authored Nov 25, 2024
1 parent bc9d06f commit b5f3df1
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 169 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# 1.8.1 - In Progress

- [FIX] New file manager uploading progress
- [FIX] Fix build when no metrics enabled

# 1.8.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fun UploaderDecomposeComponent.RenderLoadingScreen(modifier: Modifier = Modifier
Render(
state = uploaderState,
speedState = speedState,
onCancel = ::onCancel,
onCancelClick = ::onCancel,
modifier = Modifier
.fillMaxSize()
.background(LocalPalletV2.current.surface.backgroundMain.body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ abstract class FilesDecomposeComponent(
pathChangedCallback: PathChangedCallback,
fileSelectedCallback: FileSelectedCallback,
searchCallback: SearchCallback,
uploadCallback: UploadCallback
): FilesDecomposeComponent
}

Expand Down
1 change: 1 addition & 0 deletions components/filemngr/listing/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ commonDependencies {
implementation(projects.components.filemngr.uiComponents)
implementation(projects.components.filemngr.listing.api)
implementation(projects.components.filemngr.main.api)
implementation(projects.components.filemngr.upload.api)

// Compose
implementation(libs.compose.ui)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.flipperdevices.filemanager.listing.impl.api

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.childContext
import com.arkivanov.decompose.router.slot.ChildSlot
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
Expand All @@ -22,6 +23,7 @@ import com.flipperdevices.filemanager.listing.impl.viewmodel.FilesViewModel
import com.flipperdevices.filemanager.listing.impl.viewmodel.OptionsViewModel
import com.flipperdevices.filemanager.listing.impl.viewmodel.SelectionViewModel
import com.flipperdevices.filemanager.listing.impl.viewmodel.StorageInfoViewModel
import com.flipperdevices.filemanager.upload.api.UploadDecomposeComponent
import com.flipperdevices.ui.decompose.DecomposeOnBackParameter
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
Expand All @@ -38,13 +40,13 @@ class FilesDecomposeComponentImpl @AssistedInject constructor(
@Assisted private val pathChangedCallback: PathChangedCallback,
@Assisted private val fileSelectedCallback: FileSelectedCallback,
@Assisted private val searchCallback: SearchCallback,
@Assisted private val uploadCallback: UploadCallback,
private val storageInfoViewModelFactory: Provider<StorageInfoViewModel>,
private val optionsInfoViewModelFactory: Provider<OptionsViewModel>,
private val editFileViewModelFactory: Provider<EditFileViewModel>,
private val deleteFilesViewModelFactory: Provider<DeleteFilesViewModel>,
private val filesViewModelFactory: FilesViewModel.Factory,
private val createSelectionViewModel: Provider<SelectionViewModel>
private val createSelectionViewModel: Provider<SelectionViewModel>,
private val uploadDecomposeComponentFactory: UploadDecomposeComponent.Factory,
) : FilesDecomposeComponent(componentContext) {

private val slotNavigation = SlotNavigation<PathWithType>()
Expand All @@ -55,10 +57,21 @@ class FilesDecomposeComponentImpl @AssistedInject constructor(
childFactory = { bottomSheetFile, _ -> bottomSheetFile }
)

private val selectionViewModel = instanceKeeper.getOrCreate(path.toString()) {
private val selectionViewModel = instanceKeeper.getOrCreate("selectionViewModel_$path") {
createSelectionViewModel.get()
}

val filesViewModel = instanceKeeper.getOrCreate("filesViewModel_$path") {
filesViewModelFactory.invoke(path)
}

private val uploadDecomposeComponent by lazy {
uploadDecomposeComponentFactory.invoke(
componentContext = childContext("FilesDecomposeComponent_uploadDecomposeComponent"),
onFilesChanged = filesViewModel::onFilesChanged,
)
}

private val backCallback = BackCallback {
val parent = path.parent
when {
Expand Down Expand Up @@ -86,9 +99,7 @@ class FilesDecomposeComponentImpl @AssistedInject constructor(

@Composable
override fun Render() {
val filesViewModel = viewModelWithFactory(path.toString()) {
filesViewModelFactory.invoke(path)
}
val multipleFilesPicker = uploadDecomposeComponent.rememberMultipleFilesPicker(path)
val storageInfoViewModel = viewModelWithFactory(path.root.toString()) {
storageInfoViewModelFactory.get()
}
Expand Down Expand Up @@ -116,7 +127,7 @@ class FilesDecomposeComponentImpl @AssistedInject constructor(
storageInfoViewModel = storageInfoViewModel,
selectionViewModel = selectionViewModel,
onBack = onBack::invoke,
onUploadClick = uploadCallback::invoke,
onUploadClick = multipleFilesPicker::startFilePicker,
onPathChange = pathChangedCallback::invoke,
onFileMoreClick = slotNavigation::activate,
onSearchClick = searchCallback::invoke,
Expand All @@ -129,5 +140,6 @@ class FilesDecomposeComponentImpl @AssistedInject constructor(
createFileViewModel = createFileViewModel,
deleteFileViewModel = deleteFileViewModel
)
uploadDecomposeComponent.Render()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,19 @@ class FilesViewModel @AssistedInject constructor(
}
}

fun onFilesChanged(items: List<ListingItem>) {
_state.update { state ->
(state as? State.Loaded)?.let { loadedState ->
val newItemsNames = items.map(ListingItem::fileName)
val newFiles = loadedState.files
.filter { item -> !newItemsNames.contains(item.fileName) }
.plus(items)
.toImmutableList()
loadedState.copy(files = newFiles)
} ?: state
}
}

private suspend fun invalidate(
featureStatus: FFeatureStatus<FStorageFeatureApi>
) = withLock(mutex, "invalidate") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.flipperdevices.filemanager.listing.api.FilesDecomposeComponent
import com.flipperdevices.filemanager.main.api.FileManagerDecomposeComponent
import com.flipperdevices.filemanager.main.impl.model.FileManagerNavigationConfig
import com.flipperdevices.filemanager.search.api.SearchDecomposeComponent
import com.flipperdevices.filemanager.upload.api.UploadDecomposeComponent
import com.flipperdevices.ui.decompose.DecomposeComponent
import com.flipperdevices.ui.decompose.DecomposeOnBackParameter
import com.flipperdevices.ui.decompose.popOr
Expand All @@ -26,7 +25,6 @@ class FileManagerDecomposeComponentImpl @AssistedInject constructor(
@Assisted componentContext: ComponentContext,
@Assisted private val onBack: DecomposeOnBackParameter,
private val filesDecomposeComponentFactory: FilesDecomposeComponent.Factory,
private val uploadDecomposeComponentFactory: UploadDecomposeComponent.Factory,
private val searchDecomposeComponentFactory: SearchDecomposeComponent.Factory,
private val editorDecomposeComponentFactory: FileManagerEditorDecomposeComponent.Factory,
) : FileManagerDecomposeComponent<FileManagerNavigationConfig>(),
Expand Down Expand Up @@ -55,19 +53,10 @@ class FileManagerDecomposeComponentImpl @AssistedInject constructor(
fileSelectedCallback = {
navigation.pushNew(FileManagerNavigationConfig.Edit(it))
},
uploadCallback = { navigation.pushNew(FileManagerNavigationConfig.Upload(config.path)) },
searchCallback = { navigation.pushNew(FileManagerNavigationConfig.Search(config.path)) },
)
}

is FileManagerNavigationConfig.Upload -> {
uploadDecomposeComponentFactory.invoke(
componentContext = componentContext,
path = config.path,
onFinish = navigation::pop
)
}

is FileManagerNavigationConfig.Search -> {
searchDecomposeComponentFactory.invoke(
componentContext = componentContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ sealed interface FileManagerNavigationConfig {
val path: Path
) : FileManagerNavigationConfig

@Serializable
data class Upload(
@Serializable(with = PathSerializer::class)
val path: Path
) : FileManagerNavigationConfig

@Serializable
data class Edit(
@Serializable(with = PathSerializer::class)
Expand Down
2 changes: 2 additions & 0 deletions components/filemngr/upload/api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ commonDependencies {
implementation(projects.components.core.ui.decompose)
implementation(projects.components.deeplink.api)

implementation(projects.components.bridge.connection.feature.storage.api)

implementation(libs.compose.ui)
implementation(libs.decompose)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.flipperdevices.filemanager.upload.api

fun interface MultipleFilesPicker {
fun startFilePicker()
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.flipperdevices.filemanager.upload.api

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import com.flipperdevices.ui.decompose.ScreenDecomposeComponent
import com.flipperdevices.bridge.connection.feature.storage.api.model.ListingItem
import okio.Path

abstract class UploadDecomposeComponent(
componentContext: ComponentContext
) : ScreenDecomposeComponent(componentContext) {
interface UploadDecomposeComponent {

@Composable
fun rememberMultipleFilesPicker(path: Path): MultipleFilesPicker

@Composable
fun Render()

fun interface Factory {
operator fun invoke(
componentContext: ComponentContext,
path: Path,
onFinish: () -> Unit
onFilesChanged: (List<ListingItem>) -> Unit,
): UploadDecomposeComponent
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.flipperdevices.filemanager.upload.api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.ComponentContext
import com.flipperdevices.bridge.connection.feature.storage.api.model.ListingItem
import com.flipperdevices.deeplink.model.DeeplinkContent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
Expand All @@ -29,24 +30,30 @@ interface UploaderDecomposeComponent {
fun Render(
state: State,
speedState: Long?,
onCancel: () -> Unit,
onCancelClick: () -> Unit,
modifier: Modifier
)

sealed interface State {
data object Pending : State
data object Error : State
data object Uploaded : State
data class Uploaded(val items: List<ListingItem>) : State
data object Cancelled : State
data class Uploading(
val fileIndex: Int,
val totalFiles: Int,
val uploadedFileSize: Long,
val uploadFileTotalSize: Long,
val fileName: String
val currentItemIndex: Int,
val totalItemsAmount: Int,
val uploadedSize: Long,
val totalSize: Long,
val currentItem: UploadingItem,
) : State
}

data class UploadingItem(
val fileName: String,
val uploadedSize: Long,
val totalSize: Long
)

fun interface Factory {
operator fun invoke(
componentContext: ComponentContext,
Expand Down
Loading

0 comments on commit b5f3df1

Please sign in to comment.