Skip to content

Commit 8f27f4d

Browse files
committed
Merge branch 'main' into configure_notification_actions
2 parents 3ac43eb + 7fd9bd5 commit 8f27f4d

File tree

47 files changed

+1475
-34
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1475
-34
lines changed

app-common/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ dependencies {
4040

4141
implementation(projects.feature.account.avatar.api)
4242
implementation(projects.feature.account.avatar.impl)
43+
implementation(projects.feature.account.settings.api)
4344
implementation(projects.feature.account.setup)
4445
implementation(projects.feature.mail.account.api)
4546
implementation(projects.feature.mail.message.composer)

app-common/src/main/kotlin/net/thunderbird/app/common/account/AppCommonAccountModule.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import kotlinx.collections.immutable.ImmutableList
66
import kotlinx.collections.immutable.toImmutableList
77
import net.thunderbird.app.common.account.data.DefaultAccountProfileLocalDataSource
88
import net.thunderbird.app.common.account.data.DefaultLegacyAccountManager
9+
import net.thunderbird.app.common.account.data.DefaultLegacyAccountRepository
910
import net.thunderbird.core.android.account.AccountDefaultsProvider
1011
import net.thunderbird.core.android.account.LegacyAccount
1112
import net.thunderbird.core.android.account.LegacyAccountManager
13+
import net.thunderbird.core.android.account.LegacyAccountRepository
1214
import net.thunderbird.feature.account.avatar.AvatarIcon
1315
import net.thunderbird.feature.account.avatar.AvatarIconCatalog
1416
import net.thunderbird.feature.account.avatar.AvatarMonogramCreator
@@ -73,6 +75,12 @@ internal val appCommonAccountModule = module {
7375
DefaultAvatarMonogramCreator()
7476
}
7577

78+
factory<LegacyAccountRepository> {
79+
DefaultLegacyAccountRepository(
80+
accountManager = get(),
81+
)
82+
}
83+
7684
factory<AccountSetupExternalContract.AccountCreator> {
7785
AccountCreator(
7886
accountColorPicker = get(),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.thunderbird.app.common.account.data
2+
3+
import net.thunderbird.core.android.account.LegacyAccount
4+
import net.thunderbird.core.android.account.LegacyAccountManager
5+
import net.thunderbird.core.android.account.LegacyAccountRepository
6+
import net.thunderbird.feature.account.AccountId
7+
8+
class DefaultLegacyAccountRepository(private val accountManager: LegacyAccountManager) : LegacyAccountRepository {
9+
override fun getById(id: AccountId) = accountManager.getById(id)
10+
11+
override suspend fun update(account: LegacyAccount) {
12+
accountManager.update(account)
13+
}
14+
}

app-common/src/main/kotlin/net/thunderbird/app/common/startup/StartupRouter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package net.thunderbird.app.common.startup
33
import android.app.Activity
44
import app.k9mail.feature.launcher.FeatureLauncherActivity
55
import app.k9mail.feature.launcher.FeatureLauncherTarget
6-
import com.fsck.k9.account.BackgroundAccountRemover
76
import com.fsck.k9.activity.MessageHomeActivity
87
import net.thunderbird.core.android.account.LegacyAccount
98
import net.thunderbird.core.android.account.LegacyAccountManager
9+
import net.thunderbird.feature.account.settings.api.BackgroundAccountRemover
1010

1111
interface StartupRouter {
1212
fun routeToNextScreen(activity: Activity)

app-ui-catalog/src/main/kotlin/net/thunderbird/ui/catalog/ui/page/atom/items/SelectionControlItems.kt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
package net.thunderbird.ui.catalog.ui.page.atom.items
22

3+
import androidx.compose.foundation.clickable
34
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Row
46
import androidx.compose.foundation.layout.fillMaxWidth
57
import androidx.compose.foundation.layout.padding
68
import androidx.compose.foundation.lazy.grid.LazyGridScope
9+
import androidx.compose.material3.ExperimentalMaterial3Api
10+
import androidx.compose.material3.ExposedDropdownMenuDefaults
711
import androidx.compose.runtime.Composable
12+
import androidx.compose.runtime.getValue
13+
import androidx.compose.runtime.mutableStateOf
14+
import androidx.compose.runtime.remember
15+
import androidx.compose.runtime.setValue
816
import androidx.compose.ui.Alignment
917
import androidx.compose.ui.Modifier
1018
import app.k9mail.core.ui.compose.designsystem.atom.Checkbox
19+
import app.k9mail.core.ui.compose.designsystem.atom.DropdownMenuBox
1120
import app.k9mail.core.ui.compose.designsystem.atom.RadioGroup
1221
import app.k9mail.core.ui.compose.designsystem.atom.Switch
1322
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodySmall
@@ -18,6 +27,7 @@ import net.thunderbird.ui.catalog.ui.page.common.list.defaultItem
1827
import net.thunderbird.ui.catalog.ui.page.common.list.defaultItemPadding
1928
import net.thunderbird.ui.catalog.ui.page.common.list.sectionHeaderItem
2029

30+
@OptIn(ExperimentalMaterial3Api::class)
2131
@Suppress("LongMethod")
2232
fun LazyGridScope.selectionControlItems() {
2333
sectionHeaderItem(text = "Checkbox")
@@ -84,6 +94,46 @@ fun LazyGridScope.selectionControlItems() {
8494
)
8595
}
8696
}
97+
98+
sectionHeaderItem(text = "Dropdown Menu")
99+
defaultItem {
100+
Column(
101+
horizontalAlignment = Alignment.CenterHorizontally,
102+
modifier = Modifier
103+
.padding(defaultItemPadding()),
104+
) {
105+
var expanded by remember { mutableStateOf(false) }
106+
val options = persistentListOf(
107+
"Option 1",
108+
"Option 2",
109+
"Option 3",
110+
"Option 4",
111+
)
112+
var selectedOption by remember { mutableStateOf(options[0]) }
113+
114+
DropdownMenuBox(
115+
expanded = expanded,
116+
onExpandedChange = { shouldExpand ->
117+
expanded = shouldExpand
118+
},
119+
options = options,
120+
onItemSelected = {
121+
expanded = false
122+
selectedOption = it
123+
},
124+
) {
125+
Row(
126+
modifier = Modifier.clickable(onClick = { expanded = true }),
127+
verticalAlignment = Alignment.CenterVertically,
128+
) {
129+
TextTitleMedium(
130+
text = selectedOption,
131+
)
132+
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
133+
}
134+
}
135+
}
136+
}
87137
}
88138

89139
private fun LazyGridScope.captionItem(

build-plugin/plugin/src/main/kotlin/net/thunderbird/gradle/plugin/app/versioning/VersioningPlugin.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ class VersioningPlugin : Plugin<Project> {
3434
val printVersionInfoTaskName = "printVersionInfo$variantName"
3535

3636
tasks.register<PrintVersionInfoTask>(printVersionInfoTaskName) {
37-
val versionInfo = getVersionInfo(variant).get()
37+
val versionInfoProvider = getVersionInfo(variant)
3838

3939
applicationId = variant.applicationId
4040
applicationLabel = getApplicationLabel(variant)
41-
versionCode = versionInfo.versionCode
42-
versionName = versionInfo.versionName
43-
versionNameSuffix = versionInfo.versionNameSuffix
41+
versionCode = versionInfoProvider.map { it.versionCode }
42+
versionName = versionInfoProvider.map { it.versionName }
43+
versionNameSuffix = versionInfoProvider.map { it.versionNameSuffix }
4444

4545
// Set outputFile only if provided via -PoutputFile=...
4646
project.findProperty("outputFile")?.toString()?.let { path ->
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.thunderbird.core.android.account
2+
3+
import kotlinx.coroutines.flow.Flow
4+
import net.thunderbird.feature.account.AccountId
5+
6+
interface LegacyAccountRepository {
7+
/**
8+
* Returns a flow of the account with the specified [id].
9+
*
10+
* @param id The ID of the account.
11+
*/
12+
fun getById(id: AccountId): Flow<LegacyAccount?>
13+
14+
/**
15+
* Updates the specified [account].
16+
*
17+
* @param account The account to update.
18+
*/
19+
suspend fun update(account: LegacyAccount)
20+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package app.k9mail.core.ui.compose.designsystem.atom
2+
3+
import androidx.compose.material3.ExperimentalMaterial3Api
4+
import androidx.compose.material3.ExposedDropdownMenuDefaults
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.ui.Modifier
7+
import kotlinx.collections.immutable.ImmutableList
8+
import androidx.compose.material3.DropdownMenu as Material3DropdownMenu
9+
import androidx.compose.material3.DropdownMenuItem as Material3DropdownMenuItem
10+
import androidx.compose.material3.ExposedDropdownMenuBox as Material3ExposedDropdownMenuBox
11+
import androidx.compose.material3.Text as Material3Text
12+
13+
@OptIn(ExperimentalMaterial3Api::class)
14+
@Composable
15+
fun <T> DropdownMenuBox(
16+
expanded: Boolean,
17+
onExpandedChange: (Boolean) -> Unit,
18+
options: ImmutableList<T>,
19+
onItemSelected: (T) -> Unit,
20+
modifier: Modifier = Modifier,
21+
enabled: Boolean = true,
22+
optionToString: (T) -> String = { it.toString() },
23+
anchorContent: @Composable (expanded: Boolean) -> Unit,
24+
) {
25+
Material3ExposedDropdownMenuBox(
26+
expanded = expanded,
27+
onExpandedChange = {
28+
if (enabled) {
29+
onExpandedChange(expanded)
30+
}
31+
},
32+
modifier = modifier,
33+
) {
34+
anchorContent(expanded)
35+
36+
Material3DropdownMenu(
37+
expanded = expanded,
38+
onDismissRequest = { onExpandedChange(false) },
39+
) {
40+
options.forEach { option ->
41+
Material3DropdownMenuItem(
42+
text = {
43+
Material3Text(text = optionToString(option))
44+
},
45+
onClick = {
46+
onItemSelected(option)
47+
},
48+
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
49+
)
50+
}
51+
}
52+
}
53+
}

core/ui/compose/designsystem/src/main/kotlin/net/thunderbird/core/ui/compose/designsystem/atom/icon/Icons.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.compose.material.icons.outlined.Info
2828
import androidx.compose.material.icons.outlined.KeyboardArrowDown
2929
import androidx.compose.material.icons.outlined.KeyboardArrowUp
3030
import androidx.compose.material.icons.outlined.Menu
31+
import androidx.compose.material.icons.outlined.MoreVert
3132
import androidx.compose.material.icons.outlined.Report
3233
import androidx.compose.material.icons.outlined.Security
3334
import androidx.compose.material.icons.outlined.Settings
@@ -138,6 +139,7 @@ object Icons {
138139
val KeyboardArrowUp: ImageVector = Icons.Outlined.KeyboardArrowUp
139140

140141
val Menu: ImageVector = Icons.Outlined.Menu
142+
val MoreVert: ImageVector = Icons.Outlined.MoreVert
141143

142144
val OpenInNew: ImageVector = OutlinedOpenInNewIcon
143145
val Outbox: ImageVector = Icons.Filled.Outbox

core/ui/setting/api/src/commonMain/kotlin/net/thunderbird/core/ui/setting/SettingValue.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ sealed interface SettingValue<T> : Setting {
132132
* @param id The unique identifier for the setting.
133133
* @param title A lambda that returns the title of the setting.
134134
* @param description A lambda that returns the description of the setting. Default is null.
135+
* @param displayValueAsSecondaryText When `true`, the currently selected [value]
136+
* will be displayed as secondary text in the UI (e.g., subtitle style).
135137
* @param icon A lambda that returns the icon of the setting as an [ImageVector]. Default is null.
136138
* @param value The currently selected option.
137139
* @param options The list of available options to choose from.
@@ -141,6 +143,7 @@ sealed interface SettingValue<T> : Setting {
141143
val title: () -> String,
142144
val description: () -> String? = { null },
143145
val icon: () -> ImageVector? = { null },
146+
val displayValueAsSecondaryText: Boolean = false,
144147
override val value: SelectOption,
145148
val options: ImmutableList<SelectOption>,
146149
) : SettingValue<SelectOption> {

0 commit comments

Comments
 (0)