Loading feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/DropDownDrawer.kt +3 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import androidx.drawerlayout.widget.DrawerLayout import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.ui.theme.api.FeatureThemeProvider import net.thunderbird.feature.navigation.drawer.api.NavigationDrawer import net.thunderbird.feature.navigation.drawer.api.R Loading @@ -32,6 +33,7 @@ class DropDownDrawer( ) : NavigationDrawer, KoinComponent { private val themeProvider: FeatureThemeProvider by inject() private val featureFlagProvider: FeatureFlagProvider by inject() private val drawer: DrawerLayout = parent.findViewById(R.id.navigation_drawer_layout) private val drawerContent: ComposeView = parent.findViewById(R.id.navigation_drawer_content) Loading @@ -52,6 +54,7 @@ class DropDownDrawer( openUnifiedFolder = openUnifiedFolder, openManageFolders = openManageFolders, openSettings = openSettings, featureFlagProvider = featureFlagProvider, closeDrawer = { close() }, ) } Loading feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/DrawerView.kt +22 −4 Original line number Diff line number Diff line Loading @@ -2,14 +2,19 @@ package net.thunderbird.feature.navigation.drawer.dropdown.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.core.ui.compose.designsystem.molecule.PullToRefreshBox import net.thunderbird.core.featureflag.FeatureFlagKey import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.featureflag.FeatureFlagResult import net.thunderbird.feature.navigation.drawer.dropdown.FolderDrawerState import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Effect import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Event import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.ViewModel import org.koin.androidx.compose.koinViewModel @Suppress("LongParameterList") @Composable internal fun DrawerView( drawerState: FolderDrawerState, Loading @@ -19,6 +24,7 @@ internal fun DrawerView( openManageFolders: () -> Unit, openSettings: () -> Unit, closeDrawer: () -> Unit, featureFlagProvider: FeatureFlagProvider, viewModel: ViewModel = koinViewModel<DrawerViewModel>(), ) { val (state, dispatch) = viewModel.observe { effect -> Loading @@ -28,6 +34,7 @@ internal fun DrawerView( effect.accountId, effect.folderId, ) Effect.OpenUnifiedFolder -> openUnifiedFolder() is Effect.OpenManageFolders -> openManageFolders() is Effect.OpenSettings -> openSettings() Loading @@ -35,6 +42,10 @@ internal fun DrawerView( } } val isDropdownDrawerEnabled = remember { featureFlagProvider.provide(FeatureFlagKey("enable_dropdown_drawer_ui")) == FeatureFlagResult.Enabled } LaunchedEffect(drawerState.selectedAccountUuid) { dispatch(Event.SelectAccount(drawerState.selectedAccountUuid)) } Loading @@ -47,9 +58,16 @@ internal fun DrawerView( isRefreshing = state.value.isLoading, onRefresh = { dispatch(Event.OnSyncAccount) }, ) { if (isDropdownDrawerEnabled) { DrawerContent( state = state.value, onEvent = { dispatch(it) }, ) } else { SideRailDrawerContent( state = state.value, onEvent = { dispatch(it) }, ) } } } feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/SideRailDrawerContent.kt 0 → 100644 +88 −0 Original line number Diff line number Diff line package net.thunderbird.feature.navigation.drawer.dropdown.ui import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import app.k9mail.core.ui.compose.designsystem.atom.DividerHorizontal import app.k9mail.core.ui.compose.designsystem.atom.Surface import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Event import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.State import net.thunderbird.feature.navigation.drawer.dropdown.ui.account.AccountList import net.thunderbird.feature.navigation.drawer.dropdown.ui.account.AccountView import net.thunderbird.feature.navigation.drawer.dropdown.ui.common.DRAWER_WIDTH import net.thunderbird.feature.navigation.drawer.dropdown.ui.common.getAdditionalWidth import net.thunderbird.feature.navigation.drawer.dropdown.ui.folder.FolderList import net.thunderbird.feature.navigation.drawer.dropdown.ui.setting.SettingList @Composable internal fun SideRailDrawerContent( state: State, onEvent: (Event) -> Unit, modifier: Modifier = Modifier, ) { val additionalWidth = getAdditionalWidth() Surface( modifier = modifier .windowInsetsPadding(WindowInsets.statusBars) .width(DRAWER_WIDTH + additionalWidth) .fillMaxHeight() .testTag("DrawerContent"), ) { val selectedAccount = state.accounts.firstOrNull { it.id == state.selectedAccountId } Column { selectedAccount?.let { AccountView( account = selectedAccount, onClick = { onEvent(Event.OnAccountViewClick(selectedAccount)) }, showAvatar = state.config.showAccountSelector, ) DividerHorizontal() } Row { AnimatedVisibility( visible = state.config.showAccountSelector, ) { AccountList( accounts = state.accounts, selectedAccount = selectedAccount, onAccountClick = { onEvent(Event.OnAccountClick(it)) }, onSyncAllAccountsClick = { onEvent(Event.OnSyncAllAccounts) }, onSettingsClick = { onEvent(Event.OnSettingsClick) }, ) } Column( modifier = Modifier .weight(1f) .fillMaxSize(), ) { FolderList( rootFolder = state.rootFolder, selectedFolder = state.folders.firstOrNull { it.id == state.selectedFolderId }, onFolderClick = { folder -> onEvent(Event.OnFolderClick(folder)) }, showStarredCount = state.config.showStarredCount, modifier = Modifier.weight(1f), ) DividerHorizontal() SettingList( onAccountSelectorClick = { onEvent(Event.OnAccountSelectorClick) }, onManageFoldersClick = { onEvent(Event.OnManageFoldersClick) }, showAccountSelector = state.config.showAccountSelector, ) } } } } } feature/navigation/drawer/dropdown/src/test/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/DrawerViewKtTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = { counter.openManageFoldersCount++ }, openSettings = { counter.openSettingsCount++ }, closeDrawer = { counter.closeDrawerCount++ }, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading Loading @@ -85,6 +86,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = { }, openSettings = { }, closeDrawer = { }, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading Loading @@ -122,6 +124,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = {}, openSettings = {}, closeDrawer = {}, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading feature/navigation/drawer/dropdown/src/test/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/FakeFeatureFlagProvider.kt 0 → 100644 +17 −0 Original line number Diff line number Diff line package net.thunderbird.feature.navigation.drawer.dropdown.ui import net.thunderbird.core.featureflag.FeatureFlagKey import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.featureflag.FeatureFlagResult class FakeFeatureFlagProvider( private val isEnabled: Boolean = false, ) : FeatureFlagProvider { override fun provide(key: FeatureFlagKey): FeatureFlagResult { return if (isEnabled) { FeatureFlagResult.Enabled } else { FeatureFlagResult.Disabled } } } Loading
feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/DropDownDrawer.kt +3 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import androidx.drawerlayout.widget.DrawerLayout import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.ui.theme.api.FeatureThemeProvider import net.thunderbird.feature.navigation.drawer.api.NavigationDrawer import net.thunderbird.feature.navigation.drawer.api.R Loading @@ -32,6 +33,7 @@ class DropDownDrawer( ) : NavigationDrawer, KoinComponent { private val themeProvider: FeatureThemeProvider by inject() private val featureFlagProvider: FeatureFlagProvider by inject() private val drawer: DrawerLayout = parent.findViewById(R.id.navigation_drawer_layout) private val drawerContent: ComposeView = parent.findViewById(R.id.navigation_drawer_content) Loading @@ -52,6 +54,7 @@ class DropDownDrawer( openUnifiedFolder = openUnifiedFolder, openManageFolders = openManageFolders, openSettings = openSettings, featureFlagProvider = featureFlagProvider, closeDrawer = { close() }, ) } Loading
feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/DrawerView.kt +22 −4 Original line number Diff line number Diff line Loading @@ -2,14 +2,19 @@ package net.thunderbird.feature.navigation.drawer.dropdown.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.core.ui.compose.designsystem.molecule.PullToRefreshBox import net.thunderbird.core.featureflag.FeatureFlagKey import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.featureflag.FeatureFlagResult import net.thunderbird.feature.navigation.drawer.dropdown.FolderDrawerState import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Effect import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Event import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.ViewModel import org.koin.androidx.compose.koinViewModel @Suppress("LongParameterList") @Composable internal fun DrawerView( drawerState: FolderDrawerState, Loading @@ -19,6 +24,7 @@ internal fun DrawerView( openManageFolders: () -> Unit, openSettings: () -> Unit, closeDrawer: () -> Unit, featureFlagProvider: FeatureFlagProvider, viewModel: ViewModel = koinViewModel<DrawerViewModel>(), ) { val (state, dispatch) = viewModel.observe { effect -> Loading @@ -28,6 +34,7 @@ internal fun DrawerView( effect.accountId, effect.folderId, ) Effect.OpenUnifiedFolder -> openUnifiedFolder() is Effect.OpenManageFolders -> openManageFolders() is Effect.OpenSettings -> openSettings() Loading @@ -35,6 +42,10 @@ internal fun DrawerView( } } val isDropdownDrawerEnabled = remember { featureFlagProvider.provide(FeatureFlagKey("enable_dropdown_drawer_ui")) == FeatureFlagResult.Enabled } LaunchedEffect(drawerState.selectedAccountUuid) { dispatch(Event.SelectAccount(drawerState.selectedAccountUuid)) } Loading @@ -47,9 +58,16 @@ internal fun DrawerView( isRefreshing = state.value.isLoading, onRefresh = { dispatch(Event.OnSyncAccount) }, ) { if (isDropdownDrawerEnabled) { DrawerContent( state = state.value, onEvent = { dispatch(it) }, ) } else { SideRailDrawerContent( state = state.value, onEvent = { dispatch(it) }, ) } } }
feature/navigation/drawer/dropdown/src/main/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/SideRailDrawerContent.kt 0 → 100644 +88 −0 Original line number Diff line number Diff line package net.thunderbird.feature.navigation.drawer.dropdown.ui import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import app.k9mail.core.ui.compose.designsystem.atom.DividerHorizontal import app.k9mail.core.ui.compose.designsystem.atom.Surface import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.Event import net.thunderbird.feature.navigation.drawer.dropdown.ui.DrawerContract.State import net.thunderbird.feature.navigation.drawer.dropdown.ui.account.AccountList import net.thunderbird.feature.navigation.drawer.dropdown.ui.account.AccountView import net.thunderbird.feature.navigation.drawer.dropdown.ui.common.DRAWER_WIDTH import net.thunderbird.feature.navigation.drawer.dropdown.ui.common.getAdditionalWidth import net.thunderbird.feature.navigation.drawer.dropdown.ui.folder.FolderList import net.thunderbird.feature.navigation.drawer.dropdown.ui.setting.SettingList @Composable internal fun SideRailDrawerContent( state: State, onEvent: (Event) -> Unit, modifier: Modifier = Modifier, ) { val additionalWidth = getAdditionalWidth() Surface( modifier = modifier .windowInsetsPadding(WindowInsets.statusBars) .width(DRAWER_WIDTH + additionalWidth) .fillMaxHeight() .testTag("DrawerContent"), ) { val selectedAccount = state.accounts.firstOrNull { it.id == state.selectedAccountId } Column { selectedAccount?.let { AccountView( account = selectedAccount, onClick = { onEvent(Event.OnAccountViewClick(selectedAccount)) }, showAvatar = state.config.showAccountSelector, ) DividerHorizontal() } Row { AnimatedVisibility( visible = state.config.showAccountSelector, ) { AccountList( accounts = state.accounts, selectedAccount = selectedAccount, onAccountClick = { onEvent(Event.OnAccountClick(it)) }, onSyncAllAccountsClick = { onEvent(Event.OnSyncAllAccounts) }, onSettingsClick = { onEvent(Event.OnSettingsClick) }, ) } Column( modifier = Modifier .weight(1f) .fillMaxSize(), ) { FolderList( rootFolder = state.rootFolder, selectedFolder = state.folders.firstOrNull { it.id == state.selectedFolderId }, onFolderClick = { folder -> onEvent(Event.OnFolderClick(folder)) }, showStarredCount = state.config.showStarredCount, modifier = Modifier.weight(1f), ) DividerHorizontal() SettingList( onAccountSelectorClick = { onEvent(Event.OnAccountSelectorClick) }, onManageFoldersClick = { onEvent(Event.OnManageFoldersClick) }, showAccountSelector = state.config.showAccountSelector, ) } } } } }
feature/navigation/drawer/dropdown/src/test/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/DrawerViewKtTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = { counter.openManageFoldersCount++ }, openSettings = { counter.openSettingsCount++ }, closeDrawer = { counter.closeDrawerCount++ }, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading Loading @@ -85,6 +86,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = { }, openSettings = { }, closeDrawer = { }, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading Loading @@ -122,6 +124,7 @@ internal class DrawerViewKtTest : ComposeTest() { openManageFolders = {}, openSettings = {}, closeDrawer = {}, featureFlagProvider = FakeFeatureFlagProvider(isEnabled = true), viewModel = viewModel, ) } Loading
feature/navigation/drawer/dropdown/src/test/kotlin/net/thunderbird/feature/navigation/drawer/dropdown/ui/FakeFeatureFlagProvider.kt 0 → 100644 +17 −0 Original line number Diff line number Diff line package net.thunderbird.feature.navigation.drawer.dropdown.ui import net.thunderbird.core.featureflag.FeatureFlagKey import net.thunderbird.core.featureflag.FeatureFlagProvider import net.thunderbird.core.featureflag.FeatureFlagResult class FakeFeatureFlagProvider( private val isEnabled: Boolean = false, ) : FeatureFlagProvider { override fun provide(key: FeatureFlagKey): FeatureFlagResult { return if (isEnabled) { FeatureFlagResult.Enabled } else { FeatureFlagResult.Disabled } } }