Skip to content

Commit

Permalink
Refactor rename and file creation modules (#995)
Browse files Browse the repository at this point in the history
**Background**

Rename and file creation are located insided listing module. Later this
features will be required during file transfer and file copy.

**Changes**

- Move file creation and folder creation into separate module

**Test plan**

- The behaviour should be the same as before
  • Loading branch information
makeevrserg authored Dec 2, 2024
1 parent 8b325fd commit 8b2440a
Show file tree
Hide file tree
Showing 37 changed files with 876 additions and 364 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

- [Feature] Add count subfolders for new file manager
- [Feature] Add file downloading for new file manager
- [Refactor] Move rename and file create to separated modules
- [FIX] Migrate url host from metric.flipperdevices.com to metric.flipp.dev
- [FIX] Fix empty response in faphub category
- [FIX] New file manager uploading progress
Expand Down
4 changes: 4 additions & 0 deletions components/bridge/connection/sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ dependencies {
implementation(projects.components.filemngr.editor.impl)
implementation(projects.components.filemngr.download.api)
implementation(projects.components.filemngr.download.impl)
implementation(projects.components.filemngr.rename.api)
implementation(projects.components.filemngr.rename.impl)
implementation(projects.components.filemngr.create.api)
implementation(projects.components.filemngr.create.impl)

implementation(projects.components.newfilemanager.api)
implementation(projects.components.newfilemanager.impl)
Expand Down
17 changes: 17 additions & 0 deletions components/filemngr/create/api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
}

android.namespace = "com.flipperdevices.filemanager.create.api"

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

implementation(projects.components.core.ui.decompose)

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

implementation(libs.okio)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.flipperdevices.filemanager.create.api

import com.arkivanov.decompose.ComponentContext
import com.flipperdevices.bridge.connection.feature.storage.api.model.FileType
import com.flipperdevices.bridge.connection.feature.storage.api.model.ListingItem
import com.flipperdevices.ui.decompose.ScreenDecomposeComponent
import kotlinx.coroutines.flow.StateFlow
import okio.Path

abstract class CreateFileDecomposeComponent(
componentContext: ComponentContext
) : ScreenDecomposeComponent(componentContext) {
abstract val canCreateFiles: StateFlow<Boolean>

abstract fun startCreateFile(parent: Path)

abstract fun startCreateFolder(parent: Path)

abstract fun startCreate(parent: Path, type: FileType)

fun interface Factory {
operator fun invoke(
componentContext: ComponentContext,
createCallback: CreatedCallback,
): CreateFileDecomposeComponent
}

fun interface CreatedCallback {
fun invoke(item: ListingItem)
}
}
52 changes: 52 additions & 0 deletions components/filemngr/create/impl/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
plugins {
id("flipper.multiplatform-compose")
id("flipper.multiplatform-dependencies")
id("flipper.anvil-multiplatform")
id("kotlinx-serialization")
}
android.namespace = "com.flipperdevices.filemanager.create.impl"

commonDependencies {
implementation(projects.components.core.di)
implementation(projects.components.core.ktx)
implementation(projects.components.core.log)
implementation(projects.components.core.preference)

implementation(projects.components.core.ui.lifecycle)
implementation(projects.components.core.ui.theme)
implementation(projects.components.core.ui.decompose)
implementation(projects.components.core.ui.ktx)
implementation(projects.components.core.ui.res)
implementation(projects.components.core.ui.dialog)

implementation(projects.components.bridge.connection.feature.common.api)
implementation(projects.components.bridge.connection.transport.common.api)
implementation(projects.components.bridge.connection.feature.provider.api)
implementation(projects.components.bridge.connection.feature.storage.api)
implementation(projects.components.bridge.connection.feature.storageinfo.api)
implementation(projects.components.bridge.connection.feature.serialspeed.api)
implementation(projects.components.bridge.connection.feature.rpcinfo.api)
implementation(projects.components.bridge.dao.api)

implementation(projects.components.filemngr.util)
implementation(projects.components.filemngr.uiComponents)
implementation(projects.components.filemngr.create.api)

// Compose
implementation(libs.compose.ui)
implementation(libs.compose.tooling)
implementation(libs.compose.foundation)
implementation(libs.compose.material)

implementation(libs.kotlin.serialization.json)
implementation(libs.ktor.client)

implementation(libs.decompose)
implementation(libs.kotlin.coroutines)
implementation(libs.essenty.lifecycle)
implementation(libs.essenty.lifecycle.coroutines)

implementation(libs.bundles.decompose)
implementation(libs.okio)
implementation(libs.kotlin.immutable.collections)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="fmc_create_file_title">Enter Name:</string>
<string name="fml_create_file_btn">Create File</string>
<string name="fml_create_folder_btn">Create Folder</string>
<string name="fmc_create_file_allowed_chars">Allowed characters: %1$s</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.flipperdevices.filemanager.create.impl.api

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.essenty.instancekeeper.getOrCreate
import com.flipperdevices.bridge.connection.feature.storage.api.model.FileType
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.filemanager.create.api.CreateFileDecomposeComponent
import com.flipperdevices.filemanager.create.impl.viewmodel.CreateFileViewModel
import com.flipperdevices.filemanager.ui.components.name.NameDialog
import com.flipperdevices.filemanager.util.constant.FileManagerConstants
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import flipperapp.components.filemngr.create.impl.generated.resources.fmc_create_file_allowed_chars
import flipperapp.components.filemngr.create.impl.generated.resources.fmc_create_file_title
import flipperapp.components.filemngr.create.impl.generated.resources.fml_create_file_btn
import flipperapp.components.filemngr.create.impl.generated.resources.fml_create_folder_btn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import me.gulya.anvil.assisted.ContributesAssistedFactory
import okio.Path
import org.jetbrains.compose.resources.stringResource
import javax.inject.Provider
import flipperapp.components.filemngr.create.impl.generated.resources.Res as FMC

@ContributesAssistedFactory(AppGraph::class, CreateFileDecomposeComponent.Factory::class)
class CreateFileDecomposeComponentImpl @AssistedInject constructor(
@Assisted componentContext: ComponentContext,
@Assisted val createdCallback: CreatedCallback,
renameViewModelProvider: Provider<CreateFileViewModel>
) : CreateFileDecomposeComponent(componentContext) {
private val createFileViewModel = instanceKeeper.getOrCreate {
renameViewModelProvider.get()
}

override val canCreateFiles = createFileViewModel.canCreateFiles

override fun startCreateFile(parent: Path) {
createFileViewModel.startCreateFile(parent)
}

override fun startCreateFolder(parent: Path) {
createFileViewModel.startCreateFolder(parent)
}

override fun startCreate(parent: Path, type: FileType) {
createFileViewModel.startCreate(parent, type)
}

@Composable
override fun Render() {
val state by createFileViewModel.state.collectAsState()
LaunchedEffect(createFileViewModel) {
createFileViewModel.event
.onEach { event ->
when (event) {
is CreateFileViewModel.Event.Created -> {
createdCallback.invoke(event.item)
}
}
}.launchIn(this)
}
when (val localState = state) {
CreateFileViewModel.State.Pending -> Unit
is CreateFileViewModel.State.Creating -> {
NameDialog(
value = localState.name,
title = stringResource(FMC.string.fmc_create_file_title),
buttonText = when (localState.type) {
FileType.FILE -> stringResource(FMC.string.fml_create_file_btn)
FileType.DIR -> stringResource(FMC.string.fml_create_folder_btn)
},
subtitle = stringResource(
FMC.string.fmc_create_file_allowed_chars,
FileManagerConstants.FILE_NAME_AVAILABLE_CHARACTERS
),
onFinish = createFileViewModel::onConfirm,
isError = !localState.isValid,
isEnabled = !localState.isCreating,
needShowOptions = localState.needShowOptions,
onTextChange = createFileViewModel::onNameChange,
onDismissRequest = createFileViewModel::dismiss,
onOptionSelect = createFileViewModel::onOptionSelected,
options = localState.options
)
}
}
}
}
Loading

0 comments on commit 8b2440a

Please sign in to comment.