Skip to content

Commit

Permalink
Remotecontrols/dialogs (#942)
Browse files Browse the repository at this point in the history
**Background**

On new remote-controls screen we don't have much dialogs to determine
current flipper conditions. This PR adds new dialogs to improve the
situation

**Changes**

- Add dialogs into remote-controls for NotSupported/Busy/NotConnected
- Move remotecontrols into bottombar

**Test plan**

- Open some saved remote or new remote with flipper disconnected or busy
- try press button and see dialog
  • Loading branch information
makeevrserg committed Sep 9, 2024
1 parent 85a91dd commit e6f2aff
Show file tree
Hide file tree
Showing 34 changed files with 287 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Attention: don't forget to add the flag for F-Droid before release
- [Feature] Add How to Use dialog into remote-controls
- [Feature] Skip infrared signals on setup screen
- [Feature] Better user-ux when configuring remote control
- [Feature] Add flipper action dialogs into remote control and move it into bottombar
- [Refactor] Load RemoteControls from flipper, emulating animation
- [Refactor] Update to Kotlin 2.0
- [Refactor] Replace Ktorfit with Ktor requests in remote-controls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,23 @@ import com.flipperdevices.core.ui.ktx.clickableRipple
import com.flipperdevices.core.ui.theme.LocalPallet
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.core.ui.theme.LocalTypography
import com.flipperdevices.deeplink.model.Deeplink
import com.flipperdevices.keyparser.api.model.FlipperKeyParsed
import com.flipperdevices.rootscreen.api.LocalRootNavigation
import com.flipperdevices.rootscreen.model.RootScreenConfig
import com.flipperdevices.rootscreen.api.LocalDeeplinkHandler
import kotlinx.collections.immutable.ImmutableList

@Composable
fun AddRemoteEndBlock(modifier: Modifier = Modifier) {
val rootNavigation = LocalRootNavigation.current
val deeplinkHandler = LocalDeeplinkHandler.current
Text(
text = stringResource(R.string.add_remote),
style = LocalTypography.current.buttonB14,
color = LocalPalletV2.current.text.title.blackOnColor,
modifier = modifier
.padding(horizontal = 14.dp)
.clickableRipple { rootNavigation.push(RootScreenConfig.RemoteControls) }
.clickableRipple {
deeplinkHandler.handleDeeplink(Deeplink.BottomBar.ArchiveTab.RemoteControls)
}
)
}

Expand Down
2 changes: 2 additions & 0 deletions components/archive/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ dependencies {
implementation(projects.components.bottombar.api)
implementation(projects.components.rootscreen.api)

implementation(projects.components.remoteControls.main.api)

implementation(projects.components.bridge.dao.api)
implementation(projects.components.bridge.synchronization.api)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.flipperdevices.archive.impl.model.toArchiveNavigationStack
import com.flipperdevices.bottombar.handlers.ResetTabDecomposeHandler
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.deeplink.model.Deeplink
import com.flipperdevices.remotecontrols.api.RemoteControlsScreenDecomposeComponent
import com.flipperdevices.ui.decompose.DecomposeComponent
import com.flipperdevices.ui.decompose.DecomposeOnBackParameter
import com.flipperdevices.ui.decompose.findComponentByConfig
Expand All @@ -22,14 +23,16 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import me.gulya.anvil.assisted.ContributesAssistedFactory

@Suppress("LongParameterList")
@ContributesAssistedFactory(AppGraph::class, ArchiveDecomposeComponent.Factory::class)
class ArchiveDecomposeComponentImpl @AssistedInject constructor(
@Assisted componentContext: ComponentContext,
@Assisted deeplink: Deeplink.BottomBar.ArchiveTab?,
@Assisted private val onBack: DecomposeOnBackParameter,
private val openCategoryFactory: CategoryDecomposeComponent.Factory,
private val searchFactory: SearchDecomposeComponent.Factory,
private val archiveScreenFactory: ArchiveScreenDecomposeComponentImpl.Factory
private val archiveScreenFactory: ArchiveScreenDecomposeComponentImpl.Factory,
private val remoteControlsComponentFactory: RemoteControlsScreenDecomposeComponent.Factory,
) : ArchiveDecomposeComponent<ArchiveNavigationConfig>(),
ComponentContext by componentContext,
ResetTabDecomposeHandler {
Expand Down Expand Up @@ -64,6 +67,11 @@ class ArchiveDecomposeComponentImpl @AssistedInject constructor(
onItemSelected = null,
onBack = { navigation.popOr(onBack::invoke) }
)

is ArchiveNavigationConfig.RemoteControls -> remoteControlsComponentFactory(
componentContext = componentContext,
onBack = { navigation.popOr(onBack::invoke) }
)
}

override fun handleDeeplink(deeplink: Deeplink.BottomBar.ArchiveTab) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ sealed class ArchiveNavigationConfig {

@Serializable
data object OpenSearch : ArchiveNavigationConfig()

@Serializable
data object RemoteControls : ArchiveNavigationConfig()
}

fun Deeplink.BottomBar.ArchiveTab?.toArchiveNavigationStack(): List<ArchiveNavigationConfig> {
Expand All @@ -36,6 +39,10 @@ fun Deeplink.BottomBar.ArchiveTab?.toArchiveNavigationStack(): List<ArchiveNavig

null -> {
}

Deeplink.BottomBar.ArchiveTab.RemoteControls -> {
stack.add(ArchiveNavigationConfig.RemoteControls)
}
}
return stack
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ sealed interface Deeplink {

@Serializable
sealed interface ArchiveTab : BottomBar {
@Serializable
data object RemoteControls : ArchiveTab

@Serializable
sealed interface ArchiveCategory : ArchiveTab {
val category: FlipperKeyType?
Expand Down
1 change: 1 addition & 0 deletions components/remote-controls/core-ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
implementation(projects.components.core.ui.theme)
implementation(projects.components.core.ui.ktx)
implementation(projects.components.core.ui.res)
implementation(projects.components.core.ui.dialog)

implementation(projects.components.remoteControls.apiBackend)
implementation(projects.components.remoteControls.coreModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.impl.grid.remote.composable.components.RemoteGridComposableContent
import com.flipperdevices.remotecontrols.impl.grid.remote.composable.components.RemoteGridTopBar
import com.flipperdevices.remotecontrols.impl.grid.remote.presentation.decompose.RemoteGridComponent

@Composable
fun RemoteGridComposable(
remoteGridComponent: RemoteGridComponent,
flipperDispatchDialogApi: FlipperDispatchDialogApi,
modifier: Modifier = Modifier
) {
val coroutineScope = rememberCoroutineScope()
Expand All @@ -43,8 +45,11 @@ fun RemoteGridComposable(
content = { scaffoldPaddings ->
RemoteGridComposableContent(
remoteGridComponent = remoteGridComponent,
flipperDispatchDialogApi = flipperDispatchDialogApi,
model = model,
modifier = Modifier.padding(scaffoldPaddings).navigationBarsPadding()
modifier = Modifier
.padding(scaffoldPaddings)
.navigationBarsPadding()
)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,23 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.flipperdevices.core.ui.dialog.composable.busy.ComposableFlipperBusy
import com.flipperdevices.core.ui.theme.LocalPallet
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.core.ui.theme.LocalTypography
import com.flipperdevices.ifrmvp.core.ui.layout.shared.ErrorComposable
import com.flipperdevices.ifrmvp.core.ui.layout.shared.GridPagesContent
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.grid.remote.impl.R
import com.flipperdevices.remotecontrols.impl.grid.remote.composable.util.contentKey
import com.flipperdevices.remotecontrols.impl.grid.remote.presentation.decompose.RemoteGridComponent
import com.flipperdevices.rootscreen.api.LocalRootNavigation
import com.flipperdevices.rootscreen.model.RootScreenConfig

@Composable
internal fun RemoteGridComposableContent(
remoteGridComponent: RemoteGridComponent,
flipperDispatchDialogApi: FlipperDispatchDialogApi,
model: RemoteGridComponent.Model,
modifier: Modifier = Modifier
) {
val rootNavigation = LocalRootNavigation.current
AnimatedContent(
targetState = model,
modifier = modifier,
Expand All @@ -49,15 +47,10 @@ internal fun RemoteGridComposableContent(
}

is RemoteGridComponent.Model.Loaded -> {
if (animatedModel.isFlipperBusy) {
ComposableFlipperBusy(
onDismiss = remoteGridComponent::dismissBusyDialog,
goToRemote = {
remoteGridComponent.dismissBusyDialog()
rootNavigation.push(RootScreenConfig.ScreenStreaming)
}
)
}
flipperDispatchDialogApi.Render(
dialogType = animatedModel.flipperDialog,
onDismiss = remoteGridComponent::dismissDialog,
)
GridPagesContent(
pagesLayout = animatedModel.pagesLayout,
onButtonClick = { _, keyIdentifier ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.flipperdevices.ifrmvp.model.PagesLayout
import com.flipperdevices.infrared.api.InfraredConnectionApi.InfraredEmulateState
import com.flipperdevices.infrared.editor.core.model.InfraredRemote
import com.flipperdevices.keyedit.api.NotSavedFlipperKey
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.api.SaveTempSignalApi
import com.flipperdevices.remotecontrols.api.model.ServerRemoteControlParam
import com.flipperdevices.ui.decompose.DecomposeOnBackParameter
Expand All @@ -23,7 +24,7 @@ interface RemoteGridComponent {

fun pop()

fun dismissBusyDialog()
fun dismissDialog()

fun save()

Expand All @@ -35,7 +36,7 @@ interface RemoteGridComponent {
data class Loaded(
val pagesLayout: PagesLayout,
val remotes: ImmutableList<InfraredRemote>,
val isFlipperBusy: Boolean = false,
val flipperDialog: FlipperDispatchDialogApi.DialogType? = null,
val emulatedKey: IfrKeyIdentifier? = null,
val saveState: SaveTempSignalApi.State,
val connectionState: InfraredEmulateState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class RemoteGridComponentImpl @AssistedInject constructor(
}
).stateIn(coroutineScope, SharingStarted.Eagerly, RemoteGridComponent.Model.Loading())

override fun dismissBusyDialog() {
override fun dismissDialog() {
dispatchSignalApi.dismissBusyDialog()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.childContext
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.keyedit.api.NotSavedFlipperKey
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.api.model.ServerRemoteControlParam
import com.flipperdevices.remotecontrols.grid.remote.api.RemoteGridScreenDecomposeComponent
import com.flipperdevices.remotecontrols.impl.grid.remote.composable.RemoteGridComposable
Expand All @@ -20,17 +21,22 @@ class RemoteGridScreenDecomposeComponentImpl @AssistedInject constructor(
@Assisted param: ServerRemoteControlParam,
@Assisted onBack: DecomposeOnBackParameter,
@Assisted onSaveKey: (NotSavedFlipperKey) -> Unit,
remoteGridComponentFactory: RemoteGridComponent.Factory
remoteGridComponentFactory: RemoteGridComponent.Factory,
flipperDispatchDialogApiFactory: FlipperDispatchDialogApi.Factory,
) : RemoteGridScreenDecomposeComponent(componentContext) {
private val gridComponent = remoteGridComponentFactory.invoke(
componentContext = childContext("GridComponent"),
param = param,
onBack = onBack,
onSaveKey = onSaveKey
)
private val flipperDispatchDialogApi = flipperDispatchDialogApiFactory.invoke(onBack = onBack)

@Composable
override fun Render() {
RemoteGridComposable(gridComponent)
RemoteGridComposable(
remoteGridComponent = gridComponent,
flipperDispatchDialogApi = flipperDispatchDialogApi
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.flipperdevices.remotecontrols.impl.grid.remote.presentation.mapping

import com.flipperdevices.infrared.api.InfraredConnectionApi
import com.flipperdevices.remotecontrols.api.DispatchSignalApi
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi.Companion.toDialogType
import com.flipperdevices.remotecontrols.api.SaveTempSignalApi
import com.flipperdevices.remotecontrols.impl.grid.remote.presentation.decompose.RemoteGridComponent
import com.flipperdevices.remotecontrols.impl.grid.remote.presentation.viewmodel.RemoteGridViewModel
Expand All @@ -23,7 +24,7 @@ internal object GridComponentStateMapper {
RemoteGridComponent.Model.Loaded(
pagesLayout = gridState.pagesLayout,
remotes = gridState.remotes,
isFlipperBusy = dispatchState is DispatchSignalApi.State.FlipperIsBusy,
flipperDialog = dispatchState.toDialogType(),
emulatedKey = (dispatchState as? DispatchSignalApi.State.Emulating)?.ifrKeyIdentifier,
saveState = saveState,
connectionState = connectionState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.ui.unit.dp
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.ifrmvp.core.ui.layout.shared.SharedTopBar
import com.flipperdevices.infrared.api.InfraredConnectionApi.InfraredEmulateState
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.grid.saved.impl.R
import com.flipperdevices.remotecontrols.impl.grid.local.api.LocalGridScreenDecomposeComponent
import com.flipperdevices.remotecontrols.impl.grid.local.composable.components.ComposableInfraredDropDown
Expand All @@ -30,6 +31,7 @@ import com.flipperdevices.remotecontrols.impl.grid.local.presentation.decompose.
@Suppress("LongMethod")
fun LocalGridComposable(
localGridComponent: LocalGridComponent,
flipperDispatchDialogApi: FlipperDispatchDialogApi,
onCallback: (LocalGridScreenDecomposeComponent.Callback) -> Unit,
onShare: () -> Unit,
modifier: Modifier = Modifier
Expand Down Expand Up @@ -78,8 +80,11 @@ fun LocalGridComposable(
content = { scaffoldPaddings ->
LocalGridComposableContent(
localGridComponent = localGridComponent,
flipperDispatchDialogApi = flipperDispatchDialogApi,
model = model,
modifier = Modifier.padding(scaffoldPaddings).navigationBarsPadding()
modifier = Modifier
.padding(scaffoldPaddings)
.navigationBarsPadding()
)
Box(
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,22 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.flipperdevices.core.ui.dialog.composable.busy.ComposableFlipperBusy
import com.flipperdevices.core.ui.theme.LocalPallet
import com.flipperdevices.core.ui.theme.LocalPalletV2
import com.flipperdevices.core.ui.theme.LocalTypography
import com.flipperdevices.ifrmvp.core.ui.layout.shared.GridPagesContent
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.remotecontrols.grid.saved.impl.R
import com.flipperdevices.remotecontrols.impl.grid.local.composable.util.contentKey
import com.flipperdevices.remotecontrols.impl.grid.local.presentation.decompose.LocalGridComponent
import com.flipperdevices.rootscreen.api.LocalRootNavigation
import com.flipperdevices.rootscreen.model.RootScreenConfig

@Composable
internal fun LocalGridComposableContent(
localGridComponent: LocalGridComponent,
flipperDispatchDialogApi: FlipperDispatchDialogApi,
model: LocalGridComponent.Model,
modifier: Modifier = Modifier
) {
val rootNavigation = LocalRootNavigation.current
AnimatedContent(
targetState = model,
modifier = modifier,
Expand All @@ -44,15 +42,10 @@ internal fun LocalGridComposableContent(
LocalGridComponent.Model.Error -> Unit

is LocalGridComponent.Model.Loaded -> {
if (animatedModel.isFlipperBusy) {
ComposableFlipperBusy(
onDismiss = localGridComponent::dismissBusyDialog,
goToRemote = {
localGridComponent.dismissBusyDialog()
rootNavigation.push(RootScreenConfig.ScreenStreaming)
}
)
}
flipperDispatchDialogApi.Render(
dialogType = animatedModel.flipperDialog,
onDismiss = localGridComponent::dismissDialog
)
GridPagesContent(
pagesLayout = animatedModel.pagesLayout,
onButtonClick = { _, keyIdentifier ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.flipperdevices.ifrmvp.model.IfrKeyIdentifier
import com.flipperdevices.ifrmvp.model.PagesLayout
import com.flipperdevices.infrared.api.InfraredConnectionApi.InfraredEmulateState
import com.flipperdevices.infrared.editor.core.model.InfraredRemote
import com.flipperdevices.remotecontrols.api.FlipperDispatchDialogApi
import com.flipperdevices.ui.decompose.DecomposeOnBackParameter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.CoroutineScope
Expand All @@ -17,14 +18,14 @@ interface LocalGridComponent {
fun onRename(onEndAction: (FlipperKeyPath) -> Unit)
fun onDelete(onEndAction: () -> Unit)
fun pop()
fun dismissBusyDialog()
fun dismissDialog()

sealed interface Model {
data object Loading : Model
data class Loaded(
val pagesLayout: PagesLayout,
val remotes: ImmutableList<InfraredRemote>,
val isFlipperBusy: Boolean,
val flipperDialog: FlipperDispatchDialogApi.DialogType? = null,
val emulatedKey: IfrKeyIdentifier?,
val connectionState: InfraredEmulateState,
val keyPath: FlipperKeyPath
Expand Down
Loading

0 comments on commit e6f2aff

Please sign in to comment.