Skip to content

Commit

Permalink
Merge branch 'dev' into single-tap-infrared
Browse files Browse the repository at this point in the history
  • Loading branch information
makeevrserg authored Dec 4, 2024
2 parents cc179ea + 30d085b commit 47f8bc3
Show file tree
Hide file tree
Showing 110 changed files with 3,566 additions and 1,300 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@

- [Feature] Add count subfolders for new file manager
- [Feature] Add file downloading for new file manager
- [Feature] Add move-to to new file manager
- [Feature] Single tap for infrared remotes
- [Refactor] Move rename and file create to separated modules
- [Refactor] Improve and refactor new FileManager Editor
- [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
- [FIX] Fix build when no metrics enabled
- [Feature] Single tap for infrared remotes
- [FIX] Fix small issues with new file manager

# 1.8.0
Attention: don't forget to add the flag for F-Droid before release

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ internal class PendingResponseCounter(
}

companion object {
internal const val LAGS_FLIPPER_DETECT_TIMEOUT_MS = 10 * 1000L // 10 seconds
internal const val LAGS_FLIPPER_DETECT_TIMEOUT_MS = 30 * 1000L // 30 seconds
}
}
6 changes: 6 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,12 @@ 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.filemngr.transfer.api)
implementation(projects.components.filemngr.transfer.impl)

implementation(projects.components.newfilemanager.api)
implementation(projects.components.newfilemanager.impl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.flipperdevices.core.share

import android.content.Context
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.core.ktx.jre.createClearNewFileWithMkDirs
import com.squareup.anvil.annotations.ContributesBinding
import okio.Path.Companion.toOkioPath
import javax.inject.Inject
Expand All @@ -12,8 +13,9 @@ class AndroidShareHelper @Inject constructor(
) : PlatformShareHelper {

override fun provideSharableFile(fileName: String): PlatformSharableFile {
val path = SharableFile(context, fileName).toOkioPath()
return PlatformSharableFile(path)
val sharableFile = SharableFile(context, fileName)
sharableFile.createClearNewFileWithMkDirs()
return PlatformSharableFile(sharableFile.toOkioPath())
}

override fun shareFile(file: PlatformSharableFile, title: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package com.flipperdevices.core.ui.ktx.elements

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import com.flipperdevices.core.ui.ktx.clickableRipple
import com.flipperdevices.core.ui.ktx.placeholderByLocalProvider
import com.flipperdevices.core.ui.theme.LocalPallet
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.core.ui.theme.LocalTypography

@Composable
Expand All @@ -24,27 +31,45 @@ fun ComposableFlipperButton(
textPadding: PaddingValues = PaddingValues(vertical = 16.dp, horizontal = 38.dp),
onClick: () -> Unit = {},
textStyle: TextStyle = TextStyle(),
enabled: Boolean = true
enabled: Boolean = true,
isLoading: Boolean = false,
) {
val background = if (enabled) {
LocalPallet.current.accentSecond
} else {
LocalPallet.current.flipperDisableButton
}
val background by animateColorAsState(
targetValue = if (enabled && !isLoading) {
LocalPallet.current.accentSecond
} else {
LocalPallet.current.flipperDisableButton
}
)

Box(
modifier = modifier
.clip(RoundedCornerShape(size = 30.dp))
.placeholderByLocalProvider()
.background(background)
.clickableRipple(onClick = onClick),
.clickableRipple(onClick = onClick, enabled = enabled && !isLoading),
contentAlignment = Alignment.Center
) {
Text(
modifier = Modifier.padding(textPadding),
text = text,
color = LocalPallet.current.onFlipperButton,
style = LocalTypography.current.buttonB16.merge(textStyle)
AnimatedContent(
targetState = isLoading,
contentAlignment = Alignment.Center,
content = { animatedIsLoading ->
if (animatedIsLoading) {
CircularProgressIndicator(
color = LocalPalletV2.current.action.blue.icon.onColor,
modifier = Modifier.padding(textPadding).size(22.dp),
strokeCap = StrokeCap.Round,
strokeWidth = 2.dp
)
} else {
Text(
modifier = Modifier.padding(textPadding),
text = text,
color = LocalPallet.current.onFlipperButton,
style = LocalTypography.current.buttonB16.merge(textStyle)
)
}
}
)
}
}
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,93 @@
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,
isLoading = localState.isCreating
)
}
}
}
}
Loading

0 comments on commit 47f8bc3

Please sign in to comment.