0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-19 19:52:14 +02:00

Add SettingList and SettingListItem

This commit is contained in:
Wolf-Martell Montwé 2024-09-16 17:40:34 +02:00
parent a7389ebda6
commit 2a6193721e
No known key found for this signature in database
GPG Key ID: 6D45B21512ACBF72
19 changed files with 255 additions and 18 deletions

View File

@ -0,0 +1,18 @@
package app.k9mail.feature.navigation.drawer.ui.setting
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
@Composable
@Preview(showBackground = true)
fun SettingListItemPreview() {
PreviewWithThemes {
SettingListItem(
label = "Settings",
onClick = {},
imageVector = Icons.Outlined.Settings,
)
}
}

View File

@ -0,0 +1,29 @@
package app.k9mail.feature.navigation.drawer.ui.setting
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
@Composable
@Preview(showBackground = true)
fun SettingListPreview() {
PreviewWithTheme {
SettingList(
onAccountSelectorClick = {},
onManageFoldersClick = {},
showAccountSelector = false,
)
}
}
@Composable
@Preview(showBackground = true)
fun SettingListShowAccountSelectorPreview() {
PreviewWithTheme {
SettingList(
onAccountSelectorClick = {},
onManageFoldersClick = {},
showAccountSelector = true,
)
}
}

View File

@ -17,6 +17,8 @@ class FolderDrawer(
override val parent: AppCompatActivity,
private val openAccount: (account: Account) -> Unit,
private val openFolder: (folderId: Long) -> Unit,
private val openManageFolders: () -> Unit,
private val openSettings: () -> Unit,
createDrawerListener: () -> DrawerLayout.DrawerListener,
) : NavigationDrawer, KoinComponent {
@ -38,6 +40,8 @@ class FolderDrawer(
DrawerView(
openAccount = openAccount,
openFolder = openFolder,
openManageFolders = openManageFolders,
openSettings = openSettings,
closeDrawer = { close() },
)
}

View File

@ -66,7 +66,7 @@ private const val EN_SPACE = "\u2000"
@Suppress("MagicNumber", "TooManyFunctions", "LongParameterList")
class LegacyDrawer(
override val parent: AppCompatActivity,
private val openFolders: () -> Unit,
private val openManageFolders: () -> Unit,
private val openUnifiedInbox: () -> Unit,
private val openFolder: (folderId: Long) -> Unit,
private val openAccount: (account: Account) -> Boolean,
@ -352,7 +352,7 @@ class LegacyDrawer(
private fun handleItemClickListener(drawerItem: IDrawerItem<*>) {
when (drawerItem.identifier) {
DRAWER_ID_PREFERENCES -> openSettings()
DRAWER_ID_FOLDERS -> openFolders()
DRAWER_ID_FOLDERS -> openManageFolders()
DRAWER_ID_UNIFIED_INBOX -> openUnifiedInbox()
else -> {
val folder = drawerItem.tag as Folder

View File

@ -1,19 +1,17 @@
package app.k9mail.feature.navigation.drawer.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
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 app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.navigation.drawer.ui.DrawerContract.Event
import app.k9mail.feature.navigation.drawer.ui.DrawerContract.State
import app.k9mail.feature.navigation.drawer.ui.account.AccountView
import app.k9mail.feature.navigation.drawer.ui.folder.FolderList
import app.k9mail.feature.navigation.drawer.ui.setting.SettingList
@Composable
fun DrawerContent(
@ -28,11 +26,7 @@ fun DrawerContent(
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(
vertical = MainTheme.spacings.oneHalf,
),
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
.fillMaxSize(),
) {
state.selectedAccount?.let {
AccountView(
@ -51,7 +45,16 @@ fun DrawerContent(
onEvent(Event.OnFolderClick(folder))
},
showStarredCount = state.config.showStarredCount,
modifier = Modifier.weight(1f),
)
Column {
DividerHorizontal()
SettingList(
onAccountSelectorClick = { onEvent(Event.OnAccountSelectorClick) },
onManageFoldersClick = { onEvent(Event.OnManageFoldersClick) },
showAccountSelector = state.showAccountSelector,
)
}
}
}
}

View File

@ -23,6 +23,7 @@ interface DrawerContract {
val selectedAccount: DisplayAccount? = null,
val folders: ImmutableList<DisplayAccountFolder> = persistentListOf(),
val selectedFolder: DisplayAccountFolder? = null,
val showAccountSelector: Boolean = false,
val isLoading: Boolean = false,
)
@ -30,12 +31,17 @@ interface DrawerContract {
data class OnAccountClick(val account: DisplayAccount) : Event
data class OnAccountViewClick(val account: DisplayAccount) : Event
data class OnFolderClick(val folder: DisplayAccountFolder) : Event
data object OnAccountSelectorClick : Event
data object OnManageFoldersClick : Event
data object OnSettingsClick : Event
data object OnRefresh : Event
}
sealed interface Effect {
data class OpenAccount(val account: Account) : Effect
data class OpenFolder(val folderId: Long) : Effect
data object OpenManageFolders : Effect
data object OpenSettings : Effect
data object CloseDrawer : Effect
}
}

View File

@ -13,6 +13,8 @@ import org.koin.androidx.compose.koinViewModel
fun DrawerView(
openAccount: (account: Account) -> Unit,
openFolder: (folderId: Long) -> Unit,
openManageFolders: () -> Unit,
openSettings: () -> Unit,
closeDrawer: () -> Unit,
viewModel: ViewModel = koinViewModel<DrawerViewModel>(),
) {
@ -20,6 +22,8 @@ fun DrawerView(
when (effect) {
is Effect.OpenAccount -> openAccount(effect.account)
is Effect.OpenFolder -> openFolder(effect.folderId)
is Effect.OpenManageFolders -> openManageFolders()
is Effect.OpenSettings -> openSettings()
Effect.CloseDrawer -> closeDrawer()
}
}

View File

@ -101,6 +101,10 @@ class DrawerViewModel(
state.value.accounts.nextOrFirst(event.account)!!,
)
}
Event.OnAccountSelectorClick -> updateState { it.copy(showAccountSelector = it.showAccountSelector.not()) }
Event.OnManageFoldersClick -> emitEffect(Effect.OpenManageFolders)
Event.OnSettingsClick -> emitEffect(Effect.OpenSettings)
}
}

View File

@ -30,10 +30,10 @@ fun AccountView(
.height(intrinsicSize = IntrinsicSize.Max)
.clickable(onClick = onClick)
.padding(
top = MainTheme.spacings.default,
top = MainTheme.spacings.double,
start = MainTheme.spacings.double,
end = MainTheme.spacings.triple,
bottom = MainTheme.spacings.oneHalf,
bottom = MainTheme.spacings.double,
),
verticalAlignment = Alignment.CenterVertically,
) {
@ -42,7 +42,7 @@ fun AccountView(
modifier = Modifier
.fillMaxHeight()
.padding(
end = MainTheme.spacings.default,
end = MainTheme.spacings.oneHalf,
),
)
Column(

View File

@ -1,10 +1,12 @@
package app.k9mail.feature.navigation.drawer.ui.folder
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccountFolder
import kotlinx.collections.immutable.ImmutableList
@ -18,7 +20,8 @@ fun FolderList(
) {
LazyColumn(
modifier = modifier
.fillMaxSize(),
.fillMaxWidth(),
contentPadding = PaddingValues(vertical = MainTheme.spacings.default),
) {
items(folders) { folder ->
FolderListItem(

View File

@ -13,15 +13,15 @@ import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccountFolder
fun FolderListItem(
displayFolder: DisplayAccountFolder,
selected: Boolean,
showStarredCount: Boolean,
onClick: (DisplayAccountFolder) -> Unit,
showStarredCount: Boolean,
modifier: Modifier = Modifier,
) {
NavigationDrawerItem(
label = displayFolder.folder.name,
selected = selected,
modifier = modifier,
onClick = { onClick(displayFolder) },
modifier = modifier,
icon = {
Icon(
imageVector = mapFolderIcon(displayFolder.folder.type),

View File

@ -0,0 +1,44 @@
package app.k9mail.feature.navigation.drawer.ui.setting
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
import app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.navigation.drawer.R
@Composable
fun SettingList(
onAccountSelectorClick: () -> Unit,
onManageFoldersClick: () -> Unit,
showAccountSelector: Boolean,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.padding(vertical = MainTheme.spacings.default)
.fillMaxWidth(),
) {
SettingListItem(
label = stringResource(R.string.navigation_drawer_action_manage_folders),
onClick = onManageFoldersClick,
imageVector = Icons.Outlined.FolderManaged,
)
SettingListItem(
label = if (showAccountSelector) {
stringResource(R.string.navigation_drawer_action_hide_accounts)
} else {
stringResource(R.string.navigation_drawer_action_show_accounts)
},
onClick = onAccountSelectorClick,
imageVector = if (showAccountSelector) {
Icons.Outlined.ChevronLeft
} else {
Icons.Outlined.ChevronRight
},
)
}
}

View File

@ -0,0 +1,27 @@
package app.k9mail.feature.navigation.drawer.ui.setting
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
import app.k9mail.core.ui.compose.designsystem.organism.drawer.NavigationDrawerItem
@Composable
fun SettingListItem(
label: String,
onClick: () -> Unit,
imageVector: ImageVector,
modifier: Modifier = Modifier,
) {
NavigationDrawerItem(
label = label,
onClick = onClick,
modifier = modifier,
selected = false,
icon = {
Icon(
imageVector = imageVector,
)
},
)
}

View File

@ -2,6 +2,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="navigation_drawer_action_settings">Settings</string>
<string name="navigation_drawer_action_folders">Manage folders</string>
<string name="navigation_drawer_action_show_accounts">Show accounts</string>
<string name="navigation_drawer_action_hide_accounts">Hide accounts</string>
<string name="navigation_drawer_unified_inbox_title">Unified Inbox</string>
<string name="navigation_drawer_folder_item_badge_count_greater_than_99">99+</string>
<string name="navigation_drawer_folder_item_badge_count_greater_than_1_000">1k+</string>

View File

@ -1,5 +1,6 @@
package app.k9mail.feature.navigation.drawer.domain.usecase
import app.k9mail.feature.navigation.drawer.ui.FakeData
import app.k9mail.legacy.account.Account
import app.k9mail.legacy.message.controller.MessagingControllerMailChecker
import app.k9mail.legacy.message.controller.MessagingListener
@ -27,6 +28,22 @@ class SyncMailTest {
assertThat(result.isSuccess).isEqualTo(true)
}
@Test
fun `should sync mail with account`() = runTest {
val listenerExecutor: (MessagingListener?) -> Unit = { listener ->
listener?.checkMailFinished(null, null)
}
val testSubject = SyncMail(
messagingController = FakeMessagingControllerMailChecker(
listenerExecutor = listenerExecutor,
),
)
val result = testSubject(FakeData.ACCOUNT).first()
assertThat(result.isSuccess).isEqualTo(true)
}
private class FakeMessagingControllerMailChecker(
private val listenerExecutor: (MessagingListener?) -> Unit = {},
) : MessagingControllerMailChecker {

View File

@ -23,6 +23,7 @@ class DrawerStateTest {
selectedAccount = null,
folders = persistentListOf(),
selectedFolder = null,
showAccountSelector = false,
isLoading = false,
),
)

View File

@ -20,12 +20,16 @@ class DrawerViewKtTest : ComposeTest() {
val viewModel = FakeDrawerViewModel(initialState)
var openAccountCounter = 0
var openFolderCounter = 0
var openManageFoldersCounter = 0
var openSettingsCounter = 0
var closeDrawerCounter = 0
setContentWithTheme {
DrawerView(
openAccount = { openAccountCounter++ },
openFolder = { openFolderCounter++ },
openManageFolders = { openManageFoldersCounter++ },
openSettings = { openSettingsCounter++ },
closeDrawer = { closeDrawerCounter++ },
viewModel = viewModel,
)
@ -33,22 +37,48 @@ class DrawerViewKtTest : ComposeTest() {
assertThat(openAccountCounter).isEqualTo(0)
assertThat(openFolderCounter).isEqualTo(0)
assertThat(openManageFoldersCounter).isEqualTo(0)
assertThat(openSettingsCounter).isEqualTo(0)
assertThat(closeDrawerCounter).isEqualTo(0)
viewModel.effect(Effect.OpenAccount(FakeData.ACCOUNT))
assertThat(openAccountCounter).isEqualTo(1)
assertThat(openFolderCounter).isEqualTo(0)
assertThat(openManageFoldersCounter).isEqualTo(0)
assertThat(openSettingsCounter).isEqualTo(0)
assertThat(closeDrawerCounter).isEqualTo(0)
viewModel.effect(Effect.OpenFolder(1))
assertThat(openAccountCounter).isEqualTo(1)
assertThat(openFolderCounter).isEqualTo(1)
assertThat(openManageFoldersCounter).isEqualTo(0)
assertThat(openSettingsCounter).isEqualTo(0)
assertThat(closeDrawerCounter).isEqualTo(0)
viewModel.effect(Effect.OpenManageFolders)
assertThat(openAccountCounter).isEqualTo(1)
assertThat(openFolderCounter).isEqualTo(1)
assertThat(openManageFoldersCounter).isEqualTo(1)
assertThat(openSettingsCounter).isEqualTo(0)
assertThat(closeDrawerCounter).isEqualTo(0)
viewModel.effect(Effect.OpenSettings)
assertThat(openAccountCounter).isEqualTo(1)
assertThat(openFolderCounter).isEqualTo(1)
assertThat(openManageFoldersCounter).isEqualTo(1)
assertThat(openSettingsCounter).isEqualTo(1)
assertThat(closeDrawerCounter).isEqualTo(0)
viewModel.effect(Effect.CloseDrawer)
assertThat(openAccountCounter).isEqualTo(1)
assertThat(openFolderCounter).isEqualTo(1)
assertThat(openManageFoldersCounter).isEqualTo(1)
assertThat(openSettingsCounter).isEqualTo(1)
assertThat(closeDrawerCounter).isEqualTo(1)
}
@ -63,6 +93,8 @@ class DrawerViewKtTest : ComposeTest() {
DrawerView(
openAccount = {},
openFolder = {},
openManageFolders = {},
openSettings = {},
closeDrawer = {},
viewModel = viewModel,
)

View File

@ -4,6 +4,7 @@ import app.k9mail.core.mail.folder.api.Folder
import app.k9mail.core.mail.folder.api.FolderType
import app.k9mail.core.ui.compose.testing.MainDispatcherRule
import app.k9mail.core.ui.compose.testing.mvi.assertThatAndEffectTurbineConsumed
import app.k9mail.core.ui.compose.testing.mvi.assertThatAndStateTurbineConsumed
import app.k9mail.core.ui.compose.testing.mvi.eventStateTest
import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck
import app.k9mail.feature.navigation.drawer.domain.entity.DisplayAccount
@ -229,6 +230,46 @@ class DrawerViewModelTest {
}
}
@Test
fun `should change state when OnAccountSelectorClick event is received`() = runTest {
val testSubject = createTestSubject()
val turbines = turbinesWithInitialStateCheck(testSubject, State())
testSubject.event(Event.OnAccountSelectorClick)
assertThat(turbines.awaitStateItem()).isEqualTo(State(showAccountSelector = true))
testSubject.event(Event.OnAccountSelectorClick)
turbines.assertThatAndStateTurbineConsumed {
isEqualTo(State(showAccountSelector = false))
}
}
@Test
fun `should emit OpenManageFolders effect when OnManageFoldersClick event is received`() = runTest {
val testSubject = createTestSubject()
val turbines = turbinesWithInitialStateCheck(testSubject, State())
testSubject.event(Event.OnManageFoldersClick)
turbines.assertThatAndEffectTurbineConsumed {
isEqualTo(Effect.OpenManageFolders)
}
}
@Test
fun `should emit OpenSettings effect when OnSettingsClick event is received`() = runTest {
val testSubject = createTestSubject()
val turbines = turbinesWithInitialStateCheck(testSubject, State())
testSubject.event(Event.OnSettingsClick)
turbines.assertThatAndEffectTurbineConsumed {
isEqualTo(Effect.OpenSettings)
}
}
private fun createTestSubject(
drawerConfigFlow: Flow<DrawerConfig> = flow { emit(createDrawerConfig()) },
displayAccountsFlow: Flow<List<DisplayAccount>> = flow { emit(emptyList()) },

View File

@ -596,7 +596,7 @@ open class MessageList :
navigationDrawer = LegacyDrawer(
parent = this,
savedInstanceState = savedInstanceState,
openFolders = { launchManageFoldersScreen() },
openManageFolders = { launchManageFoldersScreen() },
openUnifiedInbox = { openUnifiedInbox() },
openFolder = { folderId -> openFolder(folderId) },
openAccount = { account -> openRealAccount(account) },
@ -610,6 +610,8 @@ open class MessageList :
parent = this,
openAccount = { account -> openRealAccount(account) },
openFolder = { folderId -> openFolder(folderId) },
openManageFolders = { launchManageFoldersScreen() },
openSettings = { SettingsActivity.launch(this) },
createDrawerListener = { createDrawerListener() },
)
}