diff --git a/README.md b/README.md index e1ccf2a07..f321f85d4 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ passkeys, and credit card information encrypted entirely on your local device. ### Driven by a modern & intuitive design
- Vault List Screenshot - Item Detail Screenshot - Password Generator Screenshot + Vault List Screenshot + Password Health Screenshot + Two-Factor Authenticator Screenshot
## Features @@ -22,17 +22,17 @@ passkeys, and credit card information encrypted entirely on your local device. * **Local-Only Storage:** Your data will never leave your device. * **Comprehensive Management:** Store passwords, passkeys, and credit cards. * **MFA Support:** Built-in authenticator for TOTP tokens. -* **Advanced Security:** Per-item, industry-standard encryption. +* **Advanced Security:** Per-item, industry-standard encryption & password health scanning. * **Seamless Integration:** System-wide autofill service for all your credentials. ## Download Get the latest version of KeyGo directly from the Play Store or GitHub: -|Platform|Status| -|:------:|:----:| -| Google Play -Store | [Download from Google Play](https://play.google.com/store/apps/details?id=de.davis.passwordmanager) | -|GitHub. | [![GitHub tag](https://img.shields.io/github/release/OffRange/KeyGo?include_prereleases=&sort=semver)](https://github.com/OffRange/KeyGo/releases/)| + +| Platform | Status | +|:-----------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| Google Play Store | [Download from Google Play](https://play.google.com/store/apps/details?id=de.davis.passwordmanager) | +| GitHub | [![GitHub tag](https://img.shields.io/github/release/OffRange/KeyGo?include_prereleases=&sort=semver)](https://github.com/OffRange/KeyGo/releases/) | ## Build it Yourself diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 376955630..c6012031b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,7 +15,7 @@ plugins { } versioning { - minVersion = Version(major = 2, minor = 1) + minVersion = Version(major = 2, minor = 2) } android versionedBy versioning diff --git a/core/ui/src/main/kotlin/de/davis/keygo/core/ui/components/KeyGoMenuDefaults.kt b/core/ui/src/main/kotlin/de/davis/keygo/core/ui/components/KeyGoMenuDefaults.kt new file mode 100644 index 000000000..2fe0cdb05 --- /dev/null +++ b/core/ui/src/main/kotlin/de/davis/keygo/core/ui/components/KeyGoMenuDefaults.kt @@ -0,0 +1,18 @@ +package de.davis.keygo.core.ui.components + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.MenuDefaults +import androidx.compose.material3.SelectableMenuItemColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +object KeyGoMenuDefaults { + + val containerColor: Color + @Composable get() = MaterialTheme.colorScheme.surfaceContainerHighest + + /** Item colors matching [containerColor]; the M3 defaults paint items `surfaceContainerLow`. */ + val selectableItemColors: SelectableMenuItemColors + @Composable + get() = MenuDefaults.selectableItemColors(containerColor = containerColor) +} diff --git a/docs/assets/desktop.png b/docs/assets/desktop.png deleted file mode 100644 index 544af986b..000000000 Binary files a/docs/assets/desktop.png and /dev/null differ diff --git a/docs/assets/feature-graphic.png b/docs/assets/feature-graphic.png index 9153f8637..3486feeec 100644 Binary files a/docs/assets/feature-graphic.png and b/docs/assets/feature-graphic.png differ diff --git a/docs/assets/phone-1.png b/docs/assets/phone-1.png deleted file mode 100644 index 0fdeb88ad..000000000 Binary files a/docs/assets/phone-1.png and /dev/null differ diff --git a/docs/assets/phone-2.png b/docs/assets/phone-2.png deleted file mode 100644 index 0b44581bb..000000000 Binary files a/docs/assets/phone-2.png and /dev/null differ diff --git a/docs/assets/phone-3.png b/docs/assets/phone-3.png deleted file mode 100644 index e41ba5f35..000000000 Binary files a/docs/assets/phone-3.png and /dev/null differ diff --git a/docs/assets/phone-4.png b/docs/assets/phone-4.png deleted file mode 100644 index fb336730b..000000000 Binary files a/docs/assets/phone-4.png and /dev/null differ diff --git a/docs/assets/phone-5.png b/docs/assets/phone-5.png deleted file mode 100644 index cd013daca..000000000 Binary files a/docs/assets/phone-5.png and /dev/null differ diff --git a/docs/assets/phone-6.png b/docs/assets/phone-6.png deleted file mode 100644 index 4127f62ec..000000000 Binary files a/docs/assets/phone-6.png and /dev/null differ diff --git a/docs/assets/phone/01_hero.png b/docs/assets/phone/01_hero.png new file mode 100644 index 000000000..a399a7c48 Binary files /dev/null and b/docs/assets/phone/01_hero.png differ diff --git a/docs/assets/phone/02_password_health.png b/docs/assets/phone/02_password_health.png new file mode 100644 index 000000000..135688405 Binary files /dev/null and b/docs/assets/phone/02_password_health.png differ diff --git a/docs/assets/phone/03_2fa.png b/docs/assets/phone/03_2fa.png new file mode 100644 index 000000000..5f0e048bb Binary files /dev/null and b/docs/assets/phone/03_2fa.png differ diff --git a/docs/assets/phone/04_generator.png b/docs/assets/phone/04_generator.png new file mode 100644 index 000000000..b500e3dbb Binary files /dev/null and b/docs/assets/phone/04_generator.png differ diff --git a/docs/assets/phone/05_vaults.png b/docs/assets/phone/05_vaults.png new file mode 100644 index 000000000..ee8f61683 Binary files /dev/null and b/docs/assets/phone/05_vaults.png differ diff --git a/docs/assets/phone/06_privacy.png b/docs/assets/phone/06_privacy.png new file mode 100644 index 000000000..e2b12fd93 Binary files /dev/null and b/docs/assets/phone/06_privacy.png differ diff --git a/docs/assets/tablet-1.png b/docs/assets/tablet-1.png deleted file mode 100644 index fb8dc022a..000000000 Binary files a/docs/assets/tablet-1.png and /dev/null differ diff --git a/docs/assets/tablet-10in/01_hero.png b/docs/assets/tablet-10in/01_hero.png new file mode 100644 index 000000000..9d1ac193c Binary files /dev/null and b/docs/assets/tablet-10in/01_hero.png differ diff --git a/docs/assets/tablet-10in/02_password_health.png b/docs/assets/tablet-10in/02_password_health.png new file mode 100644 index 000000000..cd4bfecd5 Binary files /dev/null and b/docs/assets/tablet-10in/02_password_health.png differ diff --git a/docs/assets/tablet-10in/03_2fa_generator.png b/docs/assets/tablet-10in/03_2fa_generator.png new file mode 100644 index 000000000..01d3d8133 Binary files /dev/null and b/docs/assets/tablet-10in/03_2fa_generator.png differ diff --git a/docs/assets/tablet-10in/04_privacy.png b/docs/assets/tablet-10in/04_privacy.png new file mode 100644 index 000000000..d2af625a7 Binary files /dev/null and b/docs/assets/tablet-10in/04_privacy.png differ diff --git a/docs/assets/tablet-2.png b/docs/assets/tablet-2.png deleted file mode 100644 index 9d1c0234a..000000000 Binary files a/docs/assets/tablet-2.png and /dev/null differ diff --git a/docs/assets/tablet-7in/01_hero.png b/docs/assets/tablet-7in/01_hero.png new file mode 100644 index 000000000..682c247b1 Binary files /dev/null and b/docs/assets/tablet-7in/01_hero.png differ diff --git a/docs/assets/tablet-7in/02_password_health.png b/docs/assets/tablet-7in/02_password_health.png new file mode 100644 index 000000000..bb7e4a56a Binary files /dev/null and b/docs/assets/tablet-7in/02_password_health.png differ diff --git a/docs/assets/tablet-7in/03_2fa_generator.png b/docs/assets/tablet-7in/03_2fa_generator.png new file mode 100644 index 000000000..a3988f2ce Binary files /dev/null and b/docs/assets/tablet-7in/03_2fa_generator.png differ diff --git a/docs/assets/tablet-7in/04_privacy.png b/docs/assets/tablet-7in/04_privacy.png new file mode 100644 index 000000000..668fc86a5 Binary files /dev/null and b/docs/assets/tablet-7in/04_privacy.png differ diff --git a/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/export/ScheduleComponents.kt b/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/export/ScheduleComponents.kt index 3201ff540..c86d3389c 100644 --- a/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/export/ScheduleComponents.kt +++ b/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/export/ScheduleComponents.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth @@ -31,7 +30,6 @@ import androidx.compose.material.icons.filled.DeleteSweep import androidx.compose.material.icons.filled.Remove import androidx.compose.material.icons.filled.Schedule import androidx.compose.material3.ButtonGroupDefaults -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -78,7 +76,6 @@ import de.davis.keygo.feature.backup.presentation.label import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds -@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable internal fun IntervalPicker( interval: BackupInterval, @@ -115,7 +112,7 @@ internal fun IntervalPicker( 0 -> ButtonGroupDefaults.connectedLeadingButtonShapes() else -> ButtonGroupDefaults.connectedTrailingButtonShapes() }, - colors = OutlinedToggleButtonDefaults.outlinedToggleButtonColors( + colors = OutlinedToggleButtonDefaults.colors( checkedContainerColor = MaterialTheme.colorScheme.primaryContainer, checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer, ) @@ -127,7 +124,6 @@ internal fun IntervalPicker( } } -@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable internal fun RetentionPicker( keepCount: Int, @@ -314,7 +310,6 @@ private fun StepperButton( } } -@OptIn(ExperimentalLayoutApi::class) @Composable private fun StepperValueField( value: Int, diff --git a/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/import/MapColumnsContent.kt b/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/import/MapColumnsContent.kt index 99c1c1879..31b61ae03 100644 --- a/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/import/MapColumnsContent.kt +++ b/feature/backup/src/main/kotlin/de/davis/keygo/feature/backup/presentation/import/MapColumnsContent.kt @@ -6,13 +6,12 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.TableChart -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenu import androidx.compose.material3.ExposedDropdownMenuAnchorType import androidx.compose.material3.ExposedDropdownMenuBox @@ -22,6 +21,7 @@ import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MenuDefaults import androidx.compose.material3.SegmentedListItem +import androidx.compose.material3.SelectableDropdownMenuItem import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -193,7 +193,6 @@ private fun SourceSegment(columnIndex: Int, header: String) { * since all three segments carry the same weight of leading icon. This is the only segment of the * three that is genuinely interactive. */ -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun TypeSegment( selectedType: CsvColumnType?, @@ -254,7 +253,7 @@ private fun TypeSegment( shape = MenuDefaults.standaloneGroupShape, ) { TYPE_OPTIONS.forEachIndexed { index, option -> - DropdownMenuItem( + SelectableDropdownMenuItem( selected = selectedType == option, onClick = { onTypeChange(option) @@ -262,10 +261,18 @@ private fun TypeSegment( }, text = { Text(text = option.displayName) }, leadingIcon = { - Icon(imageVector = option.icon, contentDescription = null) + Icon( + imageVector = option.icon, + modifier = Modifier.size(MenuDefaults.LeadingIconSize), + contentDescription = null, + ) }, selectedLeadingIcon = { - Icon(imageVector = Icons.Default.Check, contentDescription = null) + Icon( + imageVector = Icons.Default.Check, + modifier = Modifier.size(MenuDefaults.LeadingIconSize), + contentDescription = null, + ) }, shapes = MenuDefaults.itemShape(index, TYPE_OPTIONS.size) ) diff --git a/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/KeyGoFormSuggestionField.kt b/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/KeyGoFormSuggestionField.kt index 693d25a00..d6423f9c9 100644 --- a/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/KeyGoFormSuggestionField.kt +++ b/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/KeyGoFormSuggestionField.kt @@ -8,8 +8,6 @@ import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.clearText import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExposedDropdownMenu import androidx.compose.material3.ExposedDropdownMenuAnchorType import androidx.compose.material3.ExposedDropdownMenuBox @@ -23,8 +21,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.ImeAction +import de.davis.keygo.core.ui.components.KeyGoMenuDefaults -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun KeyGoFormSuggestionField( suggestions: Set, @@ -70,7 +68,9 @@ fun KeyGoFormSuggestionField( ExposedDropdownMenu( expanded = expanded, - onDismissRequest = { setExpanded(false) } + onDismissRequest = { setExpanded(false) }, + containerColor = KeyGoMenuDefaults.containerColor, + shape = MenuDefaults.standaloneGroupShape, ) { suggestions.forEachIndexed { index, suggestion -> DropdownMenuItem( diff --git a/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/MenuChip.kt b/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/MenuChip.kt index 36fb61fd0..5b15d9199 100644 --- a/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/MenuChip.kt +++ b/feature/item/core/src/main/kotlin/de/davis/keygo/feature/item/core/presentation/component/MenuChip.kt @@ -10,10 +10,8 @@ import androidx.compose.material.icons.filled.Edit import androidx.compose.material3.DropdownMenuGroup import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuPopup -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.InputChip -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MenuDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -25,9 +23,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import de.davis.keygo.core.ui.components.KeyGoMenuDefaults import de.davis.keygo.feature.item.core.R -@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun MenuChip( chipText: String, @@ -56,7 +54,7 @@ fun MenuChip( ) { DropdownMenuGroup( shapes = MenuDefaults.groupShape(0, 1), - containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, + containerColor = KeyGoMenuDefaults.containerColor, ) { onModifyClick?.let { onModify -> DropdownMenuItem( diff --git a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/component/VaultDropDownMenu.kt b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/component/VaultDropDownMenu.kt index 93bb1c1e6..84395bbcb 100644 --- a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/component/VaultDropDownMenu.kt +++ b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/component/VaultDropDownMenu.kt @@ -4,9 +4,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExposedDropdownMenu import androidx.compose.material3.ExposedDropdownMenuAnchorType import androidx.compose.material3.ExposedDropdownMenuBox @@ -15,6 +12,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MenuDefaults import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.SelectableDropdownMenuItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -25,10 +23,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import de.davis.keygo.core.item.domain.alias.VaultId import de.davis.keygo.core.item.presentation.toImageVector +import de.davis.keygo.core.ui.components.KeyGoMenuDefaults import de.davis.keygo.feature.item.create.R import de.davis.keygo.feature.item.create.presentation.model.VaultsState -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun VaultDropDownMenu( vaultsState: VaultsState, @@ -68,15 +66,14 @@ fun VaultDropDownMenu( ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest, + containerColor = KeyGoMenuDefaults.containerColor, + shape = MenuDefaults.standaloneGroupShape, ) { val optionCount = vaultsState.vaults.size vaultsState.vaults.forEachIndexed { index, metadata -> - DropdownMenuItem( + SelectableDropdownMenuItem( shapes = MenuDefaults.itemShape(index, optionCount), - colors = MenuDefaults.selectableItemColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest, - ), + colors = KeyGoMenuDefaults.selectableItemColors, text = { Text( metadata.name, diff --git a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordContent.kt b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordContent.kt index 1b68c36a2..5c8109fee 100644 --- a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordContent.kt +++ b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordContent.kt @@ -141,7 +141,10 @@ fun GeneratePasswordContent( .fillMaxWidth(), properties = cardProp, ) { - Slider(state = viewModel.sliderState) + Slider( + state = viewModel.sliderState, + onValueChange = { viewModel.sliderState.value = it }, + ) } } diff --git a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordViewModel.kt b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordViewModel.kt index 04e0aae25..83613e8de 100644 --- a/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordViewModel.kt +++ b/feature/item/create/src/main/kotlin/de/davis/keygo/feature/item/create/presentation/password/GeneratePasswordViewModel.kt @@ -1,6 +1,5 @@ package de.davis.keygo.feature.item.create.presentation.password -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SliderState import androidx.compose.runtime.snapshotFlow import androidx.lifecycle.ViewModel @@ -28,14 +27,13 @@ import org.koin.core.annotation.KoinViewModel import kotlin.time.Duration.Companion.milliseconds @KoinViewModel -@OptIn(ExperimentalMaterial3Api::class, FlowPreview::class) +@OptIn(FlowPreview::class) internal class GeneratePasswordViewModel( private val passwordGenerator: PasswordGenerator, private val passwordStrengthEstimator: PasswordStrengthEstimator, ) : ViewModel() { - @OptIn(ExperimentalMaterial3Api::class) - val sliderState = SliderState(value = 10f, valueRange = 8f..100f) + val sliderState = SliderState(value = 10f, trackRange = 8f..100f) private val finalPasswordChannel = Channel() val finalPassword = finalPasswordChannel.receiveAsFlow() @@ -73,7 +71,6 @@ internal class GeneratePasswordViewModel( initialValue = GeneratePasswordUiState(), ) - @OptIn(ExperimentalMaterial3Api::class) fun onEvent(event: GeneratePasswordUiEvent) { when (event) { is GeneratePasswordUiEvent.OnCharacterSetClick -> { diff --git a/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/MoveVaultDialog.kt b/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/MoveVaultDialog.kt index adc6a0fa7..4d7a8a621 100644 --- a/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/MoveVaultDialog.kt +++ b/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/MoveVaultDialog.kt @@ -13,9 +13,6 @@ import androidx.compose.material.icons.filled.Check import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialogDefaults import androidx.compose.material3.Button -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExposedDropdownMenu import androidx.compose.material3.ExposedDropdownMenuAnchorType import androidx.compose.material3.ExposedDropdownMenuBox @@ -28,6 +25,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MenuDefaults import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.ProgressIndicatorDefaults +import androidx.compose.material3.SelectableDropdownMenuItem import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -47,13 +45,13 @@ import de.davis.keygo.core.item.domain.alias.newVaultId import de.davis.keygo.core.item.domain.model.Vault import de.davis.keygo.core.item.domain.model.VaultMetadata import de.davis.keygo.core.item.presentation.toImageVector +import de.davis.keygo.core.ui.components.KeyGoMenuDefaults import de.davis.keygo.core.ui.components.KeyGoSwitch import de.davis.keygo.core.ui.theme.KeyGoTheme import de.davis.keygo.feature.vault.R import de.davis.keygo.feature.vault.domain.model.MoveItemsProgress import de.davis.keygo.feature.vault.presentation.model.VaultState -@OptIn(ExperimentalMaterial3Api::class) @Composable fun MoveVaultDialog( vaultState: VaultState.Move, @@ -105,7 +103,6 @@ fun MoveVaultDialog( ) } -@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable private fun MoveVaultProgressContent(progress: MoveItemsProgress) { val animatedFraction by animateFloatAsState( @@ -134,7 +131,6 @@ private fun MoveVaultProgressContent(progress: MoveItemsProgress) { } } -@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable private fun MoveVaultDialogContent( vaultState: VaultState.Move, @@ -193,7 +189,6 @@ private fun SrcVaultRow(srcVault: VaultMetadata) { ) } -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable private fun DstVaultDropdown( dstVaults: List, @@ -231,15 +226,14 @@ private fun DstVaultDropdown( ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest, + containerColor = KeyGoMenuDefaults.containerColor, + shape = MenuDefaults.standaloneGroupShape, ) { val optionCount = dstVaults.size dstVaults.forEachIndexed { index, vault -> - DropdownMenuItem( + SelectableDropdownMenuItem( shapes = MenuDefaults.itemShape(index, optionCount), - colors = MenuDefaults.selectableItemColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest, - ), + colors = KeyGoMenuDefaults.selectableItemColors, selected = vault.vaultId == selectedDstVault?.vaultId, text = { Text( diff --git a/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/VaultSelectionSheet.kt b/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/VaultSelectionSheet.kt index dd236b028..a576b95bc 100644 --- a/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/VaultSelectionSheet.kt +++ b/feature/vault/src/main/kotlin/de/davis/keygo/feature/vault/presentation/components/VaultSelectionSheet.kt @@ -21,7 +21,6 @@ import androidx.compose.material3.DropdownMenuGroup import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuPopup import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItemDefaults @@ -95,7 +94,7 @@ fun VaultSelectionSheet( } } -@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun VaultSelectionSheetContent( vaultState: VaultState.Select, @@ -232,6 +231,7 @@ private fun VaultSelectionSheetContent( leadingIcon = { Icon( imageVector = Icons.Default.Edit, + modifier = Modifier.size(MenuDefaults.LeadingIconSize), contentDescription = stringResource(R.string.edit) ) } @@ -250,6 +250,7 @@ private fun VaultSelectionSheetContent( leadingIcon = { Icon( imageVector = Icons.AutoMirrored.Default.DriveFileMove, + modifier = Modifier.size(MenuDefaults.LeadingIconSize), contentDescription = stringResource(R.string.move_to) ) } @@ -272,12 +273,13 @@ private fun VaultSelectionSheetContent( onDeleteRequest(metadata) }, shape = MenuDefaults.trailingItemShape, - colors = MenuDefaults.selectableItemColors( + colors = MenuDefaults.itemColors().copy( containerColor = MaterialTheme.colorScheme.errorContainer, ), leadingIcon = { Icon( imageVector = Icons.Default.DeleteForever, + modifier = Modifier.size(MenuDefaults.LeadingIconSize), contentDescription = stringResource(R.string.delete) ) } diff --git a/gradle.properties b/gradle.properties index 4c51ec73c..2abf2e0f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,10 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx3g -XX:+UseParallelGC -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8 +# JVM arguments for the Kotlin daemon, which runs the Kotlin compiler. Without this it inherits +# the Gradle daemon's heap, which is not enough for the larger Compose modules. +kotlin.daemon.jvmargs=-Xmx4g -XX:+UseParallelGC # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. For more details, visit # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 280e2c0cc..78d29ed35 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,47 +2,47 @@ compileSdk = "37" minSdk = "26" -agp = "9.3.2" +agp = "9.4.1" autofill = "1.3.0" accompanist = "0.37.3" -camera = "1.6.1" +camera = "1.6.2" credentials = "1.6.0" gmsAuthApiPhone = "18.3.1" gmsMlkitBarcodeScanning = "18.3.1" okhttp = "5.5.0" zxingBarcodeScanning = "3.5.4" -kotlin = "2.4.10" +kotlin = "2.4.20" kotlinSerializationJson = "1.11.0" -collectionsImmutable = "0.5.1" -coreKtx = "1.19.0" +collectionsImmutable = "0.5.2" +coreKtx = "1.19.1" junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.11.0" activityCompose = "1.13.0" -composeBom = "2026.08.00" +composeBom = "2026.09.00" mockk = "1.14.11" semver = "0.2.6" koinBOM = "4.2.2" -koin-plugin = "1.1.0" -room3 = "3.0.1" -sqlite = "2.7.0" +koin-plugin = "1.2.1" +room3 = "3.0.3" +sqlite = "2.7.1" ksp = "2.3.11" datastore = "1.2.1" protobuf = "0.10.0" -protoc = "4.36.0" +protoc = "4.36.2" coroutines = "1.11.0" bcrypt = "0.10.2" biometric = "1.4.0-alpha07" -nav3 = "1.2.0-beta01" +nav3 = "1.2.0" lifecycleViewmodelNav3 = "2.11.0" -kotlinpoet = "2.3.0" +kotlinpoet = "2.4.0" jna = "5.19.1" nbvcxz = "1.5.1" passGen = "0.1.0-beta" -robolectric = "4.16.1" -emvnfccard = "3.1.0" -aboutlibraries = "15.1.1" -work = "2.11.2" +robolectric = "4.17" +emvnfccard = "3.2.0" +aboutlibraries = "15.2.0" +work = "2.12.0" splashscreen = "1.2.0" [libraries] @@ -70,7 +70,7 @@ androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } -androidx-material3 = { group = "androidx.compose.material3", name = "material3", version = "1.5.0-alpha26" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3", version = "1.5.0-alpha29" } androidx-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout" } androidx-material3-adaptive-navigation-suite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite" }