diff --git a/.github/update_gpm_passkeys_priv_apps.py b/.github/update_gpm_passkeys_priv_apps.py index 2e4c5877..f30f6be3 100644 --- a/.github/update_gpm_passkeys_priv_apps.py +++ b/.github/update_gpm_passkeys_priv_apps.py @@ -10,5 +10,5 @@ response = requests.get( json_obj = response.json() json_text = json.dumps(json_obj, indent=2) -with open('common/src/commonMain/resources/MR/files/gpm_passkeys_privileged_apps.json', 'w') as f: +with open('common/src/commonMain/composeResources/files/gpm_passkeys_privileged_apps.json', 'w') as f: f.write(json_text) diff --git a/.github/update_justdeleteme.py b/.github/update_justdeleteme.py index e90df874..fa8cf48f 100644 --- a/.github/update_justdeleteme.py +++ b/.github/update_justdeleteme.py @@ -31,5 +31,5 @@ for site in response.json(): aggr_text = json.dumps(aggr, indent=2) -with open('common/src/commonMain/resources/MR/files/justdeleteme.json', 'w') as f: +with open('common/src/commonMain/composeResources/files/justdeleteme.json', 'w') as f: f.write(aggr_text) diff --git a/.github/update_justgetmydata.py b/.github/update_justgetmydata.py index 6938c7cd..047d4614 100644 --- a/.github/update_justgetmydata.py +++ b/.github/update_justgetmydata.py @@ -31,5 +31,5 @@ for site in response.json(): aggr_text = json.dumps(aggr, indent=2) -with open('common/src/commonMain/resources/MR/files/justgetmydata.json', 'w') as f: +with open('common/src/commonMain/composeResources/files/justgetmydata.json', 'w') as f: f.write(aggr_text) diff --git a/.github/update_passkeys.py b/.github/update_passkeys.py index 9003a5b8..a040807e 100644 --- a/.github/update_passkeys.py +++ b/.github/update_passkeys.py @@ -61,5 +61,5 @@ aggr.sort(key=lambda x: x['domain']) aggr_text = json.dumps(aggr, indent=2) -with open('common/src/commonMain/resources/MR/files/passkeys.json', 'w') as f: +with open('common/src/commonMain/composeResources/files/passkeys.json', 'w') as f: f.write(aggr_text) diff --git a/.github/update_twofactorauth.py b/.github/update_twofactorauth.py index b6a35903..c51fad43 100644 --- a/.github/update_twofactorauth.py +++ b/.github/update_twofactorauth.py @@ -45,5 +45,5 @@ for file in archive.namelist(): aggr_text = json.dumps(aggr, indent=2) -with open('common/src/commonMain/resources/MR/files/tfa.json', 'w') as f: +with open('common/src/commonMain/composeResources/files/tfa.json', 'w') as f: f.write(aggr_text) diff --git a/.github/workflows/new_apk.yaml b/.github/workflows/new_apk.yaml index 3cc5b386..235e3e25 100644 --- a/.github/workflows/new_apk.yaml +++ b/.github/workflows/new_apk.yaml @@ -32,7 +32,7 @@ jobs: arguments: :androidApp:licenseeAndroidNoneRelease - name: "Move licenses" run: | - mv -f androidApp/build/reports/licensee/androidNoneRelease/artifacts.json common/src/commonMain/resources/MR/files/licenses.json + mv -f androidApp/build/reports/licensee/androidNoneRelease/artifacts.json common/src/commonMain/composeResources/files/licenses.json - name: "./gradlew :androidApp:assembleNoneRelease" uses: gradle/actions/setup-gradle@v3 env: diff --git a/.github/workflows/new_daily_tag_play_store_internal_track.yaml b/.github/workflows/new_daily_tag_play_store_internal_track.yaml index f306f5a7..87f6585f 100644 --- a/.github/workflows/new_daily_tag_play_store_internal_track.yaml +++ b/.github/workflows/new_daily_tag_play_store_internal_track.yaml @@ -31,7 +31,7 @@ jobs: arguments: :androidApp:licenseeAndroidPlayStoreRelease - name: "Move licenses" run: | - mv -f androidApp/build/reports/licensee/androidPlayStoreRelease/artifacts.json common/src/commonMain/resources/MR/files/licenses.json + mv -f androidApp/build/reports/licensee/androidPlayStoreRelease/artifacts.json common/src/commonMain/composeResources/files/licenses.json - name: "Build release bundle" uses: gradle/actions/setup-gradle@v3 env: diff --git a/.github/workflows/new_tag_release.yaml b/.github/workflows/new_tag_release.yaml index c55cc3a3..2a1e0dba 100644 --- a/.github/workflows/new_tag_release.yaml +++ b/.github/workflows/new_tag_release.yaml @@ -167,7 +167,7 @@ jobs: arguments: :androidApp:licenseeAndroidNoneRelease - name: "Move licenses" run: | - mv -f androidApp/build/reports/licensee/androidNoneRelease/artifacts.json common/src/commonMain/resources/MR/files/licenses.json + mv -f androidApp/build/reports/licensee/androidNoneRelease/artifacts.json common/src/commonMain/composeResources/files/licenses.json - name: "./gradlew :androidApp:assembleNoneRelease" uses: gradle/actions/setup-gradle@v3 env: diff --git a/.github/workflows/update_localization.yml b/.github/workflows/update_localization.yml index 685a9a31..4dfdc9e9 100644 --- a/.github/workflows/update_localization.yml +++ b/.github/workflows/update_localization.yml @@ -6,7 +6,7 @@ on: branches: - master paths: - - 'common/src/commonMain/resources/MR/base/*.xml' + - 'common/src/commonMain/composeResources/values/*.xml' - 'listing/google/base/*.html' - 'listing/google/base/*.xml' # Configuration. diff --git a/.github/workflows/update_tld.yml b/.github/workflows/update_tld.yml index 30876fa1..daf693ae 100644 --- a/.github/workflows/update_tld.yml +++ b/.github/workflows/update_tld.yml @@ -14,7 +14,7 @@ jobs: - name: "Update data" run: | wget https://publicsuffix.org/list/public_suffix_list.dat - mv -f public_suffix_list.dat common/src/commonMain/resources/MR/files/public_suffix_list.txt + mv -f public_suffix_list.dat common/src/commonMain/composeResources/files/public_suffix_list.txt - name: "Check if any changes" id: check-changes run: | diff --git a/.gitignore b/.gitignore index 1419e03c..4ea27275 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ out/ .gradle/ build/ +# Kotlin files +.kotlin/ + # Local configuration file (sdk path, etc) local.properties diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index d9226895..ab9bb9ee 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -5,9 +5,10 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.compose) + alias(libs.plugins.kotlin.plugin.compose) alias(libs.plugins.kotlin.plugin.parcelize) alias(libs.plugins.kotlin.plugin.serialization) - alias(libs.plugins.compose) alias(libs.plugins.ksp) alias(libs.plugins.ktlint) alias(libs.plugins.google.services) diff --git a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt index 1b6e7e9a..562a4563 100644 --- a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt +++ b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt @@ -31,6 +31,7 @@ import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.platform.lifecycle.toCommon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.datetime.Clock @@ -165,14 +166,15 @@ class Main : BaseApp(), DIAware { delay(duration) duration } - .flatMap { + .effectMap { // Clear the current session. val context = LeContext(this) val session = MasterSession.Empty( - reason = textResource(Res.strings.lock_reason_inactivity, context), + reason = textResource(Res.string.lock_reason_inactivity, context), ) putVaultSession(session) } + .flatten() .attempt() .launchIn(GlobalScope) } diff --git a/build.gradle.kts b/build.gradle.kts index a50cb1d9..5a228215 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,6 +18,7 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.kapt) apply false + alias(libs.plugins.kotlin.plugin.compose) apply false alias(libs.plugins.kotlin.plugin.parcelize) apply false alias(libs.plugins.kotlin.plugin.serialization) apply false alias(libs.plugins.compose) apply false @@ -27,7 +28,6 @@ plugins { alias(libs.plugins.crashlytics) apply false alias(libs.plugins.sqldelight) apply false alias(libs.plugins.buildkonfig) apply false - alias(libs.plugins.moko) apply false alias(libs.plugins.license.check) apply false alias(libs.plugins.versions) apply true alias(libs.plugins.version.catalog.update) apply true diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1b74e02c..89810138 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,6 +1,5 @@ import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.INT import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING -import java.text.SimpleDateFormat import java.util.* plugins { @@ -11,9 +10,9 @@ plugins { alias(libs.plugins.ksp) alias(libs.plugins.ktlint) alias(libs.plugins.buildkonfig) - alias(libs.plugins.moko) alias(libs.plugins.sqldelight) alias(libs.plugins.compose) + alias(libs.plugins.kotlin.plugin.compose) } // @@ -49,8 +48,7 @@ kotlin { implementation(compose.material) implementation(compose.material3) implementation(compose.materialIconsExtended) - @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) - implementation(compose.components.resources) + api(compose.components.resources) api(libs.kdrag0n.colorkt) api(libs.kotlinx.coroutines.core) @@ -176,6 +174,12 @@ kotlin { } } +compose.resources { + publicResClass = true + packageOfResClass = "com.artemchep.keyguard.res" + generateResClass = always +} + android { compileSdk = libs.versions.androidCompileSdk.get().toInt() namespace = "com.artemchep.keyguard.common" @@ -227,6 +231,10 @@ tasks.withType>().all { kotlin.compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") } +kotlin.compilerOptions.freeCompilerArgs.addAll( + "-P", + "plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=com.artemchep.keyguard.platform.parcelize.LeParcelize", +) kotlin.sourceSets.commonMain { kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") } @@ -244,15 +252,6 @@ dependencies { add("kspAndroid", libs.androidx.room.compiler) add("kspAndroid", libs.glide.ksp) add("coreLibraryDesugaring", libs.android.desugarjdklibs) - - commonMainApi(libs.moko.resources) - commonMainApi(libs.moko.resources.compose) - commonTestImplementation(libs.moko.resources.test) -} - -multiplatformResources { - multiplatformResourcesPackage = "com.artemchep.keyguard.res" - multiplatformResourcesClassName = "Res" // optional, default MR } enum class BuildType { diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillActivity.kt index bebdd0f9..cf5a7491 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillActivity.kt @@ -42,8 +42,9 @@ import com.artemchep.keyguard.common.usecase.GetTotpCode import com.artemchep.keyguard.pick import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.runBlocking import kotlinx.parcelize.Parcelize import org.kodein.di.DIAware @@ -271,7 +272,7 @@ class AutofillActivity : BaseActivity(), DIAware { .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.cancel), + text = stringResource(Res.string.cancel), textAlign = TextAlign.Center, ) } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillSaveActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillSaveActivity.kt index 99357743..f47d7934 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillSaveActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/AutofillSaveActivity.kt @@ -39,11 +39,12 @@ import com.artemchep.keyguard.feature.home.vault.add.AddRoute import com.artemchep.keyguard.feature.home.vault.add.of import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.colorizePassword import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.parcelize.Parcelize import org.kodein.di.DIAware @@ -129,7 +130,7 @@ class AutofillSaveActivity : BaseActivity(), DIAware { .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.close), + text = stringResource(Res.string.close), textAlign = TextAlign.Center, ) } @@ -143,7 +144,7 @@ class AutofillSaveActivity : BaseActivity(), DIAware { if (username != null) { key("username") { TwoColumnRow( - title = stringResource(Res.strings.username), + title = stringResource(Res.string.username), value = username, ) } @@ -156,7 +157,7 @@ class AutofillSaveActivity : BaseActivity(), DIAware { contentColor = LocalContentColor.current, ) TwoColumnRow( - title = stringResource(Res.strings.password), + title = stringResource(Res.string.password), value = colorizedPassword, ) } @@ -167,7 +168,7 @@ class AutofillSaveActivity : BaseActivity(), DIAware { if (email != null) { key("email") { TwoColumnRow( - title = stringResource(Res.strings.email), + title = stringResource(Res.string.email), value = email, ) } @@ -176,7 +177,7 @@ class AutofillSaveActivity : BaseActivity(), DIAware { if (phone != null) { key("phone") { TwoColumnRow( - title = stringResource(Res.strings.phone_number), + title = stringResource(Res.string.phone_number), value = phone, ) } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/LargeTypeActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/LargeTypeActivity.kt index 5e2cc9c6..44103fc6 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/LargeTypeActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/LargeTypeActivity.kt @@ -25,10 +25,11 @@ import com.artemchep.keyguard.feature.navigation.NavigationNode import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.KeepScreenOnEffect import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.parcelize.Parcelize /** @@ -119,7 +120,7 @@ private fun LargeTypeScreen( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.largetype_title)) + Text(stringResource(Res.string.largetype_title)) }, navigationIcon = { IconButton( diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCompose.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCompose.kt index 92b22d29..1e533f85 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCompose.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCompose.kt @@ -19,9 +19,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.OtherScaffold import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun PasskeyError( @@ -84,7 +85,7 @@ fun PasskeyError( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.close), + text = stringResource(Res.string.close), ) } } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCreateActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCreateActivity.kt index ea40f01e..be470ca9 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCreateActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyCreateActivity.kt @@ -26,6 +26,7 @@ import androidx.credentials.provider.PendingIntentHandler import androidx.lifecycle.lifecycleScope import com.artemchep.keyguard.AppMode import com.artemchep.keyguard.LocalAppMode +import com.artemchep.keyguard.common.R import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.model.AddPasskeyCipherRequest @@ -43,10 +44,11 @@ import com.artemchep.keyguard.platform.recordException import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.common.service.passkey.entity.CreatePasskey import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first @@ -155,8 +157,7 @@ class PasskeyCreateActivity : BaseActivity(), DIAware { // Show the error to a user val uiState = Ahhehe.Error( - title = Res.strings.error_failed_create_passkey - .getString(this@PasskeyCreateActivity), + title = org.jetbrains.compose.resources.getString(Res.string.error_failed_create_passkey), message = it.localizedMessage ?: it.message ?: "Something went wrong", @@ -190,8 +191,7 @@ class PasskeyCreateActivity : BaseActivity(), DIAware { // Show the error to a user val uiState = Ahhehe.Error( - title = Res.strings.error_failed_create_passkey - .getString(this@PasskeyCreateActivity), + title = org.jetbrains.compose.resources.getString(Res.string.error_failed_create_passkey), message = it.localizedMessage ?: it.message ?: "Something went wrong", @@ -235,7 +235,7 @@ class PasskeyCreateActivity : BaseActivity(), DIAware { .align(Alignment.CenterVertically), ) { Text( - text = stringResource(Res.strings.passkey_create_header), + text = stringResource(Res.string.passkey_create_header), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -284,7 +284,7 @@ class PasskeyCreateActivity : BaseActivity(), DIAware { .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.cancel), + text = stringResource(Res.string.cancel), textAlign = TextAlign.Center, ) } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetActivity.kt index 8cf4eeac..c33ebbae 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetActivity.kt @@ -31,6 +31,7 @@ import androidx.credentials.exceptions.GetCredentialUnknownException import androidx.credentials.provider.PendingIntentHandler import androidx.lifecycle.lifecycleScope import arrow.optics.optics +import com.artemchep.keyguard.common.R import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.io.effectTap @@ -73,13 +74,14 @@ import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.recordException import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.OtherScaffold import com.artemchep.keyguard.ui.PasswordFlatTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay @@ -215,8 +217,7 @@ class PasskeyGetActivity : BaseActivity(), DIAware { // Show the error to a user val uiState = Ahhehe.Error( - title = Res.strings.error_failed_use_passkey - .getString(this@PasskeyGetActivity), + title = org.jetbrains.compose.resources.getString(Res.string.error_failed_use_passkey), message = it.localizedMessage ?: it.message ?: "Something went wrong", @@ -271,7 +272,7 @@ class PasskeyGetActivity : BaseActivity(), DIAware { .align(Alignment.CenterVertically), ) { Text( - text = stringResource(Res.strings.passkey_auth_via_header), + text = stringResource(Res.string.passkey_auth_via_header), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -310,7 +311,7 @@ class PasskeyGetActivity : BaseActivity(), DIAware { .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.cancel), + text = stringResource(Res.string.cancel), textAlign = TextAlign.Center, ) } @@ -426,7 +427,7 @@ fun UserVerificationScreen( top = { Text( textAlign = TextAlign.Center, - text = stringResource(Res.strings.userverification_header_text), + text = stringResource(Res.string.userverification_header_text), style = MaterialTheme.typography.bodyLarge, ) }, @@ -469,7 +470,7 @@ fun UserVerificationScreen( }, ) { Text( - text = stringResource(Res.strings.userverification_button_go), + text = stringResource(Res.string.userverification_button_go), ) } val onBiometricButtonClick by rememberUpdatedState( @@ -638,7 +639,7 @@ fun produceUserVerificationState( onAuthenticated() } else { val message = ToastMessage( - title = translate(Res.strings.error_incorrect_password), + title = translate(Res.string.error_incorrect_password), type = ToastMessage.Type.ERROR, ) message(message) @@ -662,8 +663,8 @@ private fun createPromptOrNull( fn: () -> Unit, ): PureBiometricAuthPrompt = run { BiometricAuthPromptSimple( - title = TextHolder.Res(Res.strings.elevatedaccess_biometric_auth_confirm_title), - text = TextHolder.Res(Res.strings.elevatedaccess_biometric_auth_confirm_text), + title = TextHolder.Res(Res.string.elevatedaccess_biometric_auth_confirm_title), + text = TextHolder.Res(Res.string.elevatedaccess_biometric_auth_confirm_text), requireConfirmation = requireConfirmation, onComplete = { result -> result.fold( diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetUnlockActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetUnlockActivity.kt index c1aa1af8..fdb44bef 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetUnlockActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/PasskeyGetUnlockActivity.kt @@ -36,8 +36,9 @@ import com.artemchep.keyguard.feature.keyguard.ManualAppScreenOnUnlock import com.artemchep.keyguard.platform.recordException import com.artemchep.keyguard.platform.recordLog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch @@ -129,7 +130,7 @@ class PasskeyGetUnlockActivity : BaseActivity(), DIAware { modifier = Modifier .weight(1f) .align(Alignment.CenterVertically), - text = stringResource(Res.strings.autofill_unlock_keyguard), + text = stringResource(Res.string.autofill_unlock_keyguard), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -147,7 +148,7 @@ class PasskeyGetUnlockActivity : BaseActivity(), DIAware { .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.cancel), + text = stringResource(Res.string.cancel), textAlign = TextAlign.Center, ) } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardAutofillService.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardAutofillService.kt index 0713af4c..7ba0bad7 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardAutofillService.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardAutofillService.kt @@ -29,6 +29,8 @@ import com.artemchep.keyguard.common.io.* import com.artemchep.keyguard.common.model.* import com.artemchep.keyguard.common.usecase.* import com.artemchep.keyguard.feature.home.vault.component.FormatCardGroupLength +import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.http.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -408,7 +410,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { SELECT, } - private fun FillResponse.Builder.buildAuthentication( + private suspend fun FillResponse.Builder.buildAuthentication( type: FooBar, result2: AutofillStructure2, request: FillRequest, @@ -469,12 +471,12 @@ class KeyguardAutofillService : AutofillService(), DIAware { } } - private fun tryBuildDataset( + private suspend fun tryBuildDataset( index: Int, context: Context, secret: DSecret, struct: AutofillStructure2, - onComplete: (Dataset.Builder.() -> Unit)? = null, + onComplete: (suspend Dataset.Builder.() -> Unit)? = null, ): Dataset? { val title = secret.name val text = kotlin.run { @@ -491,10 +493,10 @@ class KeyguardAutofillService : AutofillService(), DIAware { text = text, ) - fun createDatasetBuilder(): Dataset.Builder { + suspend fun createDatasetBuilder(): Dataset.Builder { val builder = Dataset.Builder(views) builder.setId(secret.id) - val fields = runBlocking { + val fields = run { val hints = struct.items .asSequence() .map { it.hint } @@ -556,7 +558,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { @RequiresApi(Build.VERSION_CODES.R) @SuppressLint("RestrictedApi") - private fun tryBuildSecretInlinePresentation( + private suspend fun tryBuildSecretInlinePresentation( request: FillRequest, index: Int, secret: DSecret, @@ -606,7 +608,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { @RequiresApi(Build.VERSION_CODES.R) @SuppressLint("RestrictedApi") - private fun tryBuildManualSelectionInlinePresentation( + private suspend fun tryBuildManualSelectionInlinePresentation( request: FillRequest, index: Int, intent: Intent, @@ -618,7 +620,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { PendingIntent.getActivity(this, 1010, intent, flags) }, content = { - val title = getString(R.string.autofill_open_keyguard) + val title = org.jetbrains.compose.resources.getString(Res.string.autofill_open_keyguard) setContentDescription(title) setTitle(title) setStartIcon(createAppIcon()) @@ -627,7 +629,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { @SuppressLint("RestrictedApi") @RequiresApi(Build.VERSION_CODES.R) - private fun tryCreateAuthenticationInlinePresentation( + private suspend fun tryCreateAuthenticationInlinePresentation( type: FooBar, request: FillRequest, index: Int, @@ -641,8 +643,8 @@ class KeyguardAutofillService : AutofillService(), DIAware { }, content = { val text = when (type) { - FooBar.UNLOCK -> getString(R.string.autofill_unlock_keyguard) - FooBar.SELECT -> getString(R.string.autofill_open_keyguard) + FooBar.UNLOCK -> org.jetbrains.compose.resources.getString(Res.string.autofill_unlock_keyguard) + FooBar.SELECT -> org.jetbrains.compose.resources.getString(Res.string.autofill_open_keyguard) } setContentDescription(text) setTitle(text) @@ -652,7 +654,7 @@ class KeyguardAutofillService : AutofillService(), DIAware { @SuppressLint("RestrictedApi") @RequiresApi(Build.VERSION_CODES.R) - private inline fun tryCreateInlinePresentation( + private suspend inline fun tryCreateInlinePresentation( request: FillRequest, index: Int, createPendingIntent: () -> PendingIntent, @@ -668,7 +670,9 @@ class KeyguardAutofillService : AutofillService(), DIAware { return InlinePresentation( InlineSuggestionUi .newContentBuilder(pi) - .apply(content) + .apply { + content(this) + } .build().slice, spec, false, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardCredentialService.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardCredentialService.kt index bff0dbb2..8c337a6f 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardCredentialService.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/autofill/KeyguardCredentialService.kt @@ -40,6 +40,8 @@ import com.artemchep.keyguard.common.usecase.GetVaultSession import com.artemchep.keyguard.common.usecase.filterHiddenProfiles import com.artemchep.keyguard.feature.crashlytics.crashlyticsTap import com.artemchep.keyguard.platform.recordLog +import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -188,7 +190,7 @@ class KeyguardCredentialService : CredentialProviderService(), DIAware { // Need to authenticate a user to unlock // the database first. is MasterSession.Empty -> { - val title = getString(R.string.autofill_open_keyguard) + val title = org.jetbrains.compose.resources.getString(Res.string.autofill_open_keyguard) val pi = createGetUnlockPasskeyPendingIntent() val actions = listOf( AuthenticationAction( diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/clipboard/KeyguardClipboardService.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/clipboard/KeyguardClipboardService.kt index 01a82b7d..84625d8b 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/clipboard/KeyguardClipboardService.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/clipboard/KeyguardClipboardService.kt @@ -28,6 +28,8 @@ import com.artemchep.keyguard.common.model.TotpToken import com.artemchep.keyguard.common.service.clipboard.ClipboardService import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefresh import com.artemchep.keyguard.common.usecase.GetTotpCode +import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.totp.formatCodeStr import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -352,7 +354,7 @@ class KeyguardClipboardService : Service(), DIAware { // Notifications // - private fun createNotification( + private suspend fun createNotification( type: CopyValueEvent.Type, name: String?, text: String, @@ -377,8 +379,8 @@ class KeyguardClipboardService : Service(), DIAware { } val contentTitle = when (type) { - CopyValueEvent.Type.TOTP -> getString(R.string.copied_otp_code) - CopyValueEvent.Type.VALUE -> getString(R.string.copied_value) + CopyValueEvent.Type.TOTP -> org.jetbrains.compose.resources.getString(Res.string.copied_otp_code) + CopyValueEvent.Type.VALUE -> org.jetbrains.compose.resources.getString(Res.string.copied_value) } val contentText = kotlin.run { val suffix = expiration @@ -404,7 +406,7 @@ class KeyguardClipboardService : Service(), DIAware { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, ) } - val copyTitle = getString(R.string.copy) + val copyTitle = org.jetbrains.compose.resources.getString(Res.string.copy) NotificationCompat.Action.Builder(R.drawable.ic_copy, copyTitle, copyAction) .build() } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/copy/TextServiceAndroid.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/copy/TextServiceAndroid.kt index aad984c2..4ae0873f 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/copy/TextServiceAndroid.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/copy/TextServiceAndroid.kt @@ -3,8 +3,11 @@ package com.artemchep.keyguard.copy import android.app.Application import android.content.Context import android.net.Uri +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.text.TextService -import dev.icerock.moko.resources.FileResource +import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.ExperimentalResourceApi import org.kodein.di.DirectDI import org.kodein.di.instance import java.io.InputStream @@ -18,12 +21,11 @@ class TextServiceAndroid( context = directDI.instance(), ) - override fun readFromResources( + @OptIn(ExperimentalResourceApi::class) + override suspend fun readFromResources( fileResource: FileResource, - ): InputStream = fileResource.inputStream() - - private fun FileResource.inputStream() = context.resources - .openRawResource(rawResId) + ): InputStream = Res.readBytes(fileResource.name) + .inputStream() override fun readFromFile(uri: String): InputStream { val parsedUri = Uri.parse(uri) diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/apppicker/AppPickerScreen.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/apppicker/AppPickerScreen.kt index b7e5e004..719ac88c 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/apppicker/AppPickerScreen.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/apppicker/AppPickerScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevati import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -45,7 +46,7 @@ import com.artemchep.keyguard.ui.pulltosearch.PullToSearch import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -131,7 +132,7 @@ fun ChangePasswordScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.apppicker_header_title), + title = stringResource(Res.string.apppicker_header_title), icon = { NavigationIcon() }, @@ -151,7 +152,7 @@ fun ChangePasswordScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.apppicker_search_placeholder), + placeholder = stringResource(Res.string.apppicker_search_placeholder), searchIcon = false, count = count, leading = {}, @@ -234,7 +235,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.apppicker_empty_label), + text = stringResource(Res.string.apppicker_empty_label), ) }, ) @@ -277,7 +278,7 @@ private fun AppItem( horizontal = 6.dp, vertical = 2.dp, ), - text = stringResource(Res.strings.apppicker_system_app_label), + text = stringResource(Res.string.apppicker_system_app_label), maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.labelMedium, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginOtpScreen.android.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginOtpScreen.android.kt index 1ccef540..97387a64 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginOtpScreen.android.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginOtpScreen.android.kt @@ -29,10 +29,11 @@ import androidx.compose.ui.viewinterop.AndroidView import arrow.core.left import arrow.core.right import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.util.DividerColor -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @SuppressLint("SetJavaScriptEnabled") @Composable @@ -105,7 +106,7 @@ actual fun ColumnScope.LoginOtpScreenContentFido2WebAuthnBrowser( updatedOnClick?.invoke() }, ) { - Text(stringResource(Res.strings.fido2webauthn_action_go_title)) + Text(stringResource(Res.string.fido2webauthn_action_go_title)) } ExpandedIfNotEmpty(state.error) { error -> Column { @@ -141,7 +142,7 @@ actual fun ColumnScope.LoginOtpScreenContentFido2WebAuthnBrowser( // modifier = Modifier // .padding(horizontal = Dimens.horizontalPadding), // text = stringResource( -// Res.strings.fido2webauthn_bitwarden_web_vault_version_warning_note, +// Res.string.fido2webauthn_bitwarden_web_vault_version_warning_note, // "2023.7.1", // ), // style = MaterialTheme.typography.bodyMedium, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/biometric/BiometricPromptEffect.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/biometric/BiometricPromptEffect.kt index 24f8d3a8..ae57fbae 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/biometric/BiometricPromptEffect.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/biometric/BiometricPromptEffect.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.withResumed +import androidx.lifecycle.whenResumed import arrow.core.left import arrow.core.right import com.artemchep.keyguard.android.closestActivityOrNull @@ -28,7 +28,7 @@ actual fun BiometricPromptEffect( CollectedEffect(flow) { event -> // We want the screen to be visible and on front, when the biometric // prompt is popping up. - lifecycle.lifecycle.withResumed { + lifecycle.lifecycle.whenResumed { val activity = context.closestActivityOrNull as FragmentActivity when (event) { is BiometricAuthPrompt -> activity.launchPrompt(event) @@ -38,7 +38,7 @@ actual fun BiometricPromptEffect( } } -private fun FragmentActivity.launchPrompt( +private suspend fun FragmentActivity.launchPrompt( event: BiometricAuthPrompt, ) { val promptTitle = textResource(event.title, this) @@ -77,7 +77,7 @@ private fun FragmentActivity.launchPrompt( prompt.authenticate(promptInfo, crypto) } -private fun FragmentActivity.launchPrompt( +private suspend fun FragmentActivity.launchPrompt( event: BiometricAuthPromptSimple, ) { val promptTitle = textResource(event.title, this) diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt index 9c2c343f..694dea12 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.platform.LocalContext import com.artemchep.keyguard.common.model.ToastMessage import com.artemchep.keyguard.common.usecase.ShowMessage +import com.artemchep.keyguard.platform.LeUriImpl import com.artemchep.keyguard.ui.CollectedEffect import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -45,7 +46,7 @@ actual fun FilePickerEffect( val info = uri?.let { FilePickerIntent.OpenDocument.Ifo( - uri = it, + uri = LeUriImpl(it), name = getFileName(context, it), size = getFileSize(context, it), ) diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt index 5a1988cd..385d0447 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt @@ -5,8 +5,11 @@ import androidx.compose.material.icons.automirrored.outlined.AddToHomeScreen import androidx.core.content.pm.ShortcutManagerCompat import com.artemchep.keyguard.android.util.ShortcutInfo import com.artemchep.keyguard.common.model.DCipherFilter +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.iconSmall @@ -25,7 +28,7 @@ actual fun CipherFilterUtil.addShortcutActionOrNull( ) return FlatItemAction( leading = iconSmall(Icons.AutoMirrored.Outlined.AddToHomeScreen), - title = translate(Res.strings.add_to_home_screen), + title = Res.string.add_to_home_screen.wrap(), onClick = { ShortcutManagerCompat.requestPinShortcut(androidContext, shortcut, null) }, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofill.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofill.kt index f315dab7..d5665223 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofill.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofill.kt @@ -24,13 +24,14 @@ import com.artemchep.keyguard.android.closestActivityOrNull import com.artemchep.keyguard.common.service.autofill.AutofillService import com.artemchep.keyguard.common.service.autofill.AutofillServiceStatus import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -107,12 +108,12 @@ private fun SettingAutofill( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_service_title), + text = stringResource(Res.string.pref_item_autofill_service_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_service_text), + text = stringResource(Res.string.pref_item_autofill_service_text), ) }, onClick = onCheckedChange?.partially1(!checked), @@ -150,7 +151,7 @@ private fun SettingAutofillPlatformWarningMiui( start = Dimens.horizontalPadding * 1 + 24.dp, ), type = SimpleNote.Type.INFO, - text = stringResource(Res.strings.pref_item_autofill_service_xiaomi_permission_note), + text = stringResource(Res.string.pref_item_autofill_service_xiaomi_permission_note), trailing = { val updatedContext by rememberUpdatedState(LocalContext.current) IconButton( diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardNotificationSettings.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardNotificationSettings.kt index a2be569e..b769ea51 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardNotificationSettings.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardNotificationSettings.kt @@ -12,10 +12,11 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.platform.LocalContext import com.artemchep.keyguard.common.R import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -40,7 +41,7 @@ fun SettingClipboardNotificationSettings( leading = icon(Icons.Outlined.EditNotifications), title = { Text( - text = stringResource(Res.strings.pref_item_clipboard_notification_settings_title), + text = stringResource(Res.string.pref_item_clipboard_notification_settings_title), ) }, trailing = { diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCredentialProvider.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCredentialProvider.kt index 76a92fa2..03c6c704 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCredentialProvider.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCredentialProvider.kt @@ -14,10 +14,11 @@ import com.artemchep.keyguard.common.io.ioEffect import com.artemchep.keyguard.common.io.launchIn import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -79,12 +80,12 @@ private fun SettingCredentialProvider( }, title = { Text( - text = stringResource(Res.strings.pref_item_credential_provider_title), + text = stringResource(Res.string.pref_item_credential_provider_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_credential_provider_text), + text = stringResource(Res.string.pref_item_credential_provider_text), ) }, onClick = onClick, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermission.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermission.kt index 5a03bbc5..c7a0f0eb 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermission.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermission.kt @@ -19,14 +19,15 @@ import com.artemchep.keyguard.feature.home.settings.permissions.PermissionsSetti import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState -import dev.icerock.moko.resources.StringResource -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -60,7 +61,7 @@ private fun SettingPermissionDetails( }, title = { Text( - text = stringResource(Res.strings.pref_item_permissions_title), + text = stringResource(Res.string.pref_item_permissions_title), ) }, onClick = onClick, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionCamera.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionCamera.kt index a6dfb449..cdc3ad41 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionCamera.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionCamera.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.CameraAlt import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon import com.google.accompanist.permissions.ExperimentalPermissionsApi import org.kodein.di.DirectDI @@ -17,8 +18,8 @@ actual fun settingPermissionCameraProvider( @OptIn(ExperimentalPermissionsApi::class) fun settingPermissionCameraProvider2(): SettingComponent = settingPermissionProvider( leading = icon(Icons.Outlined.CameraAlt), - title = Res.strings.pref_item_permission_camera_title, - text = Res.strings.pref_item_permission_camera_text, + title = Res.string.pref_item_permission_camera_title, + text = Res.string.pref_item_permission_camera_text, minSdk = Build.VERSION_CODES.M, permissionProvider = { Manifest.permission.CAMERA diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionPostNotifications.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionPostNotifications.kt index 9a1b63af..7e59f85d 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionPostNotifications.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionPostNotifications.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Notifications import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon import com.google.accompanist.permissions.ExperimentalPermissionsApi import org.kodein.di.DirectDI @@ -17,8 +18,8 @@ actual fun settingPermissionPostNotificationsProvider( @OptIn(ExperimentalPermissionsApi::class) fun settingPermissionPostNotificationsProvider2(): SettingComponent = settingPermissionProvider( leading = icon(Icons.Outlined.Notifications), - title = Res.strings.pref_item_permission_post_notifications_title, - text = Res.strings.pref_item_permission_post_notifications_text, + title = Res.string.pref_item_permission_post_notifications_title, + text = Res.string.pref_item_permission_post_notifications_text, minSdk = Build.VERSION_CODES.TIRAMISU, permissionProvider = { Manifest.permission.POST_NOTIFICATIONS diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionWriteExternalStorage.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionWriteExternalStorage.kt index 60bafeca..45eaa952 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionWriteExternalStorage.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPermissionWriteExternalStorage.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Storage import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon import com.google.accompanist.permissions.ExperimentalPermissionsApi import org.kodein.di.DirectDI @@ -17,8 +18,8 @@ actual fun settingPermissionWriteExternalStorageProvider( @OptIn(ExperimentalPermissionsApi::class) fun settingPermissionWriteExternalStorageProvider(): SettingComponent = settingPermissionProvider( leading = icon(Icons.Outlined.Storage), - title = Res.strings.pref_item_permission_write_external_storage_title, - text = Res.strings.pref_item_permission_write_external_storage_text, + title = Res.string.pref_item_permission_write_external_storage_title, + text = Res.string.pref_item_permission_write_external_storage_text, maxSdk = Build.VERSION_CODES.Q, permissionProvider = { Manifest.permission.WRITE_EXTERNAL_STORAGE diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptionsPlayStore.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptionsPlayStore.kt index 67d8902c..5cc2b32b 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptionsPlayStore.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptionsPlayStore.kt @@ -11,10 +11,11 @@ import androidx.compose.ui.platform.LocalContext import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -38,7 +39,7 @@ private fun SettingSubscriptionsPlayStore() { title = { Text( text = stringResource( - Res.strings.pref_item_premium_manage_subscription_on_play_store_title, + Res.string.pref_item_premium_manage_subscription_on_play_store_title, ), ) }, diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResource.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResource.kt deleted file mode 100644 index ee5137ef..00000000 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResource.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.artemchep.keyguard.feature.localization - -import android.content.Context -import com.artemchep.keyguard.platform.LeContext -import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.StringResource -import dev.icerock.moko.resources.desc.PluralFormatted -import dev.icerock.moko.resources.desc.Resource -import dev.icerock.moko.resources.desc.ResourceFormatted -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.resources.desc.desc - -fun textResource(text: TextHolder, context: Context): String = when (text) { - is TextHolder.Value -> text.data.desc() - is TextHolder.Res -> text.data.desc() -}.toString(context) - -actual fun textResource(res: StringResource, context: LeContext): String = - StringDesc.Resource(res).toString(context.context) - -actual fun textResource( - res: StringResource, - context: LeContext, - vararg args: Any, -): String = - StringDesc.ResourceFormatted(res, *args).toString(context.context) - -actual fun textResource( - res: PluralsResource, - context: LeContext, - quantity: Int, - vararg args: Any, -): String = - StringDesc.PluralFormatted(res, quantity, *args).toString(context.context) diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResourceAndroid.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResourceAndroid.kt new file mode 100644 index 00000000..3c67f74f --- /dev/null +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/localization/TextResourceAndroid.kt @@ -0,0 +1,9 @@ +package com.artemchep.keyguard.feature.localization + +import android.content.Context +import com.artemchep.keyguard.platform.LeContext + +suspend fun textResource(text: TextHolder, context: Context): String = when (text) { + is TextHolder.Value -> text.data + is TextHolder.Res -> textResource(text.data, LeContext(context)) +} diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt index 0c89cde8..95c19614 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt @@ -28,6 +28,7 @@ import androidx.core.content.ContextCompat import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.CollectedEffect import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.theme.Dimens @@ -38,7 +39,7 @@ import com.google.accompanist.permissions.rememberPermissionState import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.common.InputImage -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import java.util.concurrent.Executors @Composable @@ -73,7 +74,7 @@ fun ScanQrScreen( modifier = Modifier .statusBarsPadding(), title = { - Text(stringResource(Res.strings.scanqr_title)) + Text(stringResource(Res.string.scanqr_title)) }, navigationIcon = { NavigationIcon() diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/LeUri.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/LeUri.kt index 5b8833ee..069de750 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/LeUri.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/LeUri.kt @@ -1,11 +1,20 @@ package com.artemchep.keyguard.platform import android.net.Uri +import android.os.Parcelable import androidx.core.net.toUri +import kotlinx.parcelize.Parcelize import java.io.File -actual typealias LeUri = Uri +actual abstract class LeUri : Parcelable -actual fun leParseUri(uri: String): LeUri = Uri.parse(uri) +@Parcelize +data class LeUriImpl( + val uri: Uri, +) : LeUri() { + override fun toString(): String = uri.toString() +} -actual fun leParseUri(file: File): LeUri = file.toUri() +actual fun leParseUri(uri: String): LeUri = Uri.parse(uri).let(::LeUriImpl) + +actual fun leParseUri(file: File): LeUri = file.toUri().let(::LeUriImpl) diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt deleted file mode 100644 index abba6905..00000000 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.artemchep.keyguard.platform.parcelize - -import kotlinx.parcelize.Parcelize - -actual typealias LeParcelize = Parcelize diff --git a/common/src/androidMain/res/layout/item_autofill_select_entry.xml b/common/src/androidMain/res/layout/item_autofill_select_entry.xml index b885eec4..952a25f9 100644 --- a/common/src/androidMain/res/layout/item_autofill_select_entry.xml +++ b/common/src/androidMain/res/layout/item_autofill_select_entry.xml @@ -12,7 +12,7 @@ android:layout_gravity="center" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" - android:contentDescription="@string/autofill_open_keyguard" + android:contentDescription="@string/android_autofill_open_keyguard" android:src="@mipmap/ic_launcher" /> \ No newline at end of file diff --git a/common/src/androidMain/res/layout/item_autofill_unlock.xml b/common/src/androidMain/res/layout/item_autofill_unlock.xml index dc8c9769..e44bbfe8 100644 --- a/common/src/androidMain/res/layout/item_autofill_unlock.xml +++ b/common/src/androidMain/res/layout/item_autofill_unlock.xml @@ -24,6 +24,6 @@ android:paddingLeft="16dp" android:paddingEnd="16dp" android:paddingRight="16dp" - android:text="@string/autofill_unlock_keyguard" + android:text="@string/android_autofill_unlock_keyguard" android:textAppearance="?android:attr/textAppearanceListItemSmall" /> \ No newline at end of file diff --git a/common/src/androidMain/res/values/strings.xml b/common/src/androidMain/res/values/strings_android.xml similarity index 88% rename from common/src/androidMain/res/values/strings.xml rename to common/src/androidMain/res/values/strings_android.xml index 0dfb9ae0..438a1bab 100644 --- a/common/src/androidMain/res/values/strings.xml +++ b/common/src/androidMain/res/values/strings_android.xml @@ -18,10 +18,14 @@ Syncing vault About + Generator Keyguard form autofilling Unlock Keyguard Enable autofilling to quickly fill out forms in other apps Open Keyguard Set default autofill service Autofill settings + + Open Keyguard + Unlock Keyguard \ No newline at end of file diff --git a/common/src/commonMain/resources/MR/images/ic_keyguard@2x.png b/common/src/commonMain/composeResources/drawable-xhdpi/ic_keyguard.png similarity index 100% rename from common/src/commonMain/resources/MR/images/ic_keyguard@2x.png rename to common/src/commonMain/composeResources/drawable-xhdpi/ic_keyguard.png diff --git a/common/src/commonMain/resources/MR/images/ic_tray_macos@2x.png b/common/src/commonMain/composeResources/drawable-xhdpi/ic_tray_macos.png similarity index 100% rename from common/src/commonMain/resources/MR/images/ic_tray_macos@2x.png rename to common/src/commonMain/composeResources/drawable-xhdpi/ic_tray_macos.png diff --git a/common/src/commonMain/composeResources/drawable/ic_card_amex.xml b/common/src/commonMain/composeResources/drawable/ic_card_amex.xml new file mode 100644 index 00000000..0ddcfeaf --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_amex.xml @@ -0,0 +1,12 @@ + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_diners.xml b/common/src/commonMain/composeResources/drawable/ic_card_diners.xml new file mode 100644 index 00000000..5bb6d503 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_diners.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_discover.xml b/common/src/commonMain/composeResources/drawable/ic_card_discover.xml new file mode 100644 index 00000000..062edbe1 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_discover.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_elo.xml b/common/src/commonMain/composeResources/drawable/ic_card_elo.xml new file mode 100644 index 00000000..04ee5e8d --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_elo.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_jcb.xml b/common/src/commonMain/composeResources/drawable/ic_card_jcb.xml new file mode 100644 index 00000000..c71ae2c8 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_jcb.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_maestro.xml b/common/src/commonMain/composeResources/drawable/ic_card_maestro.xml new file mode 100644 index 00000000..afa1c121 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_maestro.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_mastercard.xml b/common/src/commonMain/composeResources/drawable/ic_card_mastercard.xml new file mode 100644 index 00000000..007f5e13 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_mastercard.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_mir.xml b/common/src/commonMain/composeResources/drawable/ic_card_mir.xml new file mode 100644 index 00000000..cbc287fe --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_mir.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_unionpay.xml b/common/src/commonMain/composeResources/drawable/ic_card_unionpay.xml new file mode 100644 index 00000000..65103384 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_unionpay.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_card_visa.xml b/common/src/commonMain/composeResources/drawable/ic_card_visa.xml new file mode 100644 index 00000000..d03fc416 --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_card_visa.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/common/src/commonMain/composeResources/drawable/ic_mastodon.xml b/common/src/commonMain/composeResources/drawable/ic_mastodon.xml new file mode 100644 index 00000000..cdabc8cf --- /dev/null +++ b/common/src/commonMain/composeResources/drawable/ic_mastodon.xml @@ -0,0 +1,9 @@ + + + diff --git a/common/src/commonMain/resources/MR/files/gpm_passkeys_privileged_apps.json b/common/src/commonMain/composeResources/files/gpm_passkeys_privileged_apps.json similarity index 100% rename from common/src/commonMain/resources/MR/files/gpm_passkeys_privileged_apps.json rename to common/src/commonMain/composeResources/files/gpm_passkeys_privileged_apps.json diff --git a/common/src/commonMain/resources/MR/files/justdeleteme.json b/common/src/commonMain/composeResources/files/justdeleteme.json similarity index 100% rename from common/src/commonMain/resources/MR/files/justdeleteme.json rename to common/src/commonMain/composeResources/files/justdeleteme.json diff --git a/common/src/commonMain/resources/MR/files/justgetmydata.json b/common/src/commonMain/composeResources/files/justgetmydata.json similarity index 100% rename from common/src/commonMain/resources/MR/files/justgetmydata.json rename to common/src/commonMain/composeResources/files/justgetmydata.json diff --git a/common/src/commonMain/resources/MR/files/licenses.json b/common/src/commonMain/composeResources/files/licenses.json similarity index 100% rename from common/src/commonMain/resources/MR/files/licenses.json rename to common/src/commonMain/composeResources/files/licenses.json diff --git a/common/src/commonMain/resources/MR/files/passkeys.json b/common/src/commonMain/composeResources/files/passkeys.json similarity index 100% rename from common/src/commonMain/resources/MR/files/passkeys.json rename to common/src/commonMain/composeResources/files/passkeys.json diff --git a/common/src/commonMain/resources/MR/files/public_suffix_list.txt b/common/src/commonMain/composeResources/files/public_suffix_list.txt similarity index 100% rename from common/src/commonMain/resources/MR/files/public_suffix_list.txt rename to common/src/commonMain/composeResources/files/public_suffix_list.txt diff --git a/common/src/commonMain/resources/MR/files/tfa.json b/common/src/commonMain/composeResources/files/tfa.json similarity index 100% rename from common/src/commonMain/resources/MR/files/tfa.json rename to common/src/commonMain/composeResources/files/tfa.json diff --git a/common/src/commonMain/resources/MR/files/wordlist_en_eff.txt b/common/src/commonMain/composeResources/files/wordlist_en_eff.txt similarity index 100% rename from common/src/commonMain/resources/MR/files/wordlist_en_eff.txt rename to common/src/commonMain/composeResources/files/wordlist_en_eff.txt diff --git a/common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Bold.ttf b/common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Bold.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Bold.ttf rename to common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Bold.ttf diff --git a/common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-BoldItalic.ttf b/common/src/commonMain/composeResources/font/AtkinsonHyperlegible-BoldItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-BoldItalic.ttf rename to common/src/commonMain/composeResources/font/AtkinsonHyperlegible-BoldItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Italic.ttf b/common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Italic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Italic.ttf rename to common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Italic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Regular.ttf b/common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Regular.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/AtkinsonHyperlegible-Regular.ttf rename to common/src/commonMain/composeResources/font/AtkinsonHyperlegible-Regular.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Black.ttf b/common/src/commonMain/composeResources/font/NotoSans-Black.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Black.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Black.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-BlackItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-BlackItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-BlackItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-BlackItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Bold.ttf b/common/src/commonMain/composeResources/font/NotoSans-Bold.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Bold.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Bold.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-BoldItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-BoldItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-BoldItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-BoldItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-ExtraBold.ttf b/common/src/commonMain/composeResources/font/NotoSans-ExtraBold.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-ExtraBold.ttf rename to common/src/commonMain/composeResources/font/NotoSans-ExtraBold.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-ExtraBoldItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-ExtraBoldItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-ExtraBoldItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-ExtraBoldItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-ExtraLight.ttf b/common/src/commonMain/composeResources/font/NotoSans-ExtraLight.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-ExtraLight.ttf rename to common/src/commonMain/composeResources/font/NotoSans-ExtraLight.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-ExtraLightItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-ExtraLightItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-ExtraLightItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-ExtraLightItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Italic.ttf b/common/src/commonMain/composeResources/font/NotoSans-Italic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Italic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Italic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Light.ttf b/common/src/commonMain/composeResources/font/NotoSans-Light.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Light.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Light.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-LightItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-LightItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-LightItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-LightItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Medium.ttf b/common/src/commonMain/composeResources/font/NotoSans-Medium.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Medium.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Medium.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-MediumItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-MediumItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-MediumItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-MediumItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Regular.ttf b/common/src/commonMain/composeResources/font/NotoSans-Regular.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Regular.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Regular.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-SemiBold.ttf b/common/src/commonMain/composeResources/font/NotoSans-SemiBold.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-SemiBold.ttf rename to common/src/commonMain/composeResources/font/NotoSans-SemiBold.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-SemiBoldItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-SemiBoldItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-SemiBoldItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-SemiBoldItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-Thin.ttf b/common/src/commonMain/composeResources/font/NotoSans-Thin.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-Thin.ttf rename to common/src/commonMain/composeResources/font/NotoSans-Thin.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSans-ThinItalic.ttf b/common/src/commonMain/composeResources/font/NotoSans-ThinItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSans-ThinItalic.ttf rename to common/src/commonMain/composeResources/font/NotoSans-ThinItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/NotoSansMono.ttf b/common/src/commonMain/composeResources/font/NotoSansMono.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/NotoSansMono.ttf rename to common/src/commonMain/composeResources/font/NotoSansMono.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Black.ttf b/common/src/commonMain/composeResources/font/Roboto-Black.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Black.ttf rename to common/src/commonMain/composeResources/font/Roboto-Black.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-BlackItalic.ttf b/common/src/commonMain/composeResources/font/Roboto-BlackItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-BlackItalic.ttf rename to common/src/commonMain/composeResources/font/Roboto-BlackItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Bold.ttf b/common/src/commonMain/composeResources/font/Roboto-Bold.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Bold.ttf rename to common/src/commonMain/composeResources/font/Roboto-Bold.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-BoldItalic.ttf b/common/src/commonMain/composeResources/font/Roboto-BoldItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-BoldItalic.ttf rename to common/src/commonMain/composeResources/font/Roboto-BoldItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Italic.ttf b/common/src/commonMain/composeResources/font/Roboto-Italic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Italic.ttf rename to common/src/commonMain/composeResources/font/Roboto-Italic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Light.ttf b/common/src/commonMain/composeResources/font/Roboto-Light.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Light.ttf rename to common/src/commonMain/composeResources/font/Roboto-Light.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-LightItalic.ttf b/common/src/commonMain/composeResources/font/Roboto-LightItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-LightItalic.ttf rename to common/src/commonMain/composeResources/font/Roboto-LightItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Medium.ttf b/common/src/commonMain/composeResources/font/Roboto-Medium.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Medium.ttf rename to common/src/commonMain/composeResources/font/Roboto-Medium.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-MediumItalic.ttf b/common/src/commonMain/composeResources/font/Roboto-MediumItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-MediumItalic.ttf rename to common/src/commonMain/composeResources/font/Roboto-MediumItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Regular.ttf b/common/src/commonMain/composeResources/font/Roboto-Regular.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Regular.ttf rename to common/src/commonMain/composeResources/font/Roboto-Regular.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-Thin.ttf b/common/src/commonMain/composeResources/font/Roboto-Thin.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-Thin.ttf rename to common/src/commonMain/composeResources/font/Roboto-Thin.ttf diff --git a/common/src/commonMain/resources/MR/fonts/Roboto-ThinItalic.ttf b/common/src/commonMain/composeResources/font/Roboto-ThinItalic.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/Roboto-ThinItalic.ttf rename to common/src/commonMain/composeResources/font/Roboto-ThinItalic.ttf diff --git a/common/src/commonMain/resources/MR/fonts/RobotoMono.ttf b/common/src/commonMain/composeResources/font/RobotoMono.ttf similarity index 100% rename from common/src/commonMain/resources/MR/fonts/RobotoMono.ttf rename to common/src/commonMain/composeResources/font/RobotoMono.ttf diff --git a/common/src/commonMain/resources/MR/af-rZA/plurals.xml b/common/src/commonMain/composeResources/values-af-rZA/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/af-rZA/plurals.xml rename to common/src/commonMain/composeResources/values-af-rZA/plurals.xml diff --git a/common/src/commonMain/resources/MR/af-rZA/strings.xml b/common/src/commonMain/composeResources/values-af-rZA/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/af-rZA/strings.xml rename to common/src/commonMain/composeResources/values-af-rZA/strings.xml diff --git a/common/src/commonMain/resources/MR/ar-rSA/plurals.xml b/common/src/commonMain/composeResources/values-ar-rSA/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ar-rSA/plurals.xml rename to common/src/commonMain/composeResources/values-ar-rSA/plurals.xml diff --git a/common/src/commonMain/resources/MR/ar-rSA/strings.xml b/common/src/commonMain/composeResources/values-ar-rSA/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ar-rSA/strings.xml rename to common/src/commonMain/composeResources/values-ar-rSA/strings.xml diff --git a/common/src/commonMain/resources/MR/ca-rES/plurals.xml b/common/src/commonMain/composeResources/values-ca-rES/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ca-rES/plurals.xml rename to common/src/commonMain/composeResources/values-ca-rES/plurals.xml diff --git a/common/src/commonMain/resources/MR/ca-rES/strings.xml b/common/src/commonMain/composeResources/values-ca-rES/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ca-rES/strings.xml rename to common/src/commonMain/composeResources/values-ca-rES/strings.xml diff --git a/common/src/commonMain/resources/MR/cs-rCZ/plurals.xml b/common/src/commonMain/composeResources/values-cs-rCZ/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/cs-rCZ/plurals.xml rename to common/src/commonMain/composeResources/values-cs-rCZ/plurals.xml diff --git a/common/src/commonMain/resources/MR/cs-rCZ/strings.xml b/common/src/commonMain/composeResources/values-cs-rCZ/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/cs-rCZ/strings.xml rename to common/src/commonMain/composeResources/values-cs-rCZ/strings.xml diff --git a/common/src/commonMain/resources/MR/da-rDK/plurals.xml b/common/src/commonMain/composeResources/values-da-rDK/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/da-rDK/plurals.xml rename to common/src/commonMain/composeResources/values-da-rDK/plurals.xml diff --git a/common/src/commonMain/resources/MR/da-rDK/strings.xml b/common/src/commonMain/composeResources/values-da-rDK/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/da-rDK/strings.xml rename to common/src/commonMain/composeResources/values-da-rDK/strings.xml diff --git a/common/src/commonMain/resources/MR/de-rDE/plurals.xml b/common/src/commonMain/composeResources/values-de-rDE/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/de-rDE/plurals.xml rename to common/src/commonMain/composeResources/values-de-rDE/plurals.xml diff --git a/common/src/commonMain/resources/MR/de-rDE/strings.xml b/common/src/commonMain/composeResources/values-de-rDE/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/de-rDE/strings.xml rename to common/src/commonMain/composeResources/values-de-rDE/strings.xml diff --git a/common/src/commonMain/resources/MR/el-rGR/plurals.xml b/common/src/commonMain/composeResources/values-el-rGR/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/el-rGR/plurals.xml rename to common/src/commonMain/composeResources/values-el-rGR/plurals.xml diff --git a/common/src/commonMain/resources/MR/el-rGR/strings.xml b/common/src/commonMain/composeResources/values-el-rGR/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/el-rGR/strings.xml rename to common/src/commonMain/composeResources/values-el-rGR/strings.xml diff --git a/common/src/commonMain/resources/MR/en-rGB/plurals.xml b/common/src/commonMain/composeResources/values-en-rGB/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/en-rGB/plurals.xml rename to common/src/commonMain/composeResources/values-en-rGB/plurals.xml diff --git a/common/src/commonMain/resources/MR/en-rGB/strings.xml b/common/src/commonMain/composeResources/values-en-rGB/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/en-rGB/strings.xml rename to common/src/commonMain/composeResources/values-en-rGB/strings.xml diff --git a/common/src/commonMain/resources/MR/en-rUS/plurals.xml b/common/src/commonMain/composeResources/values-en-rUS/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/en-rUS/plurals.xml rename to common/src/commonMain/composeResources/values-en-rUS/plurals.xml diff --git a/common/src/commonMain/resources/MR/en-rUS/strings.xml b/common/src/commonMain/composeResources/values-en-rUS/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/en-rUS/strings.xml rename to common/src/commonMain/composeResources/values-en-rUS/strings.xml diff --git a/common/src/commonMain/resources/MR/es-rES/plurals.xml b/common/src/commonMain/composeResources/values-es-rES/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/es-rES/plurals.xml rename to common/src/commonMain/composeResources/values-es-rES/plurals.xml diff --git a/common/src/commonMain/resources/MR/es-rES/strings.xml b/common/src/commonMain/composeResources/values-es-rES/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/es-rES/strings.xml rename to common/src/commonMain/composeResources/values-es-rES/strings.xml diff --git a/common/src/commonMain/resources/MR/fi-rFI/plurals.xml b/common/src/commonMain/composeResources/values-fi-rFI/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/fi-rFI/plurals.xml rename to common/src/commonMain/composeResources/values-fi-rFI/plurals.xml diff --git a/common/src/commonMain/resources/MR/fi-rFI/strings.xml b/common/src/commonMain/composeResources/values-fi-rFI/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/fi-rFI/strings.xml rename to common/src/commonMain/composeResources/values-fi-rFI/strings.xml diff --git a/common/src/commonMain/resources/MR/fr-rFR/plurals.xml b/common/src/commonMain/composeResources/values-fr-rFR/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/fr-rFR/plurals.xml rename to common/src/commonMain/composeResources/values-fr-rFR/plurals.xml diff --git a/common/src/commonMain/resources/MR/fr-rFR/strings.xml b/common/src/commonMain/composeResources/values-fr-rFR/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/fr-rFR/strings.xml rename to common/src/commonMain/composeResources/values-fr-rFR/strings.xml diff --git a/common/src/commonMain/resources/MR/hu-rHU/plurals.xml b/common/src/commonMain/composeResources/values-hu-rHU/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/hu-rHU/plurals.xml rename to common/src/commonMain/composeResources/values-hu-rHU/plurals.xml diff --git a/common/src/commonMain/resources/MR/hu-rHU/strings.xml b/common/src/commonMain/composeResources/values-hu-rHU/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/hu-rHU/strings.xml rename to common/src/commonMain/composeResources/values-hu-rHU/strings.xml diff --git a/common/src/commonMain/resources/MR/it-rIT/plurals.xml b/common/src/commonMain/composeResources/values-it-rIT/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/it-rIT/plurals.xml rename to common/src/commonMain/composeResources/values-it-rIT/plurals.xml diff --git a/common/src/commonMain/resources/MR/it-rIT/strings.xml b/common/src/commonMain/composeResources/values-it-rIT/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/it-rIT/strings.xml rename to common/src/commonMain/composeResources/values-it-rIT/strings.xml diff --git a/common/src/commonMain/resources/MR/iw-rIL/plurals.xml b/common/src/commonMain/composeResources/values-iw-rIL/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/iw-rIL/plurals.xml rename to common/src/commonMain/composeResources/values-iw-rIL/plurals.xml diff --git a/common/src/commonMain/resources/MR/iw-rIL/strings.xml b/common/src/commonMain/composeResources/values-iw-rIL/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/iw-rIL/strings.xml rename to common/src/commonMain/composeResources/values-iw-rIL/strings.xml diff --git a/common/src/commonMain/resources/MR/ja-rJP/plurals.xml b/common/src/commonMain/composeResources/values-ja-rJP/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ja-rJP/plurals.xml rename to common/src/commonMain/composeResources/values-ja-rJP/plurals.xml diff --git a/common/src/commonMain/resources/MR/ja-rJP/strings.xml b/common/src/commonMain/composeResources/values-ja-rJP/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ja-rJP/strings.xml rename to common/src/commonMain/composeResources/values-ja-rJP/strings.xml diff --git a/common/src/commonMain/resources/MR/ko-rKR/plurals.xml b/common/src/commonMain/composeResources/values-ko-rKR/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ko-rKR/plurals.xml rename to common/src/commonMain/composeResources/values-ko-rKR/plurals.xml diff --git a/common/src/commonMain/resources/MR/ko-rKR/strings.xml b/common/src/commonMain/composeResources/values-ko-rKR/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ko-rKR/strings.xml rename to common/src/commonMain/composeResources/values-ko-rKR/strings.xml diff --git a/common/src/commonMain/resources/MR/nl-rNL/plurals.xml b/common/src/commonMain/composeResources/values-nl-rNL/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/nl-rNL/plurals.xml rename to common/src/commonMain/composeResources/values-nl-rNL/plurals.xml diff --git a/common/src/commonMain/resources/MR/nl-rNL/strings.xml b/common/src/commonMain/composeResources/values-nl-rNL/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/nl-rNL/strings.xml rename to common/src/commonMain/composeResources/values-nl-rNL/strings.xml diff --git a/common/src/commonMain/resources/MR/no-rNO/plurals.xml b/common/src/commonMain/composeResources/values-no-rNO/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/no-rNO/plurals.xml rename to common/src/commonMain/composeResources/values-no-rNO/plurals.xml diff --git a/common/src/commonMain/resources/MR/no-rNO/strings.xml b/common/src/commonMain/composeResources/values-no-rNO/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/no-rNO/strings.xml rename to common/src/commonMain/composeResources/values-no-rNO/strings.xml diff --git a/common/src/commonMain/resources/MR/pl-rPL/plurals.xml b/common/src/commonMain/composeResources/values-pl-rPL/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/pl-rPL/plurals.xml rename to common/src/commonMain/composeResources/values-pl-rPL/plurals.xml diff --git a/common/src/commonMain/resources/MR/pl-rPL/strings.xml b/common/src/commonMain/composeResources/values-pl-rPL/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/pl-rPL/strings.xml rename to common/src/commonMain/composeResources/values-pl-rPL/strings.xml diff --git a/common/src/commonMain/resources/MR/pt-rBR/plurals.xml b/common/src/commonMain/composeResources/values-pt-rBR/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/pt-rBR/plurals.xml rename to common/src/commonMain/composeResources/values-pt-rBR/plurals.xml diff --git a/common/src/commonMain/resources/MR/pt-rBR/strings.xml b/common/src/commonMain/composeResources/values-pt-rBR/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/pt-rBR/strings.xml rename to common/src/commonMain/composeResources/values-pt-rBR/strings.xml diff --git a/common/src/commonMain/resources/MR/pt-rPT/plurals.xml b/common/src/commonMain/composeResources/values-pt-rPT/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/pt-rPT/plurals.xml rename to common/src/commonMain/composeResources/values-pt-rPT/plurals.xml diff --git a/common/src/commonMain/resources/MR/pt-rPT/strings.xml b/common/src/commonMain/composeResources/values-pt-rPT/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/pt-rPT/strings.xml rename to common/src/commonMain/composeResources/values-pt-rPT/strings.xml diff --git a/common/src/commonMain/resources/MR/ro-rRO/plurals.xml b/common/src/commonMain/composeResources/values-ro-rRO/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ro-rRO/plurals.xml rename to common/src/commonMain/composeResources/values-ro-rRO/plurals.xml diff --git a/common/src/commonMain/resources/MR/ro-rRO/strings.xml b/common/src/commonMain/composeResources/values-ro-rRO/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ro-rRO/strings.xml rename to common/src/commonMain/composeResources/values-ro-rRO/strings.xml diff --git a/common/src/commonMain/resources/MR/ru-rRU/plurals.xml b/common/src/commonMain/composeResources/values-ru-rRU/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/ru-rRU/plurals.xml rename to common/src/commonMain/composeResources/values-ru-rRU/plurals.xml diff --git a/common/src/commonMain/resources/MR/ru-rRU/strings.xml b/common/src/commonMain/composeResources/values-ru-rRU/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/ru-rRU/strings.xml rename to common/src/commonMain/composeResources/values-ru-rRU/strings.xml diff --git a/common/src/commonMain/resources/MR/sr-rSP/plurals.xml b/common/src/commonMain/composeResources/values-sr-rSP/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/sr-rSP/plurals.xml rename to common/src/commonMain/composeResources/values-sr-rSP/plurals.xml diff --git a/common/src/commonMain/resources/MR/sr-rSP/strings.xml b/common/src/commonMain/composeResources/values-sr-rSP/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/sr-rSP/strings.xml rename to common/src/commonMain/composeResources/values-sr-rSP/strings.xml diff --git a/common/src/commonMain/resources/MR/sv-rSE/plurals.xml b/common/src/commonMain/composeResources/values-sv-rSE/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/sv-rSE/plurals.xml rename to common/src/commonMain/composeResources/values-sv-rSE/plurals.xml diff --git a/common/src/commonMain/resources/MR/sv-rSE/strings.xml b/common/src/commonMain/composeResources/values-sv-rSE/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/sv-rSE/strings.xml rename to common/src/commonMain/composeResources/values-sv-rSE/strings.xml diff --git a/common/src/commonMain/resources/MR/tr-rTR/plurals.xml b/common/src/commonMain/composeResources/values-tr-rTR/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/tr-rTR/plurals.xml rename to common/src/commonMain/composeResources/values-tr-rTR/plurals.xml diff --git a/common/src/commonMain/resources/MR/tr-rTR/strings.xml b/common/src/commonMain/composeResources/values-tr-rTR/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/tr-rTR/strings.xml rename to common/src/commonMain/composeResources/values-tr-rTR/strings.xml diff --git a/common/src/commonMain/resources/MR/uk-rUA/plurals.xml b/common/src/commonMain/composeResources/values-uk-rUA/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/uk-rUA/plurals.xml rename to common/src/commonMain/composeResources/values-uk-rUA/plurals.xml diff --git a/common/src/commonMain/resources/MR/uk-rUA/strings.xml b/common/src/commonMain/composeResources/values-uk-rUA/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/uk-rUA/strings.xml rename to common/src/commonMain/composeResources/values-uk-rUA/strings.xml diff --git a/common/src/commonMain/resources/MR/vi-rVN/plurals.xml b/common/src/commonMain/composeResources/values-vi-rVN/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/vi-rVN/plurals.xml rename to common/src/commonMain/composeResources/values-vi-rVN/plurals.xml diff --git a/common/src/commonMain/resources/MR/vi-rVN/strings.xml b/common/src/commonMain/composeResources/values-vi-rVN/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/vi-rVN/strings.xml rename to common/src/commonMain/composeResources/values-vi-rVN/strings.xml diff --git a/common/src/commonMain/resources/MR/zh-rCN/plurals.xml b/common/src/commonMain/composeResources/values-zh-rCN/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/zh-rCN/plurals.xml rename to common/src/commonMain/composeResources/values-zh-rCN/plurals.xml diff --git a/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/common/src/commonMain/composeResources/values-zh-rCN/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/zh-rCN/strings.xml rename to common/src/commonMain/composeResources/values-zh-rCN/strings.xml diff --git a/common/src/commonMain/resources/MR/zh-rTW/plurals.xml b/common/src/commonMain/composeResources/values-zh-rTW/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/zh-rTW/plurals.xml rename to common/src/commonMain/composeResources/values-zh-rTW/plurals.xml diff --git a/common/src/commonMain/resources/MR/zh-rTW/strings.xml b/common/src/commonMain/composeResources/values-zh-rTW/strings.xml similarity index 100% rename from common/src/commonMain/resources/MR/zh-rTW/strings.xml rename to common/src/commonMain/composeResources/values-zh-rTW/strings.xml diff --git a/common/src/commonMain/resources/MR/base/plurals.xml b/common/src/commonMain/composeResources/values/plurals.xml similarity index 100% rename from common/src/commonMain/resources/MR/base/plurals.xml rename to common/src/commonMain/composeResources/values/plurals.xml diff --git a/common/src/commonMain/resources/MR/base/strings.xml b/common/src/commonMain/composeResources/values/strings.xml similarity index 98% rename from common/src/commonMain/resources/MR/base/strings.xml rename to common/src/commonMain/composeResources/values/strings.xml index 4b19ad1e..2b878719 100644 --- a/common/src/commonMain/resources/MR/base/strings.xml +++ b/common/src/commonMain/composeResources/values/strings.xml @@ -869,15 +869,15 @@ Pwned Passwords Passwords that have been exposed in data breaches. Such passwords should be changed immediately. Reused Passwords - Don\'t use the same password on multiple websites. Generate unique passwords to improve security. + Don't use the same password on multiple websites. Generate unique passwords to improve security. Vulnerable Accounts Sites that were affected by a data breach since you last changed a password. Change your password to keep your account safe. Unsecure Websites Change the URLs that use HTTP protocol to use HTTPS protocol, as the latter utilizes the most advanced encryption available. Inactive two-factor authentication - Sites that have two-factor authentication available but you haven\'t set it up yet. + Sites that have two-factor authentication available but you haven't set it up yet. Available Passkeys - Sites that have passkey available but you haven\'t set it up yet. It\'s simpler and more secure then a password. + Sites that have passkey available but you haven't set it up yet. It's simpler and more secure then a password. Incomplete Items Helps you identify missing or incomplete data in your vault. This can refer to identities with missing names or logins without usernames. Expiring Items @@ -909,14 +909,14 @@ Contact us Your message - Use English to ensure that your feedback doesn\'t get misunderstood. - We appreciate the time that you spend sending us a message. Your message goes directly to us and we use it to troubleshoot issues, make product improvements and fix problems. While we may not reply to every report, we\'re reviewing and working on improvements & fixing issues as fast as we can. + Use English to ensure that your feedback doesn't get misunderstood. + We appreciate the time that you spend sending us a message. Your message goes directly to us and we use it to troubleshoot issues, make product improvements and fix problems. While we may not reply to every report, we're reviewing and working on improvements & fixing issues as fast as we can. Accounts Add account Team behind the app - I\'m a Software engineer from Ukraine. I specialize on app design and development. + I'm a Software engineer from Ukraine. I specialize on app design and development. Follow me Search @@ -1023,7 +1023,7 @@ Persist vault key on a disk Vault key is persisted on an internal storage Vault is locked after the app is unloaded from the memory - Storing a vault key on a disk is a security risk. If the device\'s internal storage is compromised, the attacker will gain access to the local vault data. + Storing a vault key on a disk is a security risk. If the device's internal storage is compromised, the attacker will gain access to the local vault data. Permissions Features overview URL overrides @@ -1037,7 +1037,7 @@ Keep the screen on while viewing items Autofill service Use the Android Autofill Framework to assist in filling login information into other apps on the device - Some Xiaomi devices require you to manually allow the \"Display pop-up windows while running in the background\" permission. Please open the settings and verify that it is granted. + Some Xiaomi devices require you to manually allow the "Display pop-up windows while running in the background" permission. Please open the settings and verify that it is granted. Auto-copy one-time passwords When filling a login information, automatically copy one-time passwords Inline suggestions @@ -1099,7 +1099,7 @@ Filter Filter by folder, organization, type etc. Multiple keywords - Search by \'bitw test\' to find your \'Bitwarden Test Account\' item. + Search by 'bitw test' to find your 'Bitwarden Test Account' item. Watchtower Pwned passwords Find items with exposed in data breaches passwords. @@ -1134,7 +1134,7 @@ Vault The Vault is encrypted using a Key, derived from the App password using following steps: The Salt and the Hash is then stored locally on a device, to later generate a master key to unlock the vault. - Unlocking a Vault means storing a correct Key in a device\'s RAM, gaining an ability to read and modify encrypted Vault. + Unlocking a Vault means storing a correct Key in a device's RAM, gaining an ability to read and modify encrypted Vault. Remote data Remote data is stored on Bitwarden servers with zero-knowledge encryption. diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/OutOfMemoryKdfException.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/OutOfMemoryKdfException.kt index 2b0dcf12..f445d9e3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/OutOfMemoryKdfException.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/OutOfMemoryKdfException.kt @@ -2,11 +2,12 @@ package com.artemchep.keyguard.common.exception import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* open class OutOfMemoryKdfException( m: String?, e: Throwable?, ) : Exception(m, e), Readable { override val title: TextHolder - get() = TextHolder.Res(Res.strings.error_failed_generate_kdf_hash_oom) + get() = TextHolder.Res(Res.string.error_failed_generate_kdf_hash_oom) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/PasswordMismatchException.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/PasswordMismatchException.kt index 0b923e89..3fe4ad33 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/PasswordMismatchException.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/exception/PasswordMismatchException.kt @@ -3,11 +3,12 @@ package com.artemchep.keyguard.common.exception import com.artemchep.keyguard.common.model.NoAnalytics import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* class PasswordMismatchException( ) : RuntimeException("Invalid password"), Readable, NoAnalytics { override val title: TextHolder - get() = TextHolder.Res(Res.strings.error_incorrect_password) + get() = TextHolder.Res(Res.string.error_incorrect_password) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/CreditCardType.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/CreditCardType.kt index 8fcf080b..74d3ffa7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/CreditCardType.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/CreditCardType.kt @@ -23,8 +23,9 @@ package com.artemchep.keyguard.common.model import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.ImageResource +import com.artemchep.keyguard.res.* import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.DrawableResource // Thanks to // https://github.com/bendrucker/creditcards-types/ @@ -38,7 +39,7 @@ import kotlinx.collections.immutable.persistentListOf data class CreditCardType( val name: String, - val icon: ImageResource? = null, + val icon: DrawableResource? = null, val digits: IntRange = 16..16, val csc: IntRange = 3..3, /** @@ -61,7 +62,7 @@ data class CreditCardType( val creditCardVisa = CreditCardType( name = "Visa", - icon = Res.images.ic_card_visa, + icon = Res.drawable.ic_card_visa, digits = 13..19, pattern = "^4\\d{12}(\\d{3}|\\d{6})?\$".toRegex(), eagerPattern = "^4".toRegex(), @@ -70,7 +71,7 @@ val creditCardVisa = CreditCardType( val creditCardAmericanExpress = CreditCardType( name = "American Express", - icon = Res.images.ic_card_amex, + icon = Res.drawable.ic_card_amex, digits = 15..15, csc = 4..4, pattern = "^3[47]\\d{13}\$".toRegex(), @@ -86,7 +87,7 @@ val creditCardDankort = CreditCardType( val creditCardDinersClub = CreditCardType( name = "Diners Club", - icon = Res.images.ic_card_diners, + icon = Res.drawable.ic_card_diners, digits = 14..19, pattern = "^3(0[0-5]|[68]\\d)\\d{11,16}\$".toRegex(), eagerPattern = "^3(0|[68])".toRegex(), @@ -95,14 +96,14 @@ val creditCardDinersClub = CreditCardType( val creditCardDiscover = CreditCardType( name = "Discover", - icon = Res.images.ic_card_discover, + icon = Res.drawable.ic_card_discover, pattern = "^6(011(0[0-9]|[2-4]\\d|74|7[7-9]|8[6-9]|9[0-9])|4[4-9]\\d{3}|5\\d{4})\\d{10}\$".toRegex(), eagerPattern = "^6(011(0[0-9]|[2-4]|74|7[7-9]|8[6-9]|9[0-9])|4[4-9]|5)".toRegex(), ) val creditCardElo = CreditCardType( name = "Elo", - icon = Res.images.ic_card_elo, + icon = Res.drawable.ic_card_elo, pattern = "^(4[035]|5[0]|6[235])(6[7263]|9[90]|1[2416]|7[736]|8[9]|0[04579]|5[0])([0-9])([0-9])\\d{10}\$".toRegex(), eagerPattern = "^(4[035]|5[0]|6[235])(6[7263]|9[90]|1[2416]|7[736]|8[9]|0[04579]|5[0])([0-9])([0-9])".toRegex(), groupPattern = "(\\d{1,4})(\\d{1,4})?(\\d{1,4})?(\\d{1,4})?(\\d{1,3})?".toRegex(), @@ -116,7 +117,7 @@ val creditCardForbrugsforeningen = CreditCardType( val creditCardJCB = CreditCardType( name = "JCB", - icon = Res.images.ic_card_jcb, + icon = Res.drawable.ic_card_jcb, pattern = "^35\\d{14}\$".toRegex(), eagerPattern = "^35".toRegex(), ) @@ -130,7 +131,7 @@ val creditCardMada = CreditCardType( val creditCardMaestro = CreditCardType( name = "Maestro", - icon = Res.images.ic_card_maestro, + icon = Res.drawable.ic_card_maestro, digits = 12..19, pattern = "^(?:5[06789]\\d\\d|(?!6011[0234])(?!60117[4789])(?!60118[6789])(?!60119)(?!64[456789])(?!65)6\\d{3})\\d{8,15}\$".toRegex(), eagerPattern = "^(5(018|0[23]|[68])|6[37]|60111|60115|60117([56]|7[56])|60118[0-5]|64[0-3]|66)".toRegex(), @@ -139,7 +140,7 @@ val creditCardMaestro = CreditCardType( val creditCardMastercard = CreditCardType( name = "Mastercard", - icon = Res.images.ic_card_mastercard, + icon = Res.drawable.ic_card_mastercard, pattern = "^(5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)\\d{12}\$".toRegex(), eagerPattern = "^(2[3-7]|22[2-9]|5[1-5])".toRegex(), ) @@ -153,7 +154,7 @@ val creditCardMeeza = CreditCardType( val creditCardMir = CreditCardType( name = "Mir", - icon = Res.images.ic_card_mir, + icon = Res.drawable.ic_card_mir, pattern = "^220[0-4]\\d{12}\$".toRegex(), eagerPattern = "^220[0-4]".toRegex(), groupPattern = "(\\d{1,4})(\\d{1,4})?(\\d{1,4})?(\\d{1,4})?(\\d{1,3})?".toRegex(), @@ -175,7 +176,7 @@ val creditCardUATP = CreditCardType( val creditCardUnionPay = CreditCardType( name = "UnionPay", - icon = Res.images.ic_card_unionpay, + icon = Res.drawable.ic_card_unionpay, luhn = false, pattern = "^62[0-5]\\d{13,16}\$".toRegex(), eagerPattern = "^62".toRegex(), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DFilter.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DFilter.kt index 434492a1..b369fc28 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DFilter.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DFilter.kt @@ -33,6 +33,7 @@ import com.artemchep.keyguard.feature.home.vault.component.obscurePassword import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.provider.bitwarden.entity.HibpBreachGroup import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.KeyguardAttachment import com.artemchep.keyguard.ui.icons.KeyguardAuthReprompt import com.artemchep.keyguard.ui.icons.KeyguardDuplicateWebsites @@ -463,7 +464,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.one_time_password + title = Res.string.one_time_password .let(TextHolder::Res), icon = Icons.Outlined.KeyguardTwoFa, ) @@ -486,7 +487,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.attachments + title = Res.string.attachments .let(TextHolder::Res), icon = Icons.Outlined.KeyguardAttachment, ) @@ -509,7 +510,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.passkeys + title = Res.string.passkeys .let(TextHolder::Res), icon = Icons.Outlined.Key, ) @@ -560,11 +561,11 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( title = when (score) { - PasswordStrength.Score.Weak -> Res.strings.passwords_weak_label - PasswordStrength.Score.Fair -> Res.strings.passwords_fair_label - PasswordStrength.Score.Good -> Res.strings.passwords_good_label - PasswordStrength.Score.Strong -> Res.strings.passwords_strong_label - PasswordStrength.Score.VeryStrong -> Res.strings.passwords_very_strong_label + PasswordStrength.Score.Weak -> Res.string.passwords_weak_label + PasswordStrength.Score.Fair -> Res.string.passwords_fair_label + PasswordStrength.Score.Good -> Res.string.passwords_good_label + PasswordStrength.Score.Strong -> Res.string.passwords_strong_label + PasswordStrength.Score.VeryStrong -> Res.string.passwords_very_strong_label } .let(TextHolder::Res), icon = Icons.Outlined.Password, @@ -588,7 +589,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_reused_passwords_title + title = Res.string.watchtower_item_reused_passwords_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardReusedPassword, ) @@ -670,7 +671,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_pwned_passwords_title + title = Res.string.watchtower_item_pwned_passwords_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardPwnedPassword, ) @@ -746,7 +747,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_vulnerable_accounts_title + title = Res.string.watchtower_item_vulnerable_accounts_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardPwnedWebsites, ) @@ -816,7 +817,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_incomplete_items_title + title = Res.string.watchtower_item_incomplete_items_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardIncompleteItems, ) @@ -873,7 +874,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_expiring_items_title + title = Res.string.watchtower_item_expiring_items_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardExpiringItems, ) @@ -931,7 +932,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_unsecure_websites_title + title = Res.string.watchtower_item_unsecure_websites_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardUnsecureWebsites, ) @@ -990,7 +991,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_inactive_2fa_title + title = Res.string.watchtower_item_inactive_2fa_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardTwoFa, ) @@ -1095,7 +1096,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_inactive_passkey_title + title = Res.string.watchtower_item_inactive_passkey_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardPasskey, ) @@ -1212,7 +1213,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.watchtower_item_duplicate_websites_title + title = Res.string.watchtower_item_duplicate_websites_title .let(TextHolder::Res), icon = Icons.Outlined.KeyguardDuplicateWebsites, ) @@ -1286,7 +1287,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.filter_pending_items + title = Res.string.filter_pending_items .let(TextHolder::Res), icon = Icons.Outlined.KeyguardPendingSyncItems, ) @@ -1320,7 +1321,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.filter_auth_reprompt_items + title = Res.string.filter_auth_reprompt_items .let(TextHolder::Res), icon = Icons.Outlined.KeyguardAuthReprompt, ) @@ -1345,7 +1346,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.filter_failed_items + title = Res.string.filter_failed_items .let(TextHolder::Res), icon = Icons.Outlined.KeyguardFailedItems, ) @@ -1377,7 +1378,7 @@ sealed interface DFilter { @Transient override val content = PrimitiveSimple.Content( - title = Res.strings.ignored_alerts + title = Res.string.ignored_alerts .let(TextHolder::Res), icon = Icons.Outlined.KeyguardIgnoredAlerts, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSecret.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSecret.kt index 986946cd..d6855180 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSecret.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSecret.kt @@ -21,6 +21,7 @@ import com.artemchep.keyguard.feature.favicon.FaviconUrl import com.artemchep.keyguard.provider.bitwarden.usecase.util.canDelete import com.artemchep.keyguard.provider.bitwarden.usecase.util.canEdit import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.KeyguardNote import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.icons.generateAccentColors @@ -400,50 +401,50 @@ fun DSecret.Type.iconImageVector() = when (this) { } fun DSecret.Type.titleH() = when (this) { - DSecret.Type.Login -> Res.strings.cipher_type_login - DSecret.Type.Card -> Res.strings.cipher_type_card - DSecret.Type.Identity -> Res.strings.cipher_type_identity - DSecret.Type.SecureNote -> Res.strings.cipher_type_note - DSecret.Type.None -> Res.strings.cipher_type_unknown + DSecret.Type.Login -> Res.string.cipher_type_login + DSecret.Type.Card -> Res.string.cipher_type_card + DSecret.Type.Identity -> Res.string.cipher_type_identity + DSecret.Type.SecureNote -> Res.string.cipher_type_note + DSecret.Type.None -> Res.string.cipher_type_unknown } fun DSecret.Uri.MatchType.titleH() = when (this) { - DSecret.Uri.MatchType.Domain -> Res.strings.uri_match_detection_domain_title - DSecret.Uri.MatchType.Host -> Res.strings.uri_match_detection_host_title - DSecret.Uri.MatchType.StartsWith -> Res.strings.uri_match_detection_startswith_title - DSecret.Uri.MatchType.Exact -> Res.strings.uri_match_detection_exact_title - DSecret.Uri.MatchType.RegularExpression -> Res.strings.uri_match_detection_regex_title - DSecret.Uri.MatchType.Never -> Res.strings.uri_match_detection_never_title + DSecret.Uri.MatchType.Domain -> Res.string.uri_match_detection_domain_title + DSecret.Uri.MatchType.Host -> Res.string.uri_match_detection_host_title + DSecret.Uri.MatchType.StartsWith -> Res.string.uri_match_detection_startswith_title + DSecret.Uri.MatchType.Exact -> Res.string.uri_match_detection_exact_title + DSecret.Uri.MatchType.RegularExpression -> Res.string.uri_match_detection_regex_title + DSecret.Uri.MatchType.Never -> Res.string.uri_match_detection_never_title } fun DSecret.Field.LinkedId.titleH() = when (this) { - DSecret.Field.LinkedId.Login_Username -> Res.strings.username - DSecret.Field.LinkedId.Login_Password -> Res.strings.password - DSecret.Field.LinkedId.Card_CardholderName -> Res.strings.cardholder_name - DSecret.Field.LinkedId.Card_ExpMonth -> Res.strings.card_expiry_month - DSecret.Field.LinkedId.Card_ExpYear -> Res.strings.card_expiry_year - DSecret.Field.LinkedId.Card_Code -> Res.strings.card_cvv - DSecret.Field.LinkedId.Card_Brand -> Res.strings.card_type - DSecret.Field.LinkedId.Card_Number -> Res.strings.card_number - DSecret.Field.LinkedId.Identity_Title -> Res.strings.identity_first_name - DSecret.Field.LinkedId.Identity_MiddleName -> Res.strings.identity_middle_name - DSecret.Field.LinkedId.Identity_Address1 -> Res.strings.address1 - DSecret.Field.LinkedId.Identity_Address2 -> Res.strings.address2 - DSecret.Field.LinkedId.Identity_Address3 -> Res.strings.address3 - DSecret.Field.LinkedId.Identity_City -> Res.strings.city - DSecret.Field.LinkedId.Identity_State -> Res.strings.state - DSecret.Field.LinkedId.Identity_PostalCode -> Res.strings.postal_code - DSecret.Field.LinkedId.Identity_Country -> Res.strings.country - DSecret.Field.LinkedId.Identity_Company -> Res.strings.company - DSecret.Field.LinkedId.Identity_Email -> Res.strings.email - DSecret.Field.LinkedId.Identity_Phone -> Res.strings.phone_number - DSecret.Field.LinkedId.Identity_Ssn -> Res.strings.ssn - DSecret.Field.LinkedId.Identity_Username -> Res.strings.username - DSecret.Field.LinkedId.Identity_PassportNumber -> Res.strings.passport_number - DSecret.Field.LinkedId.Identity_LicenseNumber -> Res.strings.license_number - DSecret.Field.LinkedId.Identity_FirstName -> Res.strings.identity_first_name - DSecret.Field.LinkedId.Identity_LastName -> Res.strings.identity_last_name - DSecret.Field.LinkedId.Identity_FullName -> Res.strings.identity_full_name + DSecret.Field.LinkedId.Login_Username -> Res.string.username + DSecret.Field.LinkedId.Login_Password -> Res.string.password + DSecret.Field.LinkedId.Card_CardholderName -> Res.string.cardholder_name + DSecret.Field.LinkedId.Card_ExpMonth -> Res.string.card_expiry_month + DSecret.Field.LinkedId.Card_ExpYear -> Res.string.card_expiry_year + DSecret.Field.LinkedId.Card_Code -> Res.string.card_cvv + DSecret.Field.LinkedId.Card_Brand -> Res.string.card_type + DSecret.Field.LinkedId.Card_Number -> Res.string.card_number + DSecret.Field.LinkedId.Identity_Title -> Res.string.identity_first_name + DSecret.Field.LinkedId.Identity_MiddleName -> Res.string.identity_middle_name + DSecret.Field.LinkedId.Identity_Address1 -> Res.string.address1 + DSecret.Field.LinkedId.Identity_Address2 -> Res.string.address2 + DSecret.Field.LinkedId.Identity_Address3 -> Res.string.address3 + DSecret.Field.LinkedId.Identity_City -> Res.string.city + DSecret.Field.LinkedId.Identity_State -> Res.string.state + DSecret.Field.LinkedId.Identity_PostalCode -> Res.string.postal_code + DSecret.Field.LinkedId.Identity_Country -> Res.string.country + DSecret.Field.LinkedId.Identity_Company -> Res.string.company + DSecret.Field.LinkedId.Identity_Email -> Res.string.email + DSecret.Field.LinkedId.Identity_Phone -> Res.string.phone_number + DSecret.Field.LinkedId.Identity_Ssn -> Res.string.ssn + DSecret.Field.LinkedId.Identity_Username -> Res.string.username + DSecret.Field.LinkedId.Identity_PassportNumber -> Res.string.passport_number + DSecret.Field.LinkedId.Identity_LicenseNumber -> Res.string.license_number + DSecret.Field.LinkedId.Identity_FirstName -> Res.string.identity_first_name + DSecret.Field.LinkedId.Identity_LastName -> Res.string.identity_last_name + DSecret.Field.LinkedId.Identity_FullName -> Res.string.identity_full_name } fun DSecret.contains(hint: AutofillHint) = when (hint) { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSend.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSend.kt index c27b6f7d..9767b368 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSend.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DSend.kt @@ -8,6 +8,7 @@ import arrow.optics.optics import com.artemchep.keyguard.common.util.flowOfTime import com.artemchep.keyguard.core.store.bitwarden.BitwardenService import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.KeyguardAttachment import com.artemchep.keyguard.ui.icons.KeyguardNote import com.artemchep.keyguard.ui.icons.Stub @@ -101,9 +102,9 @@ fun DSend.Type.iconImageVector() = when (this) { } fun DSend.Type.titleH() = when (this) { - DSend.Type.Text -> Res.strings.send_type_text - DSend.Type.File -> Res.strings.send_type_file - DSend.Type.None -> Res.strings.send_type_unknown + DSend.Type.Text -> Res.string.send_type_text + DSend.Type.File -> Res.string.send_type_file + DSend.Type.None -> Res.string.send_type_unknown } fun DSend.Companion.requiresPremium(type: DSend.Type) = when (type) { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DWatchtowerAlert.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DWatchtowerAlert.kt index 00dc85c2..ac0fc600 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DWatchtowerAlert.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/DWatchtowerAlert.kt @@ -1,36 +1,37 @@ package com.artemchep.keyguard.common.model import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource enum class DWatchtowerAlert( val title: StringResource, ) { PWNED_PASSWORD( - title = Res.strings.watchtower_item_pwned_passwords_title, + title = Res.string.watchtower_item_pwned_passwords_title, ), PWNED_WEBSITE( - title = Res.strings.watchtower_item_vulnerable_accounts_title, + title = Res.string.watchtower_item_vulnerable_accounts_title, ), REUSED_PASSWORD( - title = Res.strings.watchtower_item_reused_passwords_title, + title = Res.string.watchtower_item_reused_passwords_title, ), TWO_FA_WEBSITE( - title = Res.strings.watchtower_item_inactive_2fa_title, + title = Res.string.watchtower_item_inactive_2fa_title, ), PASSKEY_WEBSITE( - title = Res.strings.watchtower_item_inactive_passkey_title, + title = Res.string.watchtower_item_inactive_passkey_title, ), UNSECURE_WEBSITE( - title = Res.strings.watchtower_item_unsecure_websites_title, + title = Res.string.watchtower_item_unsecure_websites_title, ), DUPLICATE( - title = Res.strings.watchtower_item_duplicate_items_title, + title = Res.string.watchtower_item_duplicate_items_title, ), INCOMPLETE( - title = Res.strings.watchtower_item_incomplete_items_title, + title = Res.string.watchtower_item_incomplete_items_title, ), EXPIRING( - title = Res.strings.watchtower_item_expiring_items_title, + title = Res.string.watchtower_item_expiring_items_title, ), } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/FileResource.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/FileResource.kt new file mode 100644 index 00000000..04cff5c9 --- /dev/null +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/FileResource.kt @@ -0,0 +1,40 @@ +package com.artemchep.keyguard.common.model + +@JvmInline +value class FileResource( + val name: String, +) { + companion object { + val gpmPasskeysPrivilegedApps: FileResource + get() = "files/gpm_passkeys_privileged_apps.json" + .let(::FileResource) + + val justDeleteMe: FileResource + get() = "files/justdeleteme.json" + .let(::FileResource) + + val justGetMyData: FileResource + get() = "files/justgetmydata.json" + .let(::FileResource) + + val licenses: FileResource + get() = "files/licenses.json" + .let(::FileResource) + + val passkeys: FileResource + get() = "files/passkeys.json" + .let(::FileResource) + + val publicSuffixList: FileResource + get() = "files/public_suffix_list.txt" + .let(::FileResource) + + val tfa: FileResource + get() = "files/tfa.json" + .let(::FileResource) + + val wordlist: FileResource + get() = "files/wordlist_en_elf.txt" + .let(::FileResource) + } +} diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/NavAnimation.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/NavAnimation.kt index b2464d42..d54517f7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/NavAnimation.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/NavAnimation.kt @@ -1,7 +1,8 @@ package com.artemchep.keyguard.common.model import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource enum class NavAnimation( val key: String, @@ -9,15 +10,15 @@ enum class NavAnimation( ) { DISABLED( key = "disabled", - title = Res.strings.nav_animation_disabled, + title = Res.string.nav_animation_disabled, ), CROSSFADE( key = "crossfade", - title = Res.strings.nav_animation_crossfade, + title = Res.string.nav_animation_crossfade, ), DYNAMIC( key = "dynamic", - title = Res.strings.nav_animation_dynamic, + title = Res.string.nav_animation_dynamic, ), ; diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/PasswordStrength.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/PasswordStrength.kt index b59b68c5..9bc4cd19 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/PasswordStrength.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/model/PasswordStrength.kt @@ -5,7 +5,8 @@ package com.artemchep.keyguard.common.model import androidx.compose.runtime.Composable import arrow.optics.optics import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource @optics data class PasswordStrength( @@ -39,19 +40,19 @@ fun PasswordStrength.Score.alertScore() = when (this) { } fun PasswordStrength.Score.formatH2() = when (this) { - PasswordStrength.Score.Weak -> Res.strings.passwords_weak_label - PasswordStrength.Score.Fair -> Res.strings.passwords_fair_label - PasswordStrength.Score.Good -> Res.strings.passwords_good_label - PasswordStrength.Score.Strong -> Res.strings.passwords_strong_label - PasswordStrength.Score.VeryStrong -> Res.strings.passwords_very_strong_label + PasswordStrength.Score.Weak -> Res.string.passwords_weak_label + PasswordStrength.Score.Fair -> Res.string.passwords_fair_label + PasswordStrength.Score.Good -> Res.string.passwords_good_label + PasswordStrength.Score.Strong -> Res.string.passwords_strong_label + PasswordStrength.Score.VeryStrong -> Res.string.passwords_very_strong_label } fun PasswordStrength.Score.formatH() = when (this) { - PasswordStrength.Score.Weak -> Res.strings.password_strength_weak_label - PasswordStrength.Score.Fair -> Res.strings.password_strength_fair_label - PasswordStrength.Score.Good -> Res.strings.password_strength_good_label - PasswordStrength.Score.Strong -> Res.strings.password_strength_strong_label - PasswordStrength.Score.VeryStrong -> Res.strings.password_strength_very_strong_label + PasswordStrength.Score.Weak -> Res.string.password_strength_weak_label + PasswordStrength.Score.Fair -> Res.string.password_strength_fair_label + PasswordStrength.Score.Good -> Res.string.password_strength_good_label + PasswordStrength.Score.Strong -> Res.string.password_strength_strong_label + PasswordStrength.Score.VeryStrong -> Res.string.password_strength_very_strong_label } @Composable diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/filter/repo/impl/CipherFilterRepositoryImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/filter/repo/impl/CipherFilterRepositoryImpl.kt index d7c95aee..8c225413 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/filter/repo/impl/CipherFilterRepositoryImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/filter/repo/impl/CipherFilterRepositoryImpl.kt @@ -22,8 +22,9 @@ import com.artemchep.keyguard.feature.home.vault.screen.FilterSection import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.KeyguardTwoFa -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource import kotlinx.collections.immutable.toPersistentMap import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow @@ -49,7 +50,7 @@ class CipherFilterRepositoryImpl( } private interface FilterEntityMapper { - fun map( + suspend fun map( context: LeContext, entity: CipherFilter, ): DCipherFilter @@ -60,7 +61,7 @@ class CipherFilterRepositoryImpl( private val name: StringResource, private val state: Map>, ) : FilterEntityMapper { - override fun map( + override suspend fun map( context: LeContext, entity: CipherFilter, ): DCipherFilter { @@ -83,7 +84,7 @@ class CipherFilterRepositoryImpl( private val filterEntityMappers = mapOf( TYPE_LOGIN to BaseFilterEntityMapper( icon = DSecret.Type.Login.iconImageVector(), - name = Res.strings.cipher_type_login, + name = Res.string.cipher_type_login, state = mapOf( FilterSection.TYPE.id to setOf( DFilter.ByType(DSecret.Type.Login), @@ -92,7 +93,7 @@ class CipherFilterRepositoryImpl( ), TYPE_CARD to BaseFilterEntityMapper( icon = DSecret.Type.Card.iconImageVector(), - name = Res.strings.cipher_type_card, + name = Res.string.cipher_type_card, state = mapOf( FilterSection.TYPE.id to setOf( DFilter.ByType(DSecret.Type.Card), @@ -101,7 +102,7 @@ class CipherFilterRepositoryImpl( ), TYPE_IDENTITY to BaseFilterEntityMapper( icon = DSecret.Type.Identity.iconImageVector(), - name = Res.strings.cipher_type_identity, + name = Res.string.cipher_type_identity, state = mapOf( FilterSection.TYPE.id to setOf( DFilter.ByType(DSecret.Type.Identity), @@ -110,7 +111,7 @@ class CipherFilterRepositoryImpl( ), TYPE_NOTE to BaseFilterEntityMapper( icon = DSecret.Type.SecureNote.iconImageVector(), - name = Res.strings.cipher_type_note, + name = Res.string.cipher_type_note, state = mapOf( FilterSection.TYPE.id to setOf( DFilter.ByType(DSecret.Type.SecureNote), @@ -119,7 +120,7 @@ class CipherFilterRepositoryImpl( ), TYPE_OTP to BaseFilterEntityMapper( icon = Icons.Outlined.KeyguardTwoFa, - name = Res.strings.one_time_password, + name = Res.string.one_time_password, state = mapOf( FilterSection.MISC.id to setOf( DFilter.ByOtp, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/gpmprivapps/impl/PrivilegedAppsServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/gpmprivapps/impl/PrivilegedAppsServiceImpl.kt index f2be4ae1..571e74d4 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/gpmprivapps/impl/PrivilegedAppsServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/gpmprivapps/impl/PrivilegedAppsServiceImpl.kt @@ -1,10 +1,12 @@ package com.artemchep.keyguard.common.service.gpmprivapps.impl import arrow.core.partially1 +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.gpmprivapps.PrivilegedAppsService import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import org.kodein.di.DirectDI import org.kodein.di.instance @@ -25,4 +27,4 @@ class PrivilegedAppsServiceImpl( private suspend fun loadJustDeleteMeRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.gpm_passkeys_privileged_apps) +) = textService.readFromResourcesAsText(FileResource.gpmPasskeysPrivilegedApps) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justdeleteme/impl/JustDeleteMeServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justdeleteme/impl/JustDeleteMeServiceImpl.kt index ec24e2e1..5fb2ae1b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justdeleteme/impl/JustDeleteMeServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justdeleteme/impl/JustDeleteMeServiceImpl.kt @@ -3,11 +3,13 @@ package com.artemchep.keyguard.common.service.justdeleteme.impl import arrow.core.partially1 import com.artemchep.keyguard.common.io.effectMap import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.justdeleteme.JustDeleteMeService import com.artemchep.keyguard.common.service.justdeleteme.JustDeleteMeServiceInfo import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -67,4 +69,4 @@ class JustDeleteMeServiceImpl( private suspend fun loadJustDeleteMeRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.justdeleteme) +) = textService.readFromResourcesAsText(FileResource.justDeleteMe) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justgetmydata/impl/JustGetMyDataServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justgetmydata/impl/JustGetMyDataServiceImpl.kt index 5fc140c3..7674b325 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justgetmydata/impl/JustGetMyDataServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/justgetmydata/impl/JustGetMyDataServiceImpl.kt @@ -5,12 +5,12 @@ import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.io.effectMap import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.justgetmydata.JustGetMyDataService import com.artemchep.keyguard.common.service.justgetmydata.JustGetMyDataServiceInfo import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.common.service.tld.TldService -import com.artemchep.keyguard.res.Res import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -97,4 +97,4 @@ class JustGetMyDataServiceImpl( private suspend fun loadJustGetMyDataRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.justgetmydata) +) = textService.readFromResourcesAsText(FileResource.justGetMyData) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/license/impl/LicenseServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/license/impl/LicenseServiceImpl.kt index c6f14586..013eeb7b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/license/impl/LicenseServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/license/impl/LicenseServiceImpl.kt @@ -3,11 +3,13 @@ package com.artemchep.keyguard.common.service.license.impl import arrow.core.partially1 import com.artemchep.keyguard.common.io.IO import com.artemchep.keyguard.common.io.effectMap +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.license.LicenseService import com.artemchep.keyguard.common.service.license.model.License import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import org.kodein.di.DirectDI @@ -76,4 +78,4 @@ class LicenseServiceImpl( private suspend fun loadLicensesRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.licenses) +) = textService.readFromResourcesAsText(FileResource.licenses) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/passkey/impl/PassKeyServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/passkey/impl/PassKeyServiceImpl.kt index 30a4958d..c72c1e10 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/passkey/impl/PassKeyServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/passkey/impl/PassKeyServiceImpl.kt @@ -3,11 +3,13 @@ package com.artemchep.keyguard.common.service.passkey.impl import arrow.core.partially1 import com.artemchep.keyguard.common.io.effectMap import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.passkey.PassKeyService import com.artemchep.keyguard.common.service.passkey.PassKeyServiceInfo import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.datetime.Instant import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -71,4 +73,4 @@ class PassKeyServiceImpl( private suspend fun loadPassKeyRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.passkeys) +) = textService.readFromResourcesAsText(FileResource.passkeys) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/anonaddy/AnonAddyEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/anonaddy/AnonAddyEmailRelay.kt index b3ea14a7..9e665cb9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/anonaddy/AnonAddyEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/anonaddy/AnonAddyEmailRelay.kt @@ -9,6 +9,7 @@ import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.provider.bitwarden.api.builder.ensureSuffix import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.header @@ -51,20 +52,20 @@ class AnonAddyEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, ), KEY_DOMAIN to EmailRelaySchema( - title = TextHolder.Res(Res.strings.domain), + title = TextHolder.Res(Res.string.domain), hint = TextHolder.Value(HINT_DOMAIN), canBeEmpty = false, ), KEY_BASE_URL to EmailRelaySchema( - title = TextHolder.Res(Res.strings.emailrelay_base_env_server_url_label), + title = TextHolder.Res(Res.string.emailrelay_base_env_server_url_label), hint = TextHolder.Value(HINT_BASE_URL), - description = TextHolder.Res(Res.strings.emailrelay_base_env_note), + description = TextHolder.Res(Res.string.emailrelay_base_env_note), canBeEmpty = true, ), ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/duckduckgo/DuckDuckGoEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/duckduckgo/DuckDuckGoEmailRelay.kt index cda7f56f..888f0def 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/duckduckgo/DuckDuckGoEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/duckduckgo/DuckDuckGoEmailRelay.kt @@ -8,6 +8,7 @@ import com.artemchep.keyguard.common.service.relays.api.EmailRelaySchema import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.header @@ -41,7 +42,7 @@ class DuckDuckGoEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/fastmail/FastmailEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/fastmail/FastmailEmailRelay.kt index 5ac3bdfe..bcf0cffb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/fastmail/FastmailEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/fastmail/FastmailEmailRelay.kt @@ -8,6 +8,7 @@ import com.artemchep.keyguard.common.service.relays.api.EmailRelaySchema import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf @@ -34,7 +35,7 @@ class FastmailEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/firefoxrelay/FirefoxRelayEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/firefoxrelay/FirefoxRelayEmailRelay.kt index 5d36e896..d201c7c7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/firefoxrelay/FirefoxRelayEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/firefoxrelay/FirefoxRelayEmailRelay.kt @@ -8,6 +8,7 @@ import com.artemchep.keyguard.common.service.relays.api.EmailRelaySchema import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.header @@ -44,7 +45,7 @@ class FirefoxRelayEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/forwardemail/ForwardEmailEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/forwardemail/ForwardEmailEmailRelay.kt index 3feb84e0..f81060a3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/forwardemail/ForwardEmailEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/forwardemail/ForwardEmailEmailRelay.kt @@ -9,6 +9,7 @@ import com.artemchep.keyguard.common.service.text.Base64Service import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.header @@ -47,13 +48,13 @@ class ForwardEmailEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, ), KEY_DOMAIN to EmailRelaySchema( - title = TextHolder.Res(Res.strings.domain), + title = TextHolder.Res(Res.string.domain), hint = TextHolder.Value(HINT_DOMAIN), canBeEmpty = false, ), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/simplelogin/SimpleLoginEmailRelay.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/simplelogin/SimpleLoginEmailRelay.kt index 9d5dbc3b..ddf87296 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/simplelogin/SimpleLoginEmailRelay.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/relays/api/simplelogin/SimpleLoginEmailRelay.kt @@ -9,6 +9,7 @@ import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.provider.bitwarden.api.builder.ensureSuffix import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.header @@ -47,15 +48,15 @@ class SimpleLoginEmailRelay( override val schema = persistentMapOf( KEY_API_KEY to EmailRelaySchema( - title = TextHolder.Res(Res.strings.api_key), + title = TextHolder.Res(Res.string.api_key), hint = TextHolder.Value(HINT_API_KEY), type = ConfirmationRoute.Args.Item.StringItem.Type.Token, canBeEmpty = false, ), KEY_BASE_URL to EmailRelaySchema( - title = TextHolder.Res(Res.strings.emailrelay_base_env_server_url_label), + title = TextHolder.Res(Res.string.emailrelay_base_env_server_url_label), hint = TextHolder.Value(HINT_BASE_URL), - description = TextHolder.Res(Res.strings.emailrelay_base_env_note), + description = TextHolder.Res(Res.string.emailrelay_base_env_note), canBeEmpty = true, ), ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/text/TextService.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/text/TextService.kt index 2397654b..765446d8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/text/TextService.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/text/TextService.kt @@ -1,12 +1,12 @@ package com.artemchep.keyguard.common.service.text -import dev.icerock.moko.resources.FileResource +import com.artemchep.keyguard.common.model.FileResource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.InputStream interface TextService { - fun readFromResources( + suspend fun readFromResources( fileResource: FileResource, ): InputStream diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/tld/impl/TldServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/tld/impl/TldServiceImpl.kt index 9811e764..3a061177 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/tld/impl/TldServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/tld/impl/TldServiceImpl.kt @@ -5,11 +5,13 @@ import com.artemchep.keyguard.common.io.IO import com.artemchep.keyguard.common.io.effectMap import com.artemchep.keyguard.common.io.measure import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.logging.LogRepository import com.artemchep.keyguard.common.service.logging.postDebug import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.tld.TldService import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.kodein.di.DirectDI @@ -75,7 +77,7 @@ private suspend fun loadTld( textService: TextService, ) = withContext(Dispatchers.IO) { textService - .readFromResources(Res.files.public_suffix_list).use { + .readFromResources(FileResource.publicSuffixList).use { it .bufferedReader() .useLines { lines -> diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/twofa/impl/TwoFaServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/twofa/impl/TwoFaServiceImpl.kt index bde2f308..6780d9d4 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/twofa/impl/TwoFaServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/twofa/impl/TwoFaServiceImpl.kt @@ -3,11 +3,13 @@ package com.artemchep.keyguard.common.service.twofa.impl import arrow.core.partially1 import com.artemchep.keyguard.common.io.effectMap import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.common.service.twofa.TwoFaService import com.artemchep.keyguard.common.service.twofa.TwoFaServiceInfo import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -63,4 +65,4 @@ class TwoFaServiceImpl( private suspend fun loadTfaRawData( textService: TextService, -) = textService.readFromResourcesAsText(Res.files.tfa) +) = textService.readFromResourcesAsText(FileResource.tfa) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/wordlist/impl/WordlistServiceImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/wordlist/impl/WordlistServiceImpl.kt index 1fa92864..63a918b7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/wordlist/impl/WordlistServiceImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/wordlist/impl/WordlistServiceImpl.kt @@ -4,9 +4,11 @@ import arrow.core.partially1 import com.artemchep.keyguard.common.io.IO import com.artemchep.keyguard.common.io.handleErrorTap import com.artemchep.keyguard.common.io.shared +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.wordlist.WordlistService import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.kodein.di.DirectDI @@ -34,7 +36,7 @@ class WordlistServiceImpl( private suspend fun loadWordlist( textService: TextService, ) = withContext(Dispatchers.IO) { - textService.readFromResources(Res.files.wordlist_en_eff).use { + textService.readFromResources(FileResource.wordlist).use { it .bufferedReader() .lineSequence() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CipherDuplicatesCheck.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CipherDuplicatesCheck.kt index 2a6ef08d..727afe72 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CipherDuplicatesCheck.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CipherDuplicatesCheck.kt @@ -3,7 +3,8 @@ package com.artemchep.keyguard.common.usecase import com.artemchep.keyguard.common.model.DSecret import com.artemchep.keyguard.common.model.DSecretDuplicateGroup import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource import kotlinx.serialization.Serializable interface CipherDuplicatesCheck : @@ -14,23 +15,23 @@ interface CipherDuplicatesCheck : val threshold: Float, ) { MAX( - title = Res.strings.tolerance_min, + title = Res.string.tolerance_min, threshold = 0.3f, ), HIGH( - title = Res.strings.tolerance_low, + title = Res.string.tolerance_low, threshold = 0.15f, ), NORMAL( - title = Res.strings.tolerance_normal, + title = Res.string.tolerance_normal, threshold = 0f, ), LOW( - title = Res.strings.tolerance_high, + title = Res.string.tolerance_high, threshold = -0.1f, ), MIN( - title = Res.strings.tolerance_max, + title = Res.string.tolerance_max, threshold = -0.15f, ), } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CopyText.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CopyText.kt index bf95f86b..83942558 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CopyText.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/CopyText.kt @@ -4,7 +4,10 @@ import com.artemchep.keyguard.common.model.ToastMessage import com.artemchep.keyguard.common.service.clipboard.ClipboardService import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.StringResource /** * @author Artem Chepurnyi @@ -17,23 +20,23 @@ class CopyText( enum class Type( val res: StringResource, ) { - VALUE(Res.strings.copied_value), - URL(Res.strings.copied_url), - URI(Res.strings.copied_uri), - PACKAGE_NAME(Res.strings.copied_package_name), - PASSWORD(Res.strings.copied_password), - USERNAME(Res.strings.copied_username), - EMAIL(Res.strings.copied_email), - PHONE_NUMBER(Res.strings.copied_phone_number), - PASSPORT_NUMBER(Res.strings.copied_passport_number), - LICENSE_NUMBER(Res.strings.copied_license_number), - CARD_NUMBER(Res.strings.copied_card_number), - CARD_CARDHOLDER_NAME(Res.strings.copied_cardholder_name), - CARD_EXP_YEAR(Res.strings.copied_expiration_year), - CARD_EXP_MONTH(Res.strings.copied_expiration_month), - CARD_CVV(Res.strings.copied_cvv_code), - OTP(Res.strings.copied_otp_code), - OTP_SECRET(Res.strings.copied_otp_secret_code), + VALUE(Res.string.copied_value), + URL(Res.string.copied_url), + URI(Res.string.copied_uri), + PACKAGE_NAME(Res.string.copied_package_name), + PASSWORD(Res.string.copied_password), + USERNAME(Res.string.copied_username), + EMAIL(Res.string.copied_email), + PHONE_NUMBER(Res.string.copied_phone_number), + PASSPORT_NUMBER(Res.string.copied_passport_number), + LICENSE_NUMBER(Res.string.copied_license_number), + CARD_NUMBER(Res.string.copied_card_number), + CARD_CARDHOLDER_NAME(Res.string.copied_cardholder_name), + CARD_EXP_YEAR(Res.string.copied_expiration_year), + CARD_EXP_MONTH(Res.string.copied_expiration_month), + CARD_CVV(Res.string.copied_cvv_code), + OTP(Res.string.copied_otp_code), + OTP_SECRET(Res.string.copied_otp_secret_code), } fun copy( @@ -43,11 +46,13 @@ class CopyText( ) { clipboardService.setPrimaryClip(text, concealed = hidden) if (!clipboardService.hasCopyNotification()) { - val message = ToastMessage( - title = translator.translate(type.res), - text = text.takeUnless { hidden }, - ) - onMessage(message) + GlobalScope.launch { + val message = ToastMessage( + title = translator.translate(type.res), + text = text.takeUnless { hidden }, + ) + onMessage(message) + } } } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/DateFormatter.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/DateFormatter.kt index 57c45a27..1fcee2c9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/DateFormatter.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/usecase/DateFormatter.kt @@ -17,11 +17,11 @@ interface DateFormatter { instant: Instant, ): String - fun formatDateShort( + suspend fun formatDateShort( instant: Instant, ): String - fun formatDateShort( + suspend fun formatDateShort( date: LocalDate, ): String diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/util/flow/observeFlow.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/util/flow/observeFlow.kt index 013add79..612f3549 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/util/flow/observeFlow.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/util/flow/observeFlow.kt @@ -14,7 +14,7 @@ inline fun observerFlow( var unregister: (() -> Unit)? = null try { unregister = withContext(Dispatchers.Main) { - val setter = { value: T -> + val setter: (T) -> Unit = { value: T -> trySend(value) } register(setter) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/EmptyView.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/EmptyView.kt index c3ebd852..cb3a820e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/EmptyView.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/EmptyView.kt @@ -21,10 +21,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun EmptySearchView( @@ -91,6 +92,6 @@ private fun DefaultEmptyViewText( ) { Text( modifier = modifier, - text = stringResource(Res.strings.items_empty_label), + text = stringResource(Res.string.items_empty_label), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddScreen.kt index f2bca1ff..6fa6f4ec 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddScreen.kt @@ -86,6 +86,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.qr.ScanQrButton import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AutofillButton import com.artemchep.keyguard.ui.BiFlatContainer import com.artemchep.keyguard.ui.BiFlatTextField @@ -136,7 +137,7 @@ import com.artemchep.keyguard.ui.theme.isDark import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.util.DividerColor import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList private val paddingValues = PaddingValues( @@ -327,7 +328,7 @@ private fun TitleTextField( .padding(horizontal = Dimens.horizontalPadding), fieldModifier = Modifier .focusRequester2(focusRequester), - label = stringResource(Res.strings.generic_name), + label = stringResource(Res.string.generic_name), singleLine = true, value = field, keyboardOptions = KeyboardOptions( @@ -350,7 +351,7 @@ private fun UsernameTextField( EmailFlatTextField( modifier = modifier .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.username), + label = stringResource(Res.string.username), value = field, leading = { Crossfade( @@ -428,7 +429,7 @@ private fun PasswordTextField( bottom = Dimens.topPaddingCaption, ), style = MaterialTheme.typography.bodyMedium, - text = stringResource(Res.strings.generator_password_note, 16), + text = stringResource(Res.string.generator_password_note, 16), color = LocalContentColor.current .combineAlpha(alpha = MediumEmphasisAlpha), ) @@ -445,7 +446,7 @@ private fun TotpTextField( FlatTextField( modifier = modifier .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.one_time_password_authenticator_key), + label = stringResource(Res.string.one_time_password_authenticator_key), value = field, textStyle = LocalTextStyle.current.copy( fontFamily = monoFontFamily, @@ -501,7 +502,7 @@ private fun NoteTextField( FlatTextField( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.note), + label = stringResource(Res.string.note), value = field, content = if (markdown) { // composable @@ -515,7 +516,7 @@ private fun NoteTextField( }, ) { Text( - text = stringResource(Res.strings.additem_markdown_render_preview), + text = stringResource(Res.string.additem_markdown_render_preview), ) } } @@ -530,12 +531,12 @@ private fun NoteTextField( ) if (markdown) { val description = annotatedResource( - Res.strings.additem_markdown_note, - stringResource(Res.strings.additem_markdown_note_italic) + Res.string.additem_markdown_note, + stringResource(Res.string.additem_markdown_note_italic) .let { "*$it*" } to SpanStyle( fontStyle = FontStyle.Italic, ), - stringResource(Res.strings.additem_markdown_note_bold) + stringResource(Res.string.additem_markdown_note_bold) .let { "**$it**" } to SpanStyle( fontWeight = FontWeight.Bold, ), @@ -566,7 +567,7 @@ private fun NoteTextField( }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } @@ -621,7 +622,7 @@ private fun UrlTextField( UrlFlatTextField( modifier = modifier .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.uri), + label = stringResource(Res.string.uri), value = field, leading = { IconBox( @@ -770,7 +771,7 @@ private fun PasskeyField( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.passkey), + text = stringResource(Res.string.passkey), ) }, ) @@ -1003,7 +1004,7 @@ private fun FieldLinkedIdField( modifier = Modifier .heightIn(min = BiFlatValueHeightMin) .weight(1f, fill = false), - text = (state.value?.titleH() ?: Res.strings.select_linked_type) + text = (state.value?.titleH() ?: Res.string.select_linked_type) .let { stringResource(it) }, color = textColor, ) @@ -1152,7 +1153,7 @@ private fun DateTimeField( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.date), + text = stringResource(Res.string.date), ) }, text = { @@ -1177,7 +1178,7 @@ private fun DateTimeField( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.time), + text = stringResource(Res.string.time), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateItemUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateItemUtil.kt index 6a566eb5..6f763c9f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateItemUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateItemUtil.kt @@ -24,7 +24,7 @@ suspend fun AddStateItem.Switch.Companion.produceItemFlow( key: String, initialValue: Boolean, populator: Request.(SwitchFieldModel) -> Request, - factory: (String, LocalStateItem) -> AddStateItem.Switch, + factory: suspend (String, LocalStateItem) -> AddStateItem.Switch, ): AddStateItem.Switch { val sink = mutablePersistedFlow(key) { initialValue } val stateItem = LocalStateItem( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateOwnershipUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateOwnershipUtil.kt index 9232eb7b..2257869e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateOwnershipUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/add/AddStateOwnershipUtil.kt @@ -10,6 +10,7 @@ import com.artemchep.keyguard.common.model.displayName import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine @@ -123,7 +124,7 @@ fun OwnershipHandle.accountFlow( if (accountId == null) { val item = AddStateOwnership.Element.Item( key = "account.empty", - title = translate(Res.strings.account_none), + title = translate(Res.string.account_none), stub = true, ) val el = AddStateOwnership.Element( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsScreen.kt index 76abc5f2..b1b40010 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsScreen.kt @@ -21,12 +21,13 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultSelection import com.artemchep.keyguard.ui.ScaffoldLazyColumn import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.SmallToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AttachmentsScreen() { @@ -38,7 +39,7 @@ fun AttachmentsScreen() { modifier = modifier, title = { Text( - text = stringResource(Res.strings.downloads), + text = stringResource(Res.string.downloads), ) }, navigationIcon = { @@ -93,7 +94,7 @@ fun AttachmentsScreen( LargeToolbar( title = { Text( - text = stringResource(Res.strings.downloads), + text = stringResource(Res.string.downloads), ) }, navigationIcon = { @@ -154,7 +155,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.downloads_empty_label), + text = stringResource(Res.string.downloads_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsStateProducer.kt index ca48bafb..09f7ab66 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/attachments/AttachmentsStateProducer.kt @@ -44,12 +44,15 @@ import com.artemchep.keyguard.feature.home.vault.screen.ah import com.artemchep.keyguard.feature.home.vault.screen.createFilter import com.artemchep.keyguard.feature.home.vault.search.filter.FilterHolder import com.artemchep.keyguard.feature.home.vault.util.AlphabeticalSortMinItemsSize +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ContextItem import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection @@ -330,7 +333,7 @@ fun produceAttachmentsScreenState( if (selectedItemsAllCancelable) { actions += FlatItemAction( leading = icon(Icons.Outlined.Cancel), - title = translate(Res.strings.cancel), + title = Res.string.cancel.wrap(), onClick = { removeIo.launchIn(appScope) }, @@ -339,7 +342,7 @@ fun produceAttachmentsScreenState( if (selectedItemsAllDownloadable) { actions += FlatItemAction( leading = icon(Icons.Outlined.Download), - title = "Download", + title = TextHolder.Value("Download"), onClick = { downloadIo.launchIn(appScope) }, @@ -348,7 +351,7 @@ fun produceAttachmentsScreenState( if (selectedItemsAllDownloaded) { actions += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = "Delete local files", + title = TextHolder.Value("Delete local files"), onClick = { removeIo.launchIn(appScope) }, @@ -450,21 +453,20 @@ fun produceAttachmentsScreenState( as ItemDecorator } - val items = sequence { - state.list.forEach { item -> - val section = decorator.getOrNull(item.item) - if (section != null) yield(section) + val out = mutableListOf() + state.list.forEach { item -> + val section = decorator.getOrNull(item.item) + if (section != null) out += section - val wrappedItem = AttachmentsState.Item.Attachment( - key = item.item.key, - item = item.item, - ) - yield(wrappedItem) - } - }.toList() + val wrappedItem = AttachmentsState.Item.Attachment( + key = item.item.key, + item = item.item, + ) + out += wrappedItem + } FilteredBoo( count = state.list.size, - list = items, + list = out, filterConfig = state.filterConfig, ) } @@ -553,7 +555,7 @@ fun foo( is FooStatus.None -> { this += FlatItemAction( icon = Icons.Outlined.Download, - title = translatorScope.translate(Res.strings.download), + title = Res.string.download.wrap(), onClick = ::performDownload, type = FlatItemAction.Type.DOWNLOAD, ) @@ -562,7 +564,7 @@ fun foo( is FooStatus.Loading -> { this += FlatItemAction( leading = icon(Icons.Outlined.Cancel), - title = translatorScope.translate(Res.strings.cancel), + title = Res.string.cancel.wrap(), onClick = ::performRemove, ) } @@ -570,12 +572,12 @@ fun foo( is FooStatus.Failed -> { this += FlatItemAction( leading = icon(Icons.Outlined.Cancel), - title = translatorScope.translate(Res.strings.cancel), + title = Res.string.cancel.wrap(), onClick = ::performRemove, ) this += FlatItemAction( leading = icon(Icons.Outlined.Refresh), - title = translatorScope.translate(Res.strings.download), + title = Res.string.download.wrap(), onClick = ::performDownload, type = FlatItemAction.Type.DOWNLOAD, ) @@ -588,7 +590,7 @@ fun foo( trailing = { ChevronIcon() }, - title = translatorScope.translate(Res.strings.file_action_open_with_title), + title = Res.string.file_action_open_with_title.wrap(), onClick = { val intent = NavigationIntent.NavigateToPreview( uri = fileUrl, @@ -604,7 +606,7 @@ fun foo( trailing = { ChevronIcon() }, - title = translatorScope.translate(Res.strings.file_action_open_in_file_manager_title), + title = Res.string.file_action_open_in_file_manager_title.wrap(), onClick = { val intent = NavigationIntent.NavigateToPreviewInFileManager( uri = fileUrl, @@ -620,7 +622,7 @@ fun foo( trailing = { ChevronIcon() }, - title = translatorScope.translate(Res.strings.file_action_send_with_title), + title = Res.string.file_action_send_with_title.wrap(), onClick = { val intent = NavigationIntent.NavigateToSend( uri = fileUrl, @@ -632,7 +634,7 @@ fun foo( } this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translatorScope.translate(Res.strings.file_action_delete_local_title), + title = Res.string.file_action_delete_local_title.wrap(), onClick = ::performRemove, ) } @@ -645,7 +647,7 @@ fun foo( trailing = { ChevronIcon() }, - title = translatorScope.translate(Res.strings.file_action_view_cipher_title), + title = Res.string.file_action_view_cipher_title.wrap(), onClick = { val route = VaultViewRoute( itemId = launchViewCipherData.cipherId, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewScreen.kt index 9699410d..c5a43626 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.EmptyView import com.artemchep.keyguard.feature.home.vault.component.VaultViewItem import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FabState @@ -47,7 +48,7 @@ import com.artemchep.keyguard.ui.shimmer.shimmer import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AccountViewScreen( @@ -101,7 +102,7 @@ fun AccountViewScreen( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.web_vault), + text = stringResource(Res.string.web_vault), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewStateProducer.kt index 4cc7e5d5..f78765df 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/AccountViewStateProducer.kt @@ -77,15 +77,18 @@ import com.artemchep.keyguard.feature.home.vault.folders.FoldersRoute import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.feature.home.vault.organizations.OrganizationsRoute import com.artemchep.keyguard.feature.largetype.LargeTypeRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.send.SendRoute import com.artemchep.keyguard.feature.watchtower.WatchtowerRoute import com.artemchep.keyguard.provider.bitwarden.ServerEnv import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.autoclose.launchAutoPopSelfHandler import com.artemchep.keyguard.ui.buildContextItems @@ -208,11 +211,11 @@ fun accountState( .launchIn(appScope) } - fun doRemoveAccountById(accountId: AccountId) { + suspend fun doRemoveAccountById(accountId: AccountId) { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.Logout), - title = translate(Res.strings.account_log_out_confirmation_title), - message = translate(Res.strings.account_log_out_confirmation_text), + title = translate(Res.string.account_log_out_confirmation_title), + message = translate(Res.string.account_log_out_confirmation_text), ) { removeAccountById(setOf(accountId)) .launchIn(appScope) @@ -313,7 +316,7 @@ fun accountState( val email = t.user.email val env = t.env.back() AccountViewState.Content.Data.PrimaryAction( - text = translate(Res.strings.account_action_sign_in_title), + text = translate(Res.string.account_action_sign_in_title), icon = Icons.Outlined.Login, onClick = ::doReLogin .partially1(accountId) @@ -366,7 +369,7 @@ fun accountState( leading = { SyncIcon(rotating = syncing) }, - title = translate(Res.strings.sync), + title = Res.string.sync.wrap(), onClick = if (busy) { null } else { @@ -409,8 +412,8 @@ fun accountState( onCheckedChange = onCheckedChange, ) }, - title = translate(Res.strings.account_action_hide_title), - text = translate(Res.strings.account_action_hide_text), + title = Res.string.account_action_hide_title.wrap(), + text = Res.string.account_action_hide_text.wrap(), onClick = onCheckedChange.partially1(!hidden), ) } @@ -421,12 +424,14 @@ fun accountState( this += FlatItemAction( icon = Icons.Outlined.Logout, - title = translate(Res.strings.account_action_sign_out_title), + title = Res.string.account_action_sign_out_title.wrap(), onClick = if (busy) { null } else { // on click listener - ::doRemoveAccountById.partially1(accountOrNull.id) + onClick { + doRemoveAccountById(accountId) + } }, ) } @@ -537,7 +542,7 @@ private fun buildItemsFlow( val syncTimestamp = meta.lastSyncTimestamp if (syncTimestamp != null) { val syncDate = dateFormatter.formatDateTime(syncTimestamp) - val syncInfoText = scope.translate(Res.strings.account_last_synced_at, syncDate) + val syncInfoText = scope.translate(Res.string.account_last_synced_at, syncDate) val syncInfoItem = VaultViewItem.Label( id = "sync.timestamp", text = AnnotatedString(syncInfoText), @@ -549,7 +554,7 @@ private fun buildItemsFlow( if (account != null) { val ff0 = VaultViewItem.Action( id = "ciphers", - title = scope.translate(Res.strings.items), + title = scope.translate(Res.string.items), leading = { BadgedBox( badge = { @@ -576,7 +581,7 @@ private fun buildItemsFlow( emit(ff0) val sendsItem = VaultViewItem.Action( id = "sends", - title = scope.translate(Res.strings.sends), + title = scope.translate(Res.string.sends), leading = { BadgedBox( badge = { @@ -604,7 +609,7 @@ private fun buildItemsFlow( } val ff = VaultViewItem.Action( id = "folders", - title = scope.translate(Res.strings.folders), + title = scope.translate(Res.string.folders), leading = { BadgedBox( badge = { @@ -635,7 +640,7 @@ private fun buildItemsFlow( emit(ff) val ff2 = VaultViewItem.Action( id = "collections", - title = scope.translate(Res.strings.collections), + title = scope.translate(Res.string.collections), leading = { BadgedBox( badge = { @@ -667,7 +672,7 @@ private fun buildItemsFlow( emit(ff2) val ff3 = VaultViewItem.Action( id = "organizations", - title = scope.translate(Res.strings.organizations), + title = scope.translate(Res.string.organizations), leading = { BadgedBox( badge = { @@ -702,7 +707,7 @@ private fun buildItemsFlow( emit(watchtowerSectionItem) val watchtowerItem = VaultViewItem.Action( id = "watchtower", - title = scope.translate(Res.strings.watchtower_header_title), + title = scope.translate(Res.string.watchtower_header_title), leading = { Icon(Icons.Outlined.Security, null) }, @@ -725,7 +730,7 @@ private fun buildItemsFlow( emit(watchtowerItem) val ff4 = VaultViewItem.Section( id = "section", - text = scope.translate(Res.strings.security), + text = scope.translate(Res.string.security), ) emit(ff4) if (profile != null) { @@ -743,7 +748,7 @@ private fun buildItemsFlow( ) val ff5 = VaultViewItem.Section( id = "section2", - text = scope.translate(Res.strings.info), + text = scope.translate(Res.string.info), ) emit(ff5) } @@ -756,7 +761,7 @@ private fun buildItemsFlow( ) val unofficialServer = profile.unofficialServer if (unofficialServer) { - val unofficialServerText = scope.translate(Res.strings.bitwarden_unofficial_server) + val unofficialServerText = scope.translate(Res.string.bitwarden_unofficial_server) val unofficialServerItem = VaultViewItem.Label( id = "unofficial_server", text = AnnotatedString(unofficialServerText), @@ -779,17 +784,17 @@ private suspend fun FlowCollector.emitName( ) { val name = profile.name - fun onClick() { + suspend fun onClick() { val intent = scope.createConfirmationDialogIntent( icon = icon(Icons.Outlined.Edit), item = ConfirmationRoute.Args.Item.StringItem( key = "name", - title = scope.translate(Res.strings.account_name), + title = scope.translate(Res.string.account_name), value = name, // You can have an empty account name. canBeEmpty = true, ), - title = scope.translate(Res.strings.account_action_change_name_title), + title = scope.translate(Res.string.account_action_change_name_title), ) { name -> val profileIdsToNames = mapOf( AccountId(profile.accountId) to name, @@ -818,8 +823,10 @@ private suspend fun FlowCollector.emitName( val id = "name" val nameEditActionItem = FlatItemAction( icon = Icons.Outlined.Edit, - title = scope.translate(Res.strings.account_action_change_name_title), - onClick = ::onClick, + title = Res.string.account_action_change_name_title.wrap(), + onClick = scope.onClick { + onClick() + }, ) val colorEditActionItem = FlatItemAction( leading = iconSmall(Icons.Outlined.Edit, Icons.Outlined.ColorLens), @@ -835,7 +842,7 @@ private suspend fun FlowCollector.emitName( .size(24.dp), ) }, - title = scope.translate(Res.strings.account_action_change_color_title), + title = Res.string.account_action_change_color_title.wrap(), onClick = ::onEditColor, ) val leading: @Composable RowScope.() -> Unit = { @@ -855,7 +862,7 @@ private suspend fun FlowCollector.emitName( VaultViewItem.Value( id = id, elevation = 1.dp, - title = scope.translate(Res.strings.account_name), + title = scope.translate(Res.string.account_name), value = "", leading = leading, dropdown = listOfNotNull( @@ -868,13 +875,13 @@ private suspend fun FlowCollector.emitName( VaultViewItem.Value( id = id, elevation = 1.dp, - title = scope.translate(Res.strings.account_name), + title = scope.translate(Res.string.account_name), value = name, leading = leading, dropdown = buildContextItems { section { this += copyText.FlatItemAction( - title = scope.translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = name, ) } @@ -918,19 +925,19 @@ private suspend fun FlowCollector.emitEmail( // Account email verification badge list += if (profile.emailVerified) { VaultViewItem.Value.Badge( - text = scope.translate(Res.strings.email_verified), + text = scope.translate(Res.string.email_verified), score = 1f, ) } else { VaultViewItem.Value.Badge( - text = scope.translate(Res.strings.email_not_verified), + text = scope.translate(Res.string.email_not_verified), score = 0.5f, ) }.let(::MutableStateFlow) // Account two-factor authentication badge if (profile.twoFactorEnabled) { list += VaultViewItem.Value.Badge( - text = scope.translate(Res.strings.account_action_tfa_title), + text = scope.translate(Res.string.account_action_tfa_title), score = 1f, ).let(::MutableStateFlow) } @@ -939,7 +946,7 @@ private suspend fun FlowCollector.emitEmail( val emailItem = VaultViewItem.Value( id = id, elevation = 1.dp, - title = scope.translate(Res.strings.email), + title = scope.translate(Res.string.email), value = email, leading = { EmailIcon( @@ -952,7 +959,7 @@ private suspend fun FlowCollector.emitEmail( dropdown = buildContextItems { section { this += copyText.FlatItemAction( - title = scope.translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = email, type = CopyText.Type.EMAIL, ) @@ -973,7 +980,7 @@ private suspend fun FlowCollector.emitEmail( section { this += FlatItemAction( leading = icon(Icons.Outlined.VerifiedUser), - title = scope.translate(Res.strings.account_action_email_verify_instructions_title), + title = Res.string.account_action_email_verify_instructions_title.wrap(), onClick = null, ) } @@ -1002,7 +1009,7 @@ private suspend fun FlowCollector.emitPremium( val premiumItem = if (profile.premium) { VaultViewItem.Action( id = id, - title = scope.translate(Res.strings.bitwarden_premium), + title = scope.translate(Res.string.bitwarden_premium), leading = { Icon(Icons.Outlined.KeyguardPremium, null) }, @@ -1010,7 +1017,7 @@ private suspend fun FlowCollector.emitPremium( ChevronIcon() }, badge = VaultViewItem.Action.Badge( - text = scope.translate(Res.strings.pref_item_premium_status_active), + text = scope.translate(Res.string.pref_item_premium_status_active), score = 1f, ), onClick = { @@ -1021,8 +1028,8 @@ private suspend fun FlowCollector.emitPremium( } else { VaultViewItem.Action( id = id, - title = scope.translate(Res.strings.bitwarden_premium), - text = scope.translate(Res.strings.account_action_premium_purchase_instructions_title), + title = scope.translate(Res.string.bitwarden_premium), + text = scope.translate(Res.string.account_action_premium_purchase_instructions_title), leading = { Icon(Icons.Outlined.KeyguardPremium, null) }, @@ -1046,17 +1053,17 @@ private suspend fun FlowCollector.emitMasterPasswordHint( ) { val hint = profile.masterPasswordHint - fun onClick() { + suspend fun onClick() { val intent = scope.createConfirmationDialogIntent( icon = icon(Icons.Outlined.Edit), item = ConfirmationRoute.Args.Item.StringItem( key = "name", - title = scope.translate(Res.strings.master_password_hint), + title = scope.translate(Res.string.master_password_hint), value = hint.orEmpty(), // You can have an empty password hint. canBeEmpty = true, ), - title = scope.translate(Res.strings.account_action_change_master_password_hint_title), + title = scope.translate(Res.string.account_action_change_master_password_hint_title), ) { newHint -> val profileIdsToNames = mapOf( AccountId(profile.accountId) to newHint, @@ -1070,13 +1077,15 @@ private suspend fun FlowCollector.emitMasterPasswordHint( val id = "master_password_hint" val hintEditActionItem = FlatItemAction( icon = Icons.Outlined.Edit, - title = scope.translate(Res.strings.account_action_change_master_password_hint_title), - onClick = ::onClick, + title = Res.string.account_action_change_master_password_hint_title.wrap(), + onClick = scope.onClick { + onClick() + }, ) val hintItem = VaultViewItem.Value( id = id, - title = scope.translate(Res.strings.master_password_hint), + title = scope.translate(Res.string.master_password_hint), value = hint.orEmpty(), private = true, leading = { @@ -1086,7 +1095,7 @@ private suspend fun FlowCollector.emitMasterPasswordHint( if (!hint.isNullOrBlank()) { section { this += copyText.FlatItemAction( - title = scope.translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = hint, ) } @@ -1115,7 +1124,7 @@ private suspend fun FlowCollector.emitFingerprint( if (fingerprint.isNotBlank()) { val item = VaultViewItem.Value( id = id, - title = scope.translate(Res.strings.fingerprint_phrase), + title = scope.translate(Res.string.fingerprint_phrase), value = fingerprint, monospace = true, colorize = true, @@ -1125,7 +1134,7 @@ private suspend fun FlowCollector.emitFingerprint( dropdown = buildContextItems { section { this += copyText.FlatItemAction( - title = scope.translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = fingerprint, ) } @@ -1146,7 +1155,7 @@ private suspend fun FlowCollector.emitFingerprint( section { this += FlatItemAction( icon = Icons.Outlined.HelpOutline, - title = scope.translate(Res.strings.fingerprint_phrase_help_title), + title = Res.string.fingerprint_phrase_help_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorEmail.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorEmail.kt index 6c572481..de61056c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorEmail.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorEmail.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -36,10 +37,10 @@ fun validateEmail(email: String?): ValidationEmail { * @return human-readable variant of [validateEmail] result, or `null` if * there's no validation error. */ -fun ValidationEmail.format(scope: TranslatorScope): String? = +suspend fun ValidationEmail.format(scope: TranslatorScope): String? = when (this) { - ValidationEmail.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) - ValidationEmail.ERROR_INVALID -> scope.translate(Res.strings.error_invalid_email) + ValidationEmail.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) + ValidationEmail.ERROR_INVALID -> scope.translate(Res.string.error_invalid_email) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorFeedback.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorFeedback.kt index 592db4ce..d8543bc0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorFeedback.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorFeedback.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -23,9 +24,9 @@ fun validateFeedback(feedback: String?): ValidationFeedback { * @return human-readable variant of [validateFeedback] result, or `null` if * there's no validation error. */ -fun ValidationFeedback.format(scope: TranslatorScope): String? = +suspend fun ValidationFeedback.format(scope: TranslatorScope): String? = when (this) { - ValidationFeedback.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) + ValidationFeedback.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorInteger.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorInteger.kt index 77d68b95..86d028c6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorInteger.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorInteger.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -32,10 +33,10 @@ fun validateInteger( } } -fun ValidationInteger.format(scope: TranslatorScope): String? = +suspend fun ValidationInteger.format(scope: TranslatorScope): String? = when (this) { - ValidationInteger.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) - ValidationInteger.ERROR_INVALID -> scope.translate(Res.strings.error_must_be_number) + ValidationInteger.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) + ValidationInteger.ERROR_INVALID -> scope.translate(Res.string.error_must_be_number) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorPassword.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorPassword.kt index 2ca59d9b..971e590c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorPassword.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorPassword.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -29,10 +30,10 @@ fun validatePassword( } } -fun ValidationPassword.format(scope: TranslatorScope): String? = +suspend fun ValidationPassword.format(scope: TranslatorScope): String? = when (this) { ValidationPassword.ERROR_MIN_LENGTH -> scope.translate( - res = Res.strings.error_must_have_at_least_n_symbols, + res = Res.string.error_must_have_at_least_n_symbols, ValidationPassword.Const.MIN_LENGTH, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorTitle.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorTitle.kt index 7b361359..31892323 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorTitle.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorTitle.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -19,9 +20,9 @@ fun validateTitle(title: String?): ValidationTitle { } } -fun ValidationTitle.format(scope: TranslatorScope): String? = +suspend fun ValidationTitle.format(scope: TranslatorScope): String? = when (this) { - ValidationTitle.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) + ValidationTitle.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUri.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUri.kt index 49845ad0..816f3ba6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUri.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUri.kt @@ -2,6 +2,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* enum class ValidationUri { OK, @@ -49,7 +50,7 @@ fun validateUri( uri: String?, allowBlank: Boolean = false, ): ValidationUri { - return if (uri == null || uri.isBlank()) { + return if (uri.isNullOrBlank()) { if (allowBlank) { ValidationUri.OK } else { @@ -62,9 +63,9 @@ fun validateUri( } } -fun ValidationUri.format(scope: TranslatorScope): String? = +suspend fun ValidationUri.format(scope: TranslatorScope): String? = when (this) { - ValidationUri.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) - ValidationUri.ERROR_INVALID -> scope.translate(Res.strings.error_invalid_uri) + ValidationUri.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) + ValidationUri.ERROR_INVALID -> scope.translate(Res.string.error_invalid_uri) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUrl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUrl.kt index 18ea24ee..3c981902 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUrl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/common/util/ValidatorUrl.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.auth.common.util import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -77,10 +78,10 @@ fun validateUrl( * @return human-readable variant of [validateEmail] result, or `null` if * there's no validation error. */ -fun ValidationUrl.format(scope: TranslatorScope): String? = +suspend fun ValidationUrl.format(scope: TranslatorScope): String? = when (this) { - ValidationUrl.ERROR_EMPTY -> scope.translate(Res.strings.error_must_not_be_blank) - ValidationUrl.ERROR_INVALID -> scope.translate(Res.strings.error_invalid_url) + ValidationUrl.ERROR_EMPTY -> scope.translate(Res.string.error_must_not_be_blank) + ValidationUrl.ERROR_INVALID -> scope.translate(Res.string.error_invalid_url) else -> null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginRegion.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginRegion.kt index e1ba3549..9102ef82 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginRegion.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginRegion.kt @@ -2,7 +2,8 @@ package com.artemchep.keyguard.feature.auth.login import com.artemchep.keyguard.provider.bitwarden.ServerEnv import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.toPersistentList @@ -59,6 +60,6 @@ sealed interface LoginRegion { get() = ServerEnv.Region.selfhosted override val title: StringResource - get() = Res.strings.addaccount_region_custom_type + get() = Res.string.addaccount_region_custom_type } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginScreen.kt index e040cc28..e6b5efbe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginScreen.kt @@ -60,6 +60,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.BiFlatTextField import com.artemchep.keyguard.ui.CollectedEffect import com.artemchep.keyguard.ui.ConcealedFlatTextField @@ -85,7 +86,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map @Composable @@ -156,7 +157,7 @@ fun LoginContentSkeleton() { LargeToolbar( title = { Text( - text = stringResource(Res.strings.addaccount_header_title), + text = stringResource(Res.string.addaccount_header_title), ) }, navigationIcon = { @@ -220,7 +221,7 @@ fun LoginContent( LargeToolbar( title = { Text( - text = stringResource(Res.strings.addaccount_header_title), + text = stringResource(Res.string.addaccount_header_title), ) }, navigationIcon = { @@ -259,7 +260,7 @@ fun LoginContent( }, text = { Text( - text = stringResource(Res.strings.addaccount_sign_in_button), + text = stringResource(Res.string.addaccount_sign_in_button), ) }, ) @@ -289,7 +290,7 @@ fun LoginContent( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount_disclaimer_bitwarden_label), + text = stringResource(Res.string.addaccount_disclaimer_bitwarden_label), style = MaterialTheme.typography.bodyMedium, ) Spacer(Modifier.height(16.dp)) @@ -348,7 +349,7 @@ fun LoginContent( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount_captcha_need_client_secret_note), + text = stringResource(Res.string.addaccount_captcha_need_client_secret_note), style = MaterialTheme.typography.bodyMedium, ) Box(Modifier.height(16.dp)) @@ -356,7 +357,7 @@ fun LoginContent( ConcealedFlatTextField( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.addaccount_captcha_need_client_secret_label), + label = stringResource(Res.string.addaccount_captcha_need_client_secret_label), value = clientSecret, keyboardOptions = KeyboardOptions( imeAction = when { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginStateProducer.kt index 0e12536f..f5b2965d 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/LoginStateProducer.kt @@ -27,7 +27,10 @@ import com.artemchep.keyguard.feature.auth.common.util.validatedEmail import com.artemchep.keyguard.feature.auth.common.util.validatedPassword import com.artemchep.keyguard.feature.auth.login.otp.LoginTwofaRoute import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize @@ -35,6 +38,7 @@ import com.artemchep.keyguard.provider.bitwarden.ServerEnv import com.artemchep.keyguard.provider.bitwarden.ServerHeader import com.artemchep.keyguard.provider.bitwarden.usecase.internal.AddAccount import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.icon import kotlinx.collections.immutable.persistentListOf @@ -200,7 +204,7 @@ fun produceLoginScreenState( .map { region -> FlatItemAction( id = region.key, - title = translate(region.title), + title = region.title.wrap(), onClick = { regionSink.value = region.key }, @@ -243,7 +247,7 @@ fun produceLoginScreenState( if (isUnsecure) { return@run TextFieldModel2.Vl( type = TextFieldModel2.Vl.Type.WARNING, - text = translate(Res.strings.uri_unsecure), + text = translate(Res.string.uri_unsecure), ) } @@ -287,7 +291,7 @@ fun produceLoginScreenState( val globalItems = listOf( LoginStateItem.Section( id = KEY_SERVER_REGION_SECTION, - text = translate(Res.strings.addaccount_region_section), + text = translate(Res.string.addaccount_region_section), ), LoginStateItem.Dropdown( id = KEY_SERVER_REGION, @@ -314,13 +318,13 @@ fun produceLoginScreenState( val envServerBaseUrlItem = createEnvUrlItem( key = KEY_SERVER_BASE_URL, - label = translate(Res.strings.addaccount_base_env_server_url_label), + label = translate(Res.string.addaccount_base_env_server_url_label), initialValue = { args.env.baseUrl }, ) { copy(baseUrl = it) } val envServerCustomIdentityUrlItem = createEnvUrlItem( key = KEY_SERVER_CUSTOM_IDENTITY_URL, - label = translate(Res.strings.addaccount_custom_env_identity_url_label), + label = translate(Res.string.addaccount_custom_env_identity_url_label), initialValue = { args.env.identityUrl }, ) { copy(identityUrl = it) } @@ -329,32 +333,32 @@ fun produceLoginScreenState( envServerBaseUrlItem, LoginStateItem.Label( id = KEY_SERVER_BASE_URL_DESCRIPTION, - text = translate(Res.strings.addaccount_base_env_note), + text = translate(Res.string.addaccount_base_env_note), ), // custom LoginStateItem.Section( id = KEY_SERVER_CUSTOM_SECTION, - text = translate(Res.strings.addaccount_custom_env_section), + text = translate(Res.string.addaccount_custom_env_section), ), createEnvUrlItem( key = KEY_SERVER_CUSTOM_WEB_VAULT_URL, - label = translate(Res.strings.addaccount_custom_env_web_vault_url_label), + label = translate(Res.string.addaccount_custom_env_web_vault_url_label), initialValue = { args.env.webVaultUrl }, ) { copy(webVaultUrl = it) }, createEnvUrlItem( key = KEY_SERVER_CUSTOM_API_URL, - label = translate(Res.strings.addaccount_custom_env_api_url_label), + label = translate(Res.string.addaccount_custom_env_api_url_label), initialValue = { args.env.apiUrl }, ) { copy(apiUrl = it) }, envServerCustomIdentityUrlItem, createEnvUrlItem( key = KEY_SERVER_CUSTOM_ICONS_URL, - label = translate(Res.strings.addaccount_custom_env_icons_url_label), + label = translate(Res.string.addaccount_custom_env_icons_url_label), initialValue = { args.env.iconsUrl }, ) { copy(iconsUrl = it) }, LoginStateItem.Label( id = KEY_SERVER_CUSTOM_DESCRIPTION, - text = translate(Res.strings.addaccount_custom_env_note), + text = translate(Res.string.addaccount_custom_env_note), ), ) @@ -410,7 +414,7 @@ fun produceLoginScreenState( clientSecretSink, clientSecretRequiredFlow, ) { clientSecret, clientSecretRequired -> - val error = translate(Res.strings.error_must_not_be_blank) + val error = translate(Res.string.error_must_not_be_blank) .takeIf { clientSecretRequired && clientSecret.isBlank() } if (error != null) { Validated.Failure(clientSecret, error) @@ -454,7 +458,7 @@ fun produceLoginScreenState( listOf( Foo2Type( type = "header", - name = translate(Res.strings.addaccount_http_header_type), + name = translate(Res.string.addaccount_http_header_type), ), ), ) @@ -466,19 +470,19 @@ fun produceLoginScreenState( afterList = { val header = LoginStateItem.Section( id = "header.section", - text = translate(Res.strings.addaccount_http_header_section), + text = translate(Res.string.addaccount_http_header_section), ) add(0, header) }, extra = { typeBasedAddItem( scope = "header", - addText = translate(Res.strings.addaccount_http_header_add_more_button), + addText = translate(Res.string.addaccount_http_header_add_more_button), typesFlow = envHeadersTypesFlow, ).map { items -> val info = LoginStateItem.Label( id = "header.info", - text = translate(Res.strings.addaccount_http_header_note), + text = translate(Res.string.addaccount_http_header_note), ) items + info } @@ -713,13 +717,13 @@ class AddStateItemFieldFactory( val labelFlow = labelSink .map { label -> val error = if (label.isBlank()) { - translate(Res.strings.error_must_not_be_blank) + translate(Res.string.error_must_not_be_blank) } else { null } TextFieldModel2( text = label, - hint = translate(Res.strings.addaccount_http_header_key_label), + hint = translate(Res.string.addaccount_http_header_key_label), error = error, state = labelMutableState, onChange = labelMutableState::value::set, @@ -734,13 +738,13 @@ class AddStateItemFieldFactory( val textFlow = textSink .map { text -> val error = if (!REGEX_US_ASCII.matches(text)) { - translate(Res.strings.error_must_contain_only_us_ascii_chars) + translate(Res.string.error_must_contain_only_us_ascii_chars) } else { null } TextFieldModel2( text = text, - hint = translate(Res.strings.addaccount_http_header_value_label), + hint = translate(Res.string.addaccount_http_header_value_label), error = error, state = textMutableState, onChange = textMutableState::value::set, @@ -814,13 +818,13 @@ data class Foo2InitialState( ) } -fun RememberStateFlowScope.foo3( +suspend fun RememberStateFlowScope.foo3( scope: String, initial: List, initialType: (Argument) -> String, factories: List>, - afterList: MutableList.() -> Unit, - extra: FieldBakeryScope.() -> Flow> = { + afterList: suspend MutableList.() -> Unit, + extra: suspend FieldBakeryScope.() -> Flow> = { flowOf(emptyList()) }, ): Flow> where T : LoginStateItem, T : LoginStateItem.HasOptions { @@ -880,7 +884,7 @@ private fun FieldBakeryScope.typeBasedAddItem( val actions = types .map { type -> FlatItemAction( - title = type.name, + title = TextHolder.Value(type.name), onClick = { add(type.type, null) }, @@ -894,14 +898,14 @@ private fun FieldBakeryScope.typeBasedAddItem( } .map { listOfNotNull(it) } -fun RememberStateFlowScope.foo( +suspend fun RememberStateFlowScope.foo( // scope name, scope: String, initialState: Foo2InitialState, entryAdd: suspend RememberStateFlowScope.(CoroutineScope, Foo2Persistable, Argument?) -> T, entryRelease: RememberStateFlowScope.(Foo2Persistable) -> Unit, - afterList: MutableList.() -> Unit, - extra: FieldBakeryScope.() -> Flow> = { + afterList: suspend MutableList.() -> Unit, + extra: suspend FieldBakeryScope.() -> Flow> = { flowOf(emptyList()) }, ): Flow> where T : LoginStateItem, T : LoginStateItem.HasOptions { @@ -1051,24 +1055,24 @@ fun RememberStateFlowScope.foo( if (index > 0) { options += FlatItemAction( icon = Icons.Outlined.ArrowUpward, - title = translate(Res.strings.list_move_up), + title = Res.string.list_move_up.wrap(), onClick = ::moveUp.partially1(entry.perst.key), ) } if (index < state.size - 1) { options += FlatItemAction( icon = Icons.Outlined.ArrowDownward, - title = translate(Res.strings.list_move_down), + title = Res.string.list_move_down.wrap(), onClick = ::moveDown.partially1(entry.perst.key), ) } options += FlatItemAction( icon = Icons.Outlined.DeleteForever, - title = translate(Res.strings.list_remove), - onClick = { + title = Res.string.list_remove.wrap(), + onClick = onClick { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.DeleteForever), - title = translate(Res.strings.list_remove_confirmation_title), + title = translate(Res.string.list_remove_confirmation_title), ) { delete(entry.perst.key) } @@ -1088,7 +1092,8 @@ fun RememberStateFlowScope.foo( .widen() .toMutableList() out += customItems - out.apply(afterList) + afterList(out) + out } .shareIn(screenScope, SharingStarted.WhileSubscribed(5000L), replay = 1) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaScreen.kt index cea2cd39..0220babb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaScreen.kt @@ -55,6 +55,7 @@ import androidx.compose.ui.unit.dp import arrow.core.partially1 import arrow.core.right import com.artemchep.keyguard.common.model.getOrNull +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.yubikey.YubiKeyManual @@ -64,6 +65,7 @@ import com.artemchep.keyguard.feature.yubikey.rememberYubiKey import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.DisabledEmphasisAlpha @@ -87,7 +89,7 @@ import com.artemchep.keyguard.ui.theme.horizontalPaddingHalf import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun LoginTwofaScreen( @@ -120,7 +122,7 @@ fun LoginTwofaScreenContent( LargeToolbar( title = { Text( - text = stringResource(Res.strings.addaccount2fa_header_title), + text = stringResource(Res.string.addaccount2fa_header_title), ) }, navigationIcon = { @@ -246,7 +248,7 @@ private fun TwoFactorProviderSelector( .map { type -> FlatItemAction( id = type.key, - title = type.title, + title = TextHolder.Value(type.title), onClick = type.onClick, ) } @@ -349,7 +351,7 @@ private fun ColumnScope.LoginOtpScreenContentUnsupported( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount2fa_unsupported_note), + text = stringResource(Res.string.addaccount2fa_unsupported_note), style = MaterialTheme.typography.bodyMedium, color = contentColor, ) @@ -369,7 +371,7 @@ private fun ColumnScope.LoginOtpScreenContentUnsupported( }, ) { Text( - text = stringResource(Res.strings.launch_web_vault), + text = stringResource(Res.string.launch_web_vault), ) } } @@ -396,7 +398,7 @@ private fun ColumnScope.LoginOtpScreenContentAuthenticator( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount2fa_otp_note), + text = stringResource(Res.string.addaccount2fa_otp_note), style = MaterialTheme.typography.bodyMedium, ) Spacer(Modifier.height(16.dp)) @@ -407,7 +409,7 @@ private fun ColumnScope.LoginOtpScreenContentAuthenticator( // adds a support for that. fieldModifier = Modifier .focusRequester(focusRequester), - label = stringResource(Res.strings.verification_code), + label = stringResource(Res.string.verification_code), value = state.code, textStyle = TextStyle( fontFamily = monoFontFamily, @@ -442,7 +444,7 @@ private fun ColumnScope.LoginOtpScreenContentAuthenticator( }, content = { Text( - text = stringResource(Res.strings.remember_me), + text = stringResource(Res.string.remember_me), style = MaterialTheme.typography.bodyMedium, ) }, @@ -471,7 +473,7 @@ private fun ColumnScope.LoginOtpScreenContentEmail( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount2fa_email_note, state.email.orEmpty()), + text = stringResource(Res.string.addaccount2fa_email_note, state.email.orEmpty()), style = MaterialTheme.typography.bodyMedium, ) Spacer(Modifier.height(16.dp)) @@ -482,7 +484,7 @@ private fun ColumnScope.LoginOtpScreenContentEmail( // adds a support for that. fieldModifier = Modifier .focusRequester(focusRequester), - label = stringResource(Res.strings.verification_code), + label = stringResource(Res.string.verification_code), value = state.code, textStyle = TextStyle( fontFamily = monoFontFamily, @@ -531,7 +533,7 @@ private fun ColumnScope.LoginOtpScreenContentEmail( }, content = { Text( - text = stringResource(Res.strings.resend_verification_code), + text = stringResource(Res.string.resend_verification_code), style = MaterialTheme.typography.bodyMedium, ) }, @@ -548,7 +550,7 @@ private fun ColumnScope.LoginOtpScreenContentEmail( }, content = { Text( - text = stringResource(Res.strings.remember_me), + text = stringResource(Res.string.remember_me), style = MaterialTheme.typography.bodyMedium, ) }, @@ -645,7 +647,7 @@ private fun ColumnScope.LoginOtpScreenContentYubiKey( }, content = { Text( - text = stringResource(Res.strings.remember_me), + text = stringResource(Res.string.remember_me), style = MaterialTheme.typography.bodyMedium, ) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaStateProducer.kt index 5d7d8c58..c3eedab7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/auth/login/otp/LoginTwofaStateProducer.kt @@ -25,6 +25,7 @@ import com.artemchep.keyguard.provider.bitwarden.model.TwoFactorProviderType import com.artemchep.keyguard.provider.bitwarden.usecase.internal.AddAccount import com.artemchep.keyguard.provider.bitwarden.usecase.internal.RequestEmailTfa import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import io.ktor.http.URLBuilder import io.ktor.http.URLParserException import io.ktor.http.Url @@ -274,7 +275,7 @@ private fun RememberStateFlowScope.createStateFlowForAuthenticator( if (code.length != 6) { Validated.Failure( model = code, - error = translate(Res.strings.error_must_have_exactly_n_symbols, 6), + error = translate(Res.string.error_must_have_exactly_n_symbols, 6), ) } else { Validated.Success( @@ -299,7 +300,7 @@ private fun RememberStateFlowScope.createStateFlowForAuthenticator( val canLogin = codeValidated is Validated.Success && !isLoading val primaryAction = LoginTwofaState.PrimaryAction( - text = translate(Res.strings.continue_), + text = translate(Res.string.continue_), icon = if (isLoading) { LoginTwofaState.PrimaryAction.Icon.LOADING } else { @@ -384,11 +385,13 @@ private fun RememberStateFlowScope.createStateFlowForYubiKey( onComplete = { event: Either -> event.fold( ifLeft = { - val msg = ToastMessage( - title = translate(Res.strings.yubikey_error_failed_to_read), - type = ToastMessage.Type.ERROR, - ) - message(msg) + action { + val msg = ToastMessage( + title = translate(Res.string.yubikey_error_failed_to_read), + type = ToastMessage.Type.ERROR, + ) + message(msg) + } }, ifRight = { token -> onComplete( @@ -423,7 +426,7 @@ private fun RememberStateFlowScope.createStateFlowForEmail( if (code.length != 6) { Validated.Failure( model = code, - error = translate(Res.strings.error_must_have_exactly_n_symbols, 6), + error = translate(Res.string.error_must_have_exactly_n_symbols, 6), ) } else { Validated.Success( @@ -443,7 +446,7 @@ private fun RememberStateFlowScope.createStateFlowForEmail( args.password, ).effectTap { val model = ToastMessage( - title = translate(Res.strings.requested_verification_email), + title = translate(Res.string.requested_verification_email), ) message(model) }, @@ -464,7 +467,7 @@ private fun RememberStateFlowScope.createStateFlowForEmail( val canLogin = codeValidated is Validated.Success && !isLoading val primaryAction = LoginTwofaState.PrimaryAction( - text = translate(Res.strings.continue_), + text = translate(Res.string.continue_), icon = if (isLoading) { LoginTwofaState.PrimaryAction.Icon.LOADING } else { @@ -613,7 +616,7 @@ private fun RememberStateFlowScope.createStateFlowForDuo( } } -private fun RememberStateFlowScope.createStateFlowForFido2WebAuthn( +private suspend fun RememberStateFlowScope.createStateFlowForFido2WebAuthn( cryptoGenerator: CryptoGenerator, base64Service: Base64Service, deeplinkService: DeeplinkService, @@ -643,9 +646,9 @@ private fun RememberStateFlowScope.createStateFlowForFido2WebAuthn( put("data", responseData) } put("callbackUri", callbackUrl) - put("headerText", translate(Res.strings.fido2webauthn_web_title)) - put("btnText", translate(Res.strings.fido2webauthn_action_go_title)) - put("btnReturnText", translate(Res.strings.fido2webauthn_action_return_title)) + put("headerText", translate(Res.string.fido2webauthn_web_title)) + put("btnText", translate(Res.string.fido2webauthn_action_go_title)) + put("btnReturnText", translate(Res.string.fido2webauthn_action_return_title)) } .let { json.encodeToString(it) } .let { base64Service.encodeToString(it) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeRoute.kt index 33f304da..1db9541b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.QrCode import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.model.BarcodeImageFormat +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.icon @@ -44,7 +46,7 @@ data class BarcodeTypeRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.QrCode), - title = translator.translate(Res.strings.barcodetype_action_show_in_barcode_title), + title = Res.string.barcodetype_action_show_in_barcode_title.wrap(), onClick = { val route = BarcodeTypeRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeScreen.kt index e73736b3..325489ff 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeScreen.kt @@ -40,12 +40,13 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.common.usecase.GetBarcodeImage import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.KeepScreenOnEffect import com.artemchep.keyguard.ui.icons.DropdownIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance @Composable @@ -69,7 +70,7 @@ private fun BarcodeTypeContent( Dialog( icon = icon(Icons.Outlined.QrCode), title = { - Text(stringResource(Res.strings.barcodetype_title)) + Text(stringResource(Res.string.barcodetype_title)) }, content = { Column { @@ -153,7 +154,7 @@ private fun BarcodeTypeContent( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeStateProducer.kt index 933162a7..047e8b16 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/barcodetype/BarcodeTypeStateProducer.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.model.BarcodeImageFormat import com.artemchep.keyguard.common.model.BarcodeImageRequest import com.artemchep.keyguard.common.model.Loadable +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState @@ -60,7 +61,7 @@ fun produceBarcodeTypeScreenState( val formatActions = formatList .map { format -> FlatItemAction( - title = format.formatTitle(), + title = TextHolder.Value(format.formatTitle()), onClick = { formatSink.value = format.name }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordScreen.kt index 7d4b0618..c3c0e458 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordScreen.kt @@ -27,6 +27,7 @@ import com.artemchep.keyguard.common.model.fold import com.artemchep.keyguard.feature.biometric.BiometricPromptEffect import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AutofillButton import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.FabState @@ -40,7 +41,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun ChangePasswordScreen() { @@ -69,7 +70,7 @@ fun ChangePasswordSkeleton() { LargeToolbar( title = { Text( - text = stringResource(Res.strings.changepassword_header_title), + text = stringResource(Res.string.changepassword_header_title), ) }, navigationIcon = { @@ -158,7 +159,7 @@ fun ChangePasswordScreen( LargeToolbar( title = { Text( - text = stringResource(Res.strings.changepassword_header_title), + text = stringResource(Res.string.changepassword_header_title), ) }, navigationIcon = { @@ -199,7 +200,7 @@ fun ChangePasswordScreen( }, text = { Text( - text = stringResource(Res.strings.changepassword_change_password_button), + text = stringResource(Res.string.changepassword_change_password_button), ) }, ) @@ -209,14 +210,14 @@ fun ChangePasswordScreen( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), value = state.password.current, - label = stringResource(Res.strings.current_password), + label = stringResource(Res.string.current_password), ) Spacer(Modifier.height(8.dp)) PasswordFlatTextField( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), value = state.password.new, - label = stringResource(Res.strings.new_password), + label = stringResource(Res.string.new_password), trailing = { AutofillButton( key = "password", @@ -239,7 +240,7 @@ fun ChangePasswordScreen( }, content = { Text( - text = stringResource(Res.strings.changepassword_biometric_auth_checkbox), + text = stringResource(Res.string.changepassword_biometric_auth_checkbox), style = MaterialTheme.typography.bodyMedium, ) }, @@ -265,7 +266,7 @@ fun ChangePasswordScreen( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.changepassword_disclaimer_local_note), + text = stringResource(Res.string.changepassword_disclaimer_local_note), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -277,7 +278,7 @@ fun ChangePasswordScreen( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.changepassword_disclaimer_abuse_note), + text = stringResource(Res.string.changepassword_disclaimer_abuse_note), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordStateProducer.kt index 204e91c6..d0ea75ce 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/changepassword/ChangePasswordStateProducer.kt @@ -20,6 +20,7 @@ import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first @@ -192,7 +193,7 @@ private fun RememberStateFlowScope.ah( ifRight = ::identity, ) val prompt = BiometricAuthPrompt( - title = TextHolder.Res(Res.strings.changepassword_biometric_auth_confirm_title), + title = TextHolder.Res(Res.string.changepassword_biometric_auth_confirm_title), cipher = cipher, requireConfirmation = requireConfirmation, onComplete = { result -> diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/colorpicker/ColorPickerScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/colorpicker/ColorPickerScreen.kt index cd79a660..30b8b8c5 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/colorpicker/ColorPickerScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/colorpicker/ColorPickerScreen.kt @@ -32,10 +32,11 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.isDark -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun ColorPickerScreen( @@ -49,7 +50,7 @@ fun ColorPickerScreen( Dialog( icon = icon(Icons.Outlined.ColorLens), title = { - Text(stringResource(Res.strings.colorpicker_title)) + Text(stringResource(Res.string.colorpicker_title)) }, content = { Column { @@ -72,7 +73,7 @@ fun ColorPickerScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = updatedOnOk != null, @@ -80,7 +81,7 @@ fun ColorPickerScreen( updatedOnOk?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationScreen.kt index 234a4a4d..2c1a9775 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationScreen.kt @@ -49,6 +49,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.search.filter.component.FilterItemComposable import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AutofillButton import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.ExpandedIfNotEmptyForRow @@ -61,7 +62,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun ConfirmationScreen( @@ -149,7 +150,7 @@ fun ConfirmationScreen( }, ) { Text( - text = stringResource(Res.strings.uri_action_launch_docs_title), + text = stringResource(Res.string.uri_action_launch_docs_title), ) } Spacer( @@ -166,7 +167,7 @@ fun ConfirmationScreen( updatedOnDeny?.invoke() }, ) { - Text(stringResource(Res.strings.cancel)) + Text(stringResource(Res.string.cancel)) } TextButton( enabled = state.onConfirm != null, @@ -174,7 +175,7 @@ fun ConfirmationScreen( updatedOnConfirm?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) @@ -398,7 +399,7 @@ private fun ConfirmationEnumItem( }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } @@ -485,7 +486,7 @@ private fun ConfirmationFileItem( } } else { Text( - text = stringResource(Res.strings.select_file), + text = stringResource(Res.string.select_file), style = MaterialTheme.typography.bodySmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationStateProducer.kt index b9a499ac..3ff3335b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/ConfirmationStateProducer.kt @@ -16,6 +16,7 @@ import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map import org.kodein.di.compose.localDI @@ -88,7 +89,7 @@ fun confirmationState( val error = if (item.canBeEmpty || fixed.isNotBlank()) { null } else { - translate(Res.strings.error_must_not_be_blank) + translate(Res.string.error_must_not_be_blank) } val sensitive = item.type == ConfirmationRoute.Args.Item.StringItem.Type.Password || diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessScreen.kt index e21fb360..7cbf75d7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessScreen.kt @@ -34,6 +34,7 @@ import com.artemchep.keyguard.feature.biometric.BiometricPromptEffect import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.PasswordFlatTextField import com.artemchep.keyguard.ui.focus.FocusRequester2 @@ -43,7 +44,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.util.DividerColor -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay @Composable @@ -63,7 +64,7 @@ fun ElevatedAccessScreen( Dialog( icon = icon(Icons.Outlined.Security), title = { - Text(stringResource(Res.strings.elevatedaccess_header_title)) + Text(stringResource(Res.string.elevatedaccess_header_title)) }, content = { Column( @@ -94,7 +95,7 @@ fun ElevatedAccessScreen( updatedOnDeny?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( modifier = Modifier @@ -104,7 +105,7 @@ fun ElevatedAccessScreen( updatedOnConfirm?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) @@ -151,7 +152,7 @@ private fun ColumnScope.ElevatedAccessContent( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.elevatedaccess_header_text), + text = stringResource(Res.string.elevatedaccess_header_text), ) Spacer(modifier = Modifier.height(16.dp)) PasswordFlatTextField( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessStateProducer.kt index 99974bcc..ce05353d 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/elevatedaccess/ElevatedAccessStateProducer.kt @@ -27,6 +27,7 @@ import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first @@ -155,7 +156,7 @@ fun produceElevatedAccessState( transmitter(ElevatedAccessResult.Allow) } else { val message = ToastMessage( - title = translate(Res.strings.error_incorrect_password), + title = translate(Res.string.error_incorrect_password), type = ToastMessage.Type.ERROR, ) message(message) @@ -176,8 +177,8 @@ private fun createPromptOrNull( fn: () -> Unit, ): PureBiometricAuthPrompt = run { BiometricAuthPromptSimple( - title = TextHolder.Res(Res.strings.elevatedaccess_biometric_auth_confirm_title), - text = TextHolder.Res(Res.strings.elevatedaccess_biometric_auth_confirm_text), + title = TextHolder.Res(Res.string.elevatedaccess_biometric_auth_confirm_title), + text = TextHolder.Res(Res.string.elevatedaccess_biometric_auth_confirm_text), requireConfirmation = requireConfirmation, onComplete = { result -> result.fold( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationScreen.kt index 41dd1938..d24e15ca 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationScreen.kt @@ -33,6 +33,7 @@ import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.search.filter.component.FilterItemComposable import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatTextField import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -42,7 +43,7 @@ import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay @OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class) @@ -58,7 +59,7 @@ fun FolderConfirmationScreen( Dialog( icon = icon(Icons.Outlined.Folder), title = { - Text(stringResource(Res.strings.folderpicker_header_title)) + Text(stringResource(Res.string.folderpicker_header_title)) }, content = { val data = state.content.getOrNull() @@ -110,7 +111,7 @@ fun FolderConfirmationScreen( updatedOnDeny?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = state.onConfirm != null, @@ -118,7 +119,7 @@ fun FolderConfirmationScreen( updatedOnConfirm?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) @@ -145,7 +146,7 @@ fun CreateNewFolder( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.folderpicker_create_new_folder), + text = stringResource(Res.string.folderpicker_create_new_folder), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -157,7 +158,7 @@ fun CreateNewFolder( fieldModifier = Modifier .focusRequester2(requester), value = it, - label = stringResource(Res.strings.generic_name), + label = stringResource(Res.string.generic_name), ) LaunchedEffect(requester) { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationStateProducer.kt index 9a9c144c..4f1a8eff 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/folder/FolderConfirmationStateProducer.kt @@ -21,6 +21,7 @@ import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged @@ -151,7 +152,7 @@ fun folderConfirmationState( items += FolderVariant( accountId = args.accountId.id, folder = FolderVariant.FolderInfo.None, - name = translate(Res.strings.folder_none), + name = translate(Res.string.folder_none), enabled = enabled, ) } @@ -160,7 +161,7 @@ fun folderConfirmationState( items += FolderVariant( accountId = args.accountId.id, folder = FolderVariant.FolderInfo.New, - name = translate(Res.strings.folder_new), + name = translate(Res.string.folder_new), enabled = true, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationScreen.kt index 493de156..711a2940 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationScreen.kt @@ -27,11 +27,12 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.search.filter.component.FilterItemComposable import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun OrganizationConfirmationScreen( @@ -72,22 +73,22 @@ private fun OrganizationConfirmationScreen( val accountsOrNull = state.content.getOrNull()?.accounts FolderSection( - title = stringResource(Res.strings.accounts), + title = stringResource(Res.string.accounts), section = accountsOrNull, ) val organizationsOrNull = state.content.getOrNull()?.organizations FolderSection( - title = stringResource(Res.strings.organizations), + title = stringResource(Res.string.organizations), section = organizationsOrNull, ) val collectionsOrNull = state.content.getOrNull()?.collections FolderSection( - title = stringResource(Res.strings.collections), + title = stringResource(Res.string.collections), section = collectionsOrNull, ) val foldersOrNull = state.content.getOrNull()?.folders FolderSection( - title = stringResource(Res.strings.folders), + title = stringResource(Res.string.folders), section = foldersOrNull, ) @@ -114,7 +115,7 @@ private fun OrganizationConfirmationScreen( updatedOnDeny?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = state.onConfirm != null, @@ -122,7 +123,7 @@ private fun OrganizationConfirmationScreen( updatedOnConfirm?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationStateProducer.kt index 84dfa61d..6adf7038 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/confirmation/organization/OrganizationConfirmationStateProducer.kt @@ -33,6 +33,7 @@ import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.AccentColors import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.isDark @@ -254,7 +255,7 @@ fun organizationConfirmationState( OrganizationVariant( accountId = account.accountId, organizationId = null, - name = translate(Res.strings.organization_none), + name = translate(Res.string.organization_none), enabled = enabled, ) } @@ -302,7 +303,7 @@ fun organizationConfirmationState( items += FolderVariant( accountId = account.accountId, folder = FolderVariant.FolderInfo.None, - name = translate(Res.strings.folder_none), + name = translate(Res.string.folder_none), enabled = enabled, ) } @@ -312,7 +313,7 @@ fun organizationConfirmationState( items += FolderVariant( accountId = account.accountId, folder = FolderVariant.FolderInfo.New, - name = translate(Res.strings.folder_new), + name = translate(Res.string.folder_new), enabled = enabled, ) } @@ -535,7 +536,7 @@ fun organizationConfirmationState( .toList() OrganizationConfirmationState.Content.Section( items = items, - text = translate(Res.strings.destinationpicker_organization_ownership_note) + text = translate(Res.string.destinationpicker_organization_ownership_note) .takeIf { selectedOrganizationId != null }, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datasafety/DataSafetyScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datasafety/DataSafetyScreen.kt index 8aecf412..c580b287 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datasafety/DataSafetyScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datasafety/DataSafetyScreen.kt @@ -31,13 +31,14 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -51,7 +52,7 @@ fun DataSafetyScreen() { LargeToolbar( title = { Text( - text = stringResource(Res.strings.datasafety_header_title), + text = stringResource(Res.string.datasafety_header_title), ) }, navigationIcon = { @@ -76,39 +77,39 @@ private fun ColumnScope.DataSafetyScreenContent() { ) LargeSection( - text = stringResource(Res.strings.datasafety_local_section), + text = stringResource(Res.string.datasafety_local_section), ) Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.datasafety_local_text), + text = stringResource(Res.string.datasafety_local_text), ) Spacer( modifier = Modifier .height(16.dp), ) Section( - text = stringResource(Res.strings.datasafety_local_downloads_section), + text = stringResource(Res.string.datasafety_local_downloads_section), ) TwoColumnRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = Dimens.horizontalPadding), - title = stringResource(Res.strings.encryption), - value = stringResource(Res.strings.none), + title = stringResource(Res.string.encryption), + value = stringResource(Res.string.none), ) Spacer( modifier = Modifier .height(16.dp), ) Section( - text = stringResource(Res.strings.datasafety_local_settings_section), + text = stringResource(Res.string.datasafety_local_settings_section), ) TwoColumnRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = Dimens.horizontalPadding), - title = stringResource(Res.strings.encryption), + title = stringResource(Res.string.encryption), value = "256-bit AES", ) Spacer( @@ -122,7 +123,7 @@ private fun ColumnScope.DataSafetyScreenContent() { Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.datasafety_local_settings_note), + text = stringResource(Res.string.datasafety_local_settings_note), ) } } @@ -131,14 +132,14 @@ private fun ColumnScope.DataSafetyScreenContent() { .height(16.dp), ) Section( - text = stringResource(Res.strings.datasafety_local_vault_section), + text = stringResource(Res.string.datasafety_local_vault_section), ) TwoColumnRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = Dimens.horizontalPadding), - title = stringResource(Res.strings.encryption), - value = stringResource(Res.strings.encryption_algorithm_256bit_aes), + title = stringResource(Res.string.encryption), + value = stringResource(Res.string.encryption_algorithm_256bit_aes), ) Spacer( modifier = Modifier @@ -148,15 +149,15 @@ private fun ColumnScope.DataSafetyScreenContent() { LocalTextStyle provides secondaryTextStyle, ) { Column { - val labelAppPassword = stringResource(Res.strings.app_password) - val labelHash = stringResource(Res.strings.encryption_hash) - val labelSalt = stringResource(Res.strings.encryption_salt) - val labelKey = stringResource(Res.strings.encryption_key) + val labelAppPassword = stringResource(Res.string.app_password) + val labelHash = stringResource(Res.string.encryption_hash) + val labelSalt = stringResource(Res.string.encryption_salt) + val labelKey = stringResource(Res.string.encryption_key) Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), text = stringResource( - Res.strings.datasafety_local_encryption_algorithm_intro, + Res.string.datasafety_local_encryption_algorithm_intro, ), ) Spacer( @@ -168,7 +169,7 @@ private fun ColumnScope.DataSafetyScreenContent() { .fillMaxWidth() .padding(horizontal = Dimens.horizontalPadding), title = labelSalt, - value = stringResource(Res.strings.encryption_random_bits_data, 64), + value = stringResource(Res.string.encryption_random_bits_data, 64), ) HorizontalDivider( modifier = Modifier @@ -202,7 +203,7 @@ private fun ColumnScope.DataSafetyScreenContent() { modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), text = stringResource( - Res.strings.datasafety_local_encryption_algorithm_outro, + Res.string.datasafety_local_encryption_algorithm_outro, ), ) } @@ -215,17 +216,17 @@ private fun ColumnScope.DataSafetyScreenContent() { modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), text = stringResource( - Res.strings.datasafety_local_unlocking_vault, - stringResource(Res.strings.encryption_key), + Res.string.datasafety_local_unlocking_vault, + stringResource(Res.string.encryption_key), ), ) LargeSection( - text = stringResource(Res.strings.datasafety_remote_section), + text = stringResource(Res.string.datasafety_remote_section), ) Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.datasafety_remote_text), + text = stringResource(Res.string.datasafety_remote_text), ) TextButton( modifier = Modifier @@ -241,7 +242,7 @@ private fun ColumnScope.DataSafetyScreenContent() { }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datedaypicker/DateDayPickerScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datedaypicker/DateDayPickerScreen.kt index 1df831a8..74ea8b91 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datedaypicker/DateDayPickerScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datedaypicker/DateDayPickerScreen.kt @@ -17,7 +17,8 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.datetime.Instant @@ -55,7 +56,7 @@ fun DatePickerScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = updatedOnOk != null, @@ -63,7 +64,7 @@ fun DatePickerScreen( updatedOnOk?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerScreen.kt index 409c65d7..9ddbf714 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerScreen.kt @@ -28,12 +28,13 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.selectedContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList @Composable @@ -48,7 +49,7 @@ fun DatePickerScreen( Dialog( icon = icon(Icons.Outlined.CalendarMonth), title = { - Text(stringResource(Res.strings.datepicker_title)) + Text(stringResource(Res.string.datepicker_title)) }, content = { Column { @@ -69,7 +70,7 @@ fun DatePickerScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = updatedOnOk != null, @@ -77,7 +78,7 @@ fun DatePickerScreen( updatedOnOk?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerStateProducer.kt index ddcab7ca..735a05cb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/datepicker/DatePickerStateProducer.kt @@ -6,7 +6,8 @@ import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.combine import kotlinx.datetime.Clock @@ -102,18 +103,18 @@ fun produceDatePickerState( } fun getMonthTitleStringRes(month: Int): StringResource = when (month) { - 1 -> Res.strings.january - 2 -> Res.strings.february - 3 -> Res.strings.march - 4 -> Res.strings.april - 5 -> Res.strings.may - 6 -> Res.strings.june - 7 -> Res.strings.july - 8 -> Res.strings.august - 9 -> Res.strings.september - 10 -> Res.strings.october - 11 -> Res.strings.november - 12 -> Res.strings.december + 1 -> Res.string.january + 2 -> Res.string.february + 3 -> Res.string.march + 4 -> Res.string.april + 5 -> Res.string.may + 6 -> Res.string.june + 7 -> Res.string.july + 8 -> Res.string.august + 9 -> Res.string.september + 10 -> Res.string.october + 11 -> Res.string.november + 12 -> Res.string.december else -> throw IllegalArgumentException("Number of the month should be in 1..12 range, got $month instead!") } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/decorator/ItemDecorator.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/decorator/ItemDecorator.kt index a3f2b4f6..770926cb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/decorator/ItemDecorator.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/decorator/ItemDecorator.kt @@ -6,11 +6,11 @@ import kotlinx.datetime.TimeZone import kotlinx.datetime.monthsUntil interface ItemDecorator { - fun getOrNull(item: Value): Generic? + suspend fun getOrNull(item: Value): Generic? } object ItemDecoratorNone : ItemDecorator { - override fun getOrNull(item: Any) = null + override suspend fun getOrNull(item: Any) = null } class ItemDecoratorDate( @@ -26,7 +26,7 @@ class ItemDecoratorDate( */ private var lastMonths: Int? = null - override fun getOrNull(item: Value): Generic? { + override suspend fun getOrNull(item: Value): Generic? { val instant = selector(item) ?: return null val months = instant .monthsUntil(past, TimeZone.UTC) @@ -54,7 +54,7 @@ class ItemDecoratorTitle( */ private var lastChar: Char? = null - override fun getOrNull(item: Value): Generic? { + override suspend fun getOrNull(item: Value): Generic? { val char = selector(item) ?.firstOrNull() ?.uppercaseChar() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListScreen.kt index b410b59d..56630bb8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListScreen.kt @@ -38,6 +38,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationEntry import com.artemchep.keyguard.feature.navigation.LocalNavigationRouter import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Compose import com.artemchep.keyguard.ui.DefaultSelection import com.artemchep.keyguard.ui.DropdownMenuItemFlat @@ -51,7 +52,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @OptIn( ExperimentalMaterial3Api::class, @@ -107,7 +108,7 @@ fun DuplicatesListScreen( title = { Column() { Text( - text = stringResource(Res.strings.watchtower_header_title), + text = stringResource(Res.string.watchtower_header_title), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -115,7 +116,7 @@ fun DuplicatesListScreen( maxLines = 2, ) Text( - text = stringResource(Res.strings.watchtower_item_duplicate_items_title), + text = stringResource(Res.string.watchtower_item_duplicate_items_title), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -137,7 +138,7 @@ fun DuplicatesListScreen( ) { Column { Text( - text = stringResource(Res.strings.tolerance), + text = stringResource(Res.string.tolerance), ) val textResOrNull = loadableState.getOrNull()?.sensitivity?.title @@ -229,7 +230,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.duplicates_empty_label), + text = stringResource(Res.string.duplicates_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListStateProducer.kt index c4a8dd77..43f285a7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/duplicates/list/DuplicatesListStateProducer.kt @@ -53,11 +53,13 @@ import com.artemchep.keyguard.feature.home.vault.util.cipherRestoreAction import com.artemchep.keyguard.feature.home.vault.util.cipherTrashAction import com.artemchep.keyguard.feature.home.vault.util.cipherViewPasswordHistoryAction import com.artemchep.keyguard.feature.home.vault.util.cipherWatchtowerAlerts +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.copy import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.icons.KeyguardFavourite @@ -322,7 +324,7 @@ fun produceDuplicatesListState( allItems += groupedItems allItems += VaultItem2.Button( id = "merge." + group.id, - title = translate(Res.strings.ciphers_action_merge_title), + title = translate(Res.string.ciphers_action_merge_title), leading = icon(Icons.Outlined.Merge, Icons.Outlined.Add), onClick = { val ciphers = groupedItems @@ -358,7 +360,7 @@ fun produceDuplicatesListState( .entries .map { s -> FlatItemAction( - title = translate(s.title), + title = s.title.wrap(), onClick = { sensitivitySink.value = s }, @@ -437,7 +439,7 @@ fun RememberStateFlowScope.createCipherSelectionFlow( if (canEdit && selectedCiphers.any { !it.favorite }) { actions += FlatItemAction( icon = Icons.Outlined.KeyguardFavourite, - title = translate(Res.strings.ciphers_action_add_to_favorites_title), + title = Res.string.ciphers_action_add_to_favorites_title.wrap(), onClick = { val filteredCipherIds = selectedCiphers .asSequence() @@ -464,7 +466,7 @@ fun RememberStateFlowScope.createCipherSelectionFlow( if (canEdit && selectedCiphers.any { it.favorite }) { actions += FlatItemAction( icon = Icons.Outlined.KeyguardFavouriteOutline, - title = translate(Res.strings.ciphers_action_remove_from_favorites_title), + title = Res.string.ciphers_action_remove_from_favorites_title.wrap(), onClick = { val filteredCipherIds = selectedCiphers .asSequence() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakRoute.kt index 770a0bb4..a8e07436 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.FactCheck import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.model.AccountId +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.icon @@ -34,7 +36,7 @@ data class EmailLeakRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.FactCheck), - title = translator.translate(Res.strings.email_action_check_data_breach_title), + title = Res.string.email_action_check_data_breach_title.wrap(), onClick = { val route = EmailLeakRoute( args = Args( @@ -66,7 +68,7 @@ data class EmailLeakRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.FactCheck), - title = translator.translate(Res.strings.username_action_check_data_breach_title), + title = Res.string.username_action_check_data_breach_title.wrap(), onClick = { val route = EmailLeakRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakScreen.kt index 9938120a..ea65e66d 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/emailleak/EmailLeakScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.favicon.FaviconImage import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.FlatTextFieldBadge @@ -49,7 +50,8 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.pluralStringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance @Composable @@ -62,14 +64,14 @@ fun EmailLeakScreen( Dialog( icon = icon(Icons.Outlined.FactCheck), title = { - Text(stringResource(Res.strings.emailleak_title)) + Text(stringResource(Res.string.emailleak_title)) }, content = { Column { Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.emailleak_note), + text = stringResource(Res.string.emailleak_note), style = MaterialTheme.typography.bodySmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -112,7 +114,7 @@ fun EmailLeakScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -146,7 +148,7 @@ private fun ColumnScope.Content( if (leaks == null) { FlatSimpleNote( type = SimpleNote.Type.WARNING, - text = stringResource(Res.strings.emailleak_failed_to_load_status_text), + text = stringResource(Res.string.emailleak_failed_to_load_status_text), ) return } @@ -154,15 +156,15 @@ private fun ColumnScope.Content( if (leaks.isNotEmpty()) { FlatSimpleNote( type = SimpleNote.Type.WARNING, - title = stringResource(Res.strings.emailleak_breach_found_title), + title = stringResource(Res.string.emailleak_breach_found_title), ) Section( - text = stringResource(Res.strings.emailleak_breach_section), + text = stringResource(Res.string.emailleak_breach_section), ) } else { FlatSimpleNote( type = SimpleNote.Type.OK, - title = stringResource(Res.strings.emailleak_breach_not_found_title), + title = stringResource(Res.string.emailleak_breach_not_found_title), ) } leaks.forEachIndexed { index, item -> @@ -239,7 +241,7 @@ private fun BreachItem( if (item.count != null) { val numberFormatter: NumberFormatter by rememberInstance() Text( - text = stringResource( + text = pluralStringResource( Res.plurals.emailleak_breach_accounts_count_plural, item.count, numberFormatter.formatNumber(item.count.toInt()), @@ -251,7 +253,7 @@ private fun BreachItem( if (item.occurredAt != null) { Text( text = stringResource( - Res.strings.emailleak_breach_occurred_at, + Res.string.emailleak_breach_occurred_at, item.occurredAt, ), style = MaterialTheme.typography.labelSmall, @@ -262,7 +264,7 @@ private fun BreachItem( if (item.reportedAt != null) { Text( text = stringResource( - Res.strings.emailleak_breach_reported_at, + Res.string.emailleak_breach_reported_at, item.reportedAt, ), style = MaterialTheme.typography.labelSmall, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportRoute.kt index 0e59bb0c..05bfec20 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportRoute.kt @@ -7,11 +7,14 @@ import com.artemchep.keyguard.common.model.AccountId import com.artemchep.keyguard.common.model.DFilter import com.artemchep.keyguard.feature.confirmation.elevatedaccess.ElevatedAccessResult import com.artemchep.keyguard.feature.confirmation.elevatedaccess.ElevatedAccessRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.icons.icon @@ -20,7 +23,7 @@ data class ExportRoute( val args: Args, ) : Route { companion object { - fun actionOrNull( + suspend fun actionOrNull( translator: TranslatorScope, accountId: AccountId, individual: Boolean, @@ -32,7 +35,7 @@ data class ExportRoute( navigate = navigate, ) - fun action( + suspend fun action( translator: TranslatorScope, accountId: AccountId, individual: Boolean, @@ -40,9 +43,9 @@ data class ExportRoute( ): FlatItemAction { val title = kotlin.run { val res = if (individual) { - Res.strings.account_action_export_individual_vault_title + Res.string.account_action_export_individual_vault_title } else { - Res.strings.account_action_export_vault_title + Res.string.account_action_export_vault_title } translator.translate(res) } @@ -55,7 +58,7 @@ data class ExportRoute( } icon(res) }, - title = title, + title = TextHolder.Value(title), onClick = { val accountFilter = DFilter.ById( id = accountId.id, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportScreen.kt index 1e4c7e1e..5c3c74bc 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportScreen.kt @@ -41,6 +41,7 @@ import com.artemchep.keyguard.feature.search.filter.FilterScreen import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.platform.LocalLeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AutofillButton import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.ExpandedIfNotEmpty @@ -62,7 +63,7 @@ import com.artemchep.keyguard.ui.theme.warning import com.artemchep.keyguard.ui.theme.warningContainer import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.SmallToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.persistentListOf @Composable @@ -74,7 +75,7 @@ fun ExportScreen( ) val title = args.title - ?: stringResource(Res.strings.exportaccount_header_title) + ?: stringResource(Res.string.exportaccount_header_title) val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() when (loadableState) { is Loadable.Ok -> { @@ -307,7 +308,7 @@ private fun ExportScreen( }, text = { Text( - text = stringResource(Res.strings.exportaccount_export_button), + text = stringResource(Res.string.exportaccount_export_button), ) }, ) @@ -354,7 +355,7 @@ private fun ExportScreen( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.exportaccount_no_attachments_note), + text = stringResource(Res.string.exportaccount_no_attachments_note), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current .combineAlpha(alpha = MediumEmphasisAlpha), @@ -396,7 +397,7 @@ private fun ColumnScope.ExportContentOk( leading = icon(Icons.Outlined.Storage, Icons.Outlined.Warning), title = { Text( - text = stringResource(Res.strings.pref_item_permission_write_external_storage_grant), + text = stringResource(Res.string.pref_item_permission_write_external_storage_grant), ) }, onClick = { @@ -409,7 +410,7 @@ private fun ColumnScope.ExportContentOk( modifier = Modifier .fillMaxWidth() .padding(horizontal = Dimens.horizontalPadding), - label = stringResource(Res.strings.exportaccount_password_label), + label = stringResource(Res.string.exportaccount_password_label), value = password.model, trailing = { AutofillButton( @@ -442,7 +443,7 @@ private fun ColumnScope.ExportContentOk( }, title = { Text( - text = stringResource(Res.strings.items), + text = stringResource(Res.string.items), ) }, trailing = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportStateProducer.kt index 13e477eb..72073c1b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/export/ExportStateProducer.kt @@ -29,8 +29,10 @@ import com.artemchep.keyguard.feature.home.vault.screen.createFilter import com.artemchep.keyguard.feature.home.vault.search.filter.FilterHolder import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf @@ -96,7 +98,7 @@ fun produceExportScreenState( ) .effectTap { val msg = ToastMessage( - title = translate(Res.strings.exportaccount_export_success), + title = translate(Res.string.exportaccount_export_success), type = ToastMessage.Type.SUCCESS, ) message(msg) @@ -202,12 +204,12 @@ fun produceExportScreenState( revision = state.filterConfig?.id ?: 0, list = state.list, count = state.list.size, - onView = { + onView = onClick { val filter = state.filterConfig?.filter val route = VaultRoute( args = VaultRoute.Args( appBar = VaultRoute.Args.AppBar( - title = translate(Res.strings.exportaccount_header_title), + title = translate(Res.string.exportaccount_header_title), ), filter = filter, trash = false, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/feedback/FeedbackScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/feedback/FeedbackScreen.kt index 985180c6..34eba042 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/feedback/FeedbackScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/feedback/FeedbackScreen.kt @@ -26,6 +26,7 @@ import com.artemchep.keyguard.common.model.fold import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.FabState import com.artemchep.keyguard.ui.FlatTextField @@ -35,7 +36,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun FeedbackScreen() { @@ -59,7 +60,7 @@ private fun FeedbackContent( LargeToolbar( title = { Text( - text = stringResource(Res.strings.contactus_header_title), + text = stringResource(Res.string.contactus_header_title), ) }, navigationIcon = { @@ -87,7 +88,7 @@ private fun FeedbackContent( }, text = { Text( - text = stringResource(Res.strings.send), + text = stringResource(Res.string.send), ) }, ) @@ -105,7 +106,7 @@ private fun FeedbackContent( ifOk = { state -> FlatTextField( modifier = contentModifier, - label = stringResource(Res.strings.contactus_message_label), + label = stringResource(Res.string.contactus_message_label), value = state.message, keyboardOptions = KeyboardOptions( autoCorrect = true, @@ -132,7 +133,7 @@ private fun FeedbackContent( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.contactus_english_note), + text = stringResource(Res.string.contactus_english_note), style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, color = LocalContentColor.current.combineAlpha(alpha = MediumEmphasisAlpha), @@ -144,7 +145,7 @@ private fun FeedbackContent( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.contactus_thanks_note), + text = stringResource(Res.string.contactus_thanks_note), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current.combineAlpha(alpha = MediumEmphasisAlpha), ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/CipherFiltersRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/CipherFiltersRoute.kt index 897d5a3a..5b56906f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/CipherFiltersRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/CipherFiltersRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.FilterAlt import androidx.compose.material.icons.outlined.FilterList import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardCipherFilter @@ -29,7 +31,7 @@ object CipherFiltersRoute : Route { navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.KeyguardCipherFilter), - title = translator.translate(Res.strings.customfilters_header_title), + title = Res.string.customfilters_header_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListScreen.kt index 0b14c90f..ef1da139 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListScreen.kt @@ -49,6 +49,7 @@ import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.util.hasDynamicShortcuts import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.DefaultSelection @@ -65,7 +66,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -148,7 +149,7 @@ fun CipherFiltersListScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.customfilters_header_title), + title = stringResource(Res.string.customfilters_header_title), icon = { NavigationIcon() }, @@ -168,7 +169,7 @@ fun CipherFiltersListScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.customfilters_search_placeholder), + placeholder = stringResource(Res.string.customfilters_search_placeholder), searchIcon = false, count = count, leading = {}, @@ -273,7 +274,7 @@ fun CipherFiltersListScreen( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.customfilters_dynamic_shortcut_tip), + text = stringResource(Res.string.customfilters_dynamic_shortcut_tip), style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current .combineAlpha(alpha = MediumEmphasisAlpha), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt index a328c760..c41316da 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt @@ -24,13 +24,16 @@ import com.artemchep.keyguard.feature.generator.wordlist.util.WordlistUtil import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short import com.artemchep.keyguard.feature.home.vault.search.IndexedText +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.search.search.IndexedModel import com.artemchep.keyguard.feature.search.search.mapSearch import com.artemchep.keyguard.feature.search.search.searchFilter import com.artemchep.keyguard.feature.search.search.searchQueryHandle import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -221,22 +224,26 @@ fun produceCipherFiltersListState( section { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = CipherFilterUtil::onRename - .partially1(this@produceScreenState) - .partially1(renameCipherFilter) - .partially1(selectedItem), + title = Res.string.edit.wrap(), + onClick = onClick { + CipherFilterUtil.onRename( + renameCipherFilter = renameCipherFilter, + model = selectedItem, + ) + }, ) } } section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.delete), - onClick = CipherFilterUtil::onDeleteByItems - .partially1(this@produceScreenState) - .partially1(removeCipherFilterById) - .partially1(selectedItems), + title = Res.string.delete.wrap(), + onClick = onClick { + CipherFilterUtil.onDeleteByItems( + removeCipherFilterById = removeCipherFilterById, + items = selectedItems, + ) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt index dfc5df81..1eddf1ee 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt @@ -17,6 +17,7 @@ import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardCipherFilter @@ -26,7 +27,7 @@ import com.artemchep.keyguard.ui.icons.iconSmall object CipherFilterUtil { context(RememberStateFlowScope) - fun onRename( + suspend fun onRename( renameCipherFilter: RenameCipherFilter, model: DCipherFilter, ) { @@ -34,7 +35,7 @@ object CipherFilterUtil { val nameItem = ConfirmationRoute.Args.Item.StringItem( key = nameKey, value = model.name, - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), type = ConfirmationRoute.Args.Item.StringItem.Type.Text, canBeEmpty = false, ) @@ -49,7 +50,7 @@ object CipherFilterUtil { main = Icons.Outlined.KeyguardCipherFilter, secondary = Icons.Outlined.Edit, ), - title = translate(Res.strings.customfilters_edit_filter_title), + title = translate(Res.string.customfilters_edit_filter_title), items = items, docUrl = null, ), @@ -72,14 +73,14 @@ object CipherFilterUtil { } context(RememberStateFlowScope) - fun onDeleteByItems( + suspend fun onDeleteByItems( removeCipherFilterById: RemoveCipherFilterById, items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.customfilters_delete_many_confirmation_title) + translate(Res.string.customfilters_delete_many_confirmation_title) } else { - translate(Res.strings.customfilters_delete_one_confirmation_title) + translate(Res.string.customfilters_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.name } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt index cb211660..82187e1b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt @@ -23,10 +23,13 @@ import com.artemchep.keyguard.feature.filter.util.CipherFilterUtil import com.artemchep.keyguard.feature.filter.util.addShortcutActionOrNull import com.artemchep.keyguard.feature.home.vault.model.FilterItem import com.artemchep.keyguard.feature.home.vault.screen.FilterSection +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.autoclose.launchAutoPopSelfHandler import com.artemchep.keyguard.ui.buildContextItems @@ -198,7 +201,7 @@ fun produceCipherFilterViewState( l += createFilterItem( filter = f, leading = iconSmall(Icons.Outlined.FolderOff), - title = translate(Res.strings.folder_none), + title = translate(Res.string.folder_none), ).let(::flowOf) return@forEach } @@ -211,7 +214,7 @@ fun produceCipherFilterViewState( l += createFilterItem( filter = f, leading = null, - title = translate(Res.strings.collection_none), + title = translate(Res.string.collection_none), ).let(::flowOf) return@forEach } @@ -224,7 +227,7 @@ fun produceCipherFilterViewState( l += createFilterItem( filter = f, leading = null, - title = translate(Res.strings.organization_none), + title = translate(Res.string.organization_none), ).let(::flowOf) return@forEach } @@ -273,11 +276,13 @@ fun produceCipherFilterViewState( section { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = CipherFilterUtil::onRename - .partially1(this@produceScreenState) - .partially1(renameCipherFilter) - .partially1(filter), + title = Res.string.edit.wrap(), + onClick = onClick { + CipherFilterUtil.onRename( + renameCipherFilter = renameCipherFilter, + model = filter, + ) + }, ) } section { @@ -286,11 +291,13 @@ fun produceCipherFilterViewState( ) this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = CipherFilterUtil::onDeleteByItems - .partially1(this@produceScreenState) - .partially1(removeCipherFilterById) - .partially1(filterAsItems), + title = Res.string.delete.wrap(), + onClick = onClick { + CipherFilterUtil.onDeleteByItems( + removeCipherFilterById = removeCipherFilterById, + items = filterAsItems, + ) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorScreen.kt index c10914e1..90c7fc03 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorScreen.kt @@ -86,6 +86,7 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.ExpandedIfNotEmpty @@ -113,7 +114,7 @@ import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.SmallToolbar import com.artemchep.keyguard.ui.util.VerticalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -143,7 +144,7 @@ fun GeneratorScreen( containerColor = Color.Transparent, title = { Text( - text = stringResource(Res.strings.generator_header_title), + text = stringResource(Res.string.generator_header_title), ) }, navigationIcon = { @@ -264,7 +265,7 @@ private fun GeneratorPaneMaster( LargeToolbar( title = { - Text(stringResource(Res.strings.generator_header_title)) + Text(stringResource(Res.string.generator_header_title)) }, navigationIcon = { NavigationIcon() @@ -328,9 +329,9 @@ private fun GeneratorPaneMaster( modifier = Modifier .animateContentSize(), text = if (valueExists) { - stringResource(Res.strings.generator_regenerate_button) + stringResource(Res.string.generator_regenerate_button) } else { - stringResource(Res.strings.generator_generate_button) + stringResource(Res.string.generator_generate_button) }, ) } @@ -434,7 +435,7 @@ fun ColumnScope.GeneratorValue( text = if (password.isEmpty()) { val color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha) - val text = stringResource(Res.strings.empty_value) + val text = stringResource(Res.string.empty_value) buildAnnotatedString { withStyle( style = SpanStyle(color = color), @@ -536,7 +537,7 @@ private fun ColumnScope.GeneratorFilterTip( }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } @@ -560,7 +561,7 @@ private fun ColumnScope.GeneratorFilterItems( Unit.takeIf { showSection }, ) { Section( - text = stringResource(Res.strings.filter_header_title), + text = stringResource(Res.string.filter_header_title), ) } @@ -883,7 +884,7 @@ private fun ColumnScope.DecoratedSliderLayout( modifier = Modifier .weight(1f), style = MaterialTheme.typography.bodyLarge, - text = stringResource(Res.strings.length), + text = stringResource(Res.string.length), ) length( Modifier @@ -946,7 +947,7 @@ fun ColumnScope.DecoratedSlider( modifier = Modifier .weight(1f), style = MaterialTheme.typography.bodyLarge, - text = stringResource(Res.strings.length), + text = stringResource(Res.string.length), ) FilterSwitchItemCounter( counter = counter, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorStateProducer.kt index 4b90bb50..4101efb6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorStateProducer.kt @@ -61,6 +61,8 @@ import com.artemchep.keyguard.feature.generator.history.GeneratorHistoryRoute import com.artemchep.keyguard.feature.generator.wordlist.WordlistsRoute import com.artemchep.keyguard.feature.home.vault.add.AddRoute import com.artemchep.keyguard.feature.home.vault.add.LeAddRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.copy @@ -68,6 +70,7 @@ import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.generatorTarget import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ContextItem import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.buildContextItems @@ -441,7 +444,7 @@ fun produceGeneratorState( } .shareInScreenScope() - fun wordlistFilterItem( + suspend fun wordlistFilterItem( wordlistId: Long?, wordlists: List, onSelect: (Long) -> Unit, @@ -459,8 +462,8 @@ fun produceGeneratorState( numberFormatter.formatNumber(quantity), ) this += FlatItemAction( - title = defaultWordlistName, - text = text, + title = TextHolder.Value(defaultWordlistName), + text = TextHolder.Value(text), onClick = onSelect .partially1(0), ) @@ -474,7 +477,7 @@ fun produceGeneratorState( numberFormatter.formatNumber(quantity), ) this += FlatItemAction( - title = wordlist.name, + title = TextHolder.Value(wordlist.name), leading = { val backgroundColor = if (MaterialTheme.colorScheme.isDark) { wordlist.accentColor.dark @@ -487,7 +490,7 @@ fun produceGeneratorState( .background(backgroundColor, shape = CircleShape), ) }, - text = text, + text = TextHolder.Value(text), onClick = onSelect .partially1(wordlist.idRaw) .takeIf { quantity > 0 }, @@ -667,7 +670,7 @@ fun produceGeneratorState( } val passphraseFilterTip = GeneratorState.Filter.Tip( - text = translate(Res.strings.generator_passphrase_note), + text = translate(Res.string.generator_passphrase_note), onLearnMore = { val url = "https://xkcd.com/936/" val intent = NavigationIntent.NavigateToBrowser(url) @@ -676,13 +679,13 @@ fun produceGeneratorState( onHide = ::hideTip, ) - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.Passphrase, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Text( key = "$PREFIX_PASSPHRASE.delimiter", - title = translate(Res.strings.generator_passphrase_delimiter_title), + title = translate(Res.string.generator_passphrase_delimiter_title), model = TextFieldModel2( state = passphraseDelimiterState, text = config.delimiter, @@ -691,7 +694,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSPHRASE.capitalize", - title = translate(Res.strings.generator_passphrase_capitalize_title), + title = translate(Res.string.generator_passphrase_capitalize_title), model = SwitchFieldModel( checked = config.capitalize, onChange = passphraseCapitalizeSink::value::set, @@ -699,7 +702,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSPHRASE.include_number", - title = translate(Res.strings.generator_passphrase_number_title), + title = translate(Res.string.generator_passphrase_number_title), model = SwitchFieldModel( checked = config.includeNumber, onChange = passphraseIncludeNumberSink::value::set, @@ -707,7 +710,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Enum( key = "$PREFIX_PASSPHRASE.wordlist", - title = translate(Res.strings.generator_passphrase_wordlist_title), + title = translate(Res.string.generator_passphrase_wordlist_title), model = wordlistFilterItem( wordlistId = config.wordlistId, wordlists = config.wordlists, @@ -728,13 +731,13 @@ fun produceGeneratorState( ) } - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.Username, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Text( key = "$PREFIX_PASSPHRASE.custom_word", - title = translate(Res.strings.generator_username_custom_word_title), + title = translate(Res.string.generator_username_custom_word_title), model = TextFieldModel2( state = usernameCustomWordState, text = config.customWord, @@ -743,7 +746,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Text( key = "$PREFIX_PASSPHRASE.delimiter", - title = translate(Res.strings.generator_username_delimiter_title), + title = translate(Res.string.generator_username_delimiter_title), model = TextFieldModel2( state = usernameDelimiterState, text = config.delimiter, @@ -752,7 +755,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_USERNAME.capitalize", - title = translate(Res.strings.generator_username_capitalize_title), + title = translate(Res.string.generator_username_capitalize_title), model = SwitchFieldModel( checked = config.capitalize, onChange = usernameCapitalizeSink::value::set, @@ -760,7 +763,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_USERNAME.include_number", - title = translate(Res.strings.generator_username_number_title), + title = translate(Res.string.generator_username_number_title), model = SwitchFieldModel( checked = config.includeNumber, onChange = usernameIncludeNumberSink::value::set, @@ -768,7 +771,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Enum( key = "$PREFIX_USERNAME.wordlist", - title = translate(Res.strings.generator_username_wordlist_title), + title = translate(Res.string.generator_username_wordlist_title), model = wordlistFilterItem( wordlistId = config.wordlistId, wordlists = config.wordlists, @@ -790,17 +793,17 @@ fun produceGeneratorState( } val passwordFilterTip = GeneratorState.Filter.Tip( - text = translate(Res.strings.generator_password_note, 16), + text = translate(Res.string.generator_password_note, 16), onHide = ::hideTip, ) - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.Password, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.include_numbers", - title = translate(Res.strings.generator_password_numbers_title), + title = translate(Res.string.generator_password_numbers_title), model = SwitchFieldModel( checked = config.includeNumbers, onChange = passwordIncludeNumbersSink::value::set, @@ -815,7 +818,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.include_symbols", - title = translate(Res.strings.generator_password_symbols_title), + title = translate(Res.string.generator_password_symbols_title), text = """!"#$%&'()*+-./:;<=>?@[\]^_`{|}~""", model = SwitchFieldModel( checked = config.includeSymbols, @@ -831,7 +834,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.include_uppercase_chars", - title = translate(Res.strings.generator_password_uppercase_letters_title), + title = translate(Res.string.generator_password_uppercase_letters_title), model = SwitchFieldModel( checked = config.includeUppercaseCharacters, onChange = passwordIncludeUppercaseCharactersSink::value::set, @@ -846,7 +849,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.include_lowercase_chars", - title = translate(Res.strings.generator_password_lowercase_letters_title), + title = translate(Res.string.generator_password_lowercase_letters_title), model = SwitchFieldModel( checked = config.includeLowercaseCharacters, onChange = passwordIncludeLowercaseCharactersSink::value::set, @@ -864,7 +867,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.exclude_similar_chars", - title = translate(Res.strings.generator_password_exclude_similar_symbols_title), + title = translate(Res.string.generator_password_exclude_similar_symbols_title), text = "il1Lo0O", model = SwitchFieldModel( checked = config.excludeSimilarCharacters, @@ -873,7 +876,7 @@ fun produceGeneratorState( ), GeneratorState.Filter.Item.Switch( key = "$PREFIX_PASSWORD.exclude_ambiguous_chars", - title = translate(Res.strings.generator_password_exclude_ambiguous_symbols_title), + title = translate(Res.string.generator_password_exclude_ambiguous_symbols_title), text = """{}[]()/\'"`~,;:.<>""", model = SwitchFieldModel( checked = config.excludeAmbiguousCharacters, @@ -895,7 +898,7 @@ fun produceGeneratorState( } val catchAllEmailFilterTip = GeneratorState.Filter.Tip( - text = translate(Res.strings.generator_email_catch_all_note), + text = translate(Res.string.generator_email_catch_all_note), onHide = ::hideTip, ) @@ -905,26 +908,26 @@ fun produceGeneratorState( navigate(intent) } - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.EmailCatchAll, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Text( key = "$PREFIX_EMAIL_CATCH_ALL.domain", - title = translate(Res.strings.generator_email_catch_all_domain_title), + title = translate(Res.string.generator_email_catch_all_domain_title), model = TextFieldModel2( state = emailCatchAllDomainState, text = config.domain, hint = "example.com", error = when { config.domain.isEmpty() -> - translate(Res.strings.error_must_not_be_empty) + translate(Res.string.error_must_not_be_empty) config.domain in popularEmailDomains -> - translate(Res.strings.error_must_be_custom_domain) + translate(Res.string.error_must_be_custom_domain) !REGEX_DOMAIN.matches(config.domain.trim()) -> - translate(Res.strings.error_invalid_domain) + translate(Res.string.error_invalid_domain) else -> null }, @@ -947,29 +950,29 @@ fun produceGeneratorState( val emailPlusAddressingFilterTip = GeneratorState.Filter.Tip( text = translate( - Res.strings.generator_email_plus_addressing_note, + Res.string.generator_email_plus_addressing_note, "username+abc@example.com", ), onHide = ::hideTip, ) - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.EmailPlusAddressing, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Text( key = "$PREFIX_EMAIL_PLUS_ADDRESSING.email", - title = translate(Res.strings.generator_email_plus_addressing_email_title), + title = translate(Res.string.generator_email_plus_addressing_email_title), model = TextFieldModel2( state = emailPlusAddressingEmailState, text = config.email, hint = "username@example.com", error = when { config.email.isEmpty() -> - translate(Res.strings.error_must_not_be_empty) + translate(Res.string.error_must_not_be_empty) !REGEX_EMAIL.matches(config.email.trim()) -> - translate(Res.strings.error_invalid_email) + translate(Res.string.error_invalid_email) else -> null }, @@ -992,32 +995,32 @@ fun produceGeneratorState( val emailSubdomainAddressingFilterTip = GeneratorState.Filter.Tip( text = translate( - Res.strings.generator_email_subdomain_addressing_note, + Res.string.generator_email_subdomain_addressing_note, "username@abc.example.com", ), onHide = ::hideTip, ) - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2.EmailSubdomainAddressing, ): GeneratorState.Filter { val items = persistentListOf( GeneratorState.Filter.Item.Text( key = "$PREFIX_EMAIL_SUBDOMAIN_ADDRESSING.email", - title = translate(Res.strings.generator_email_subdomain_addressing_email_title), + title = translate(Res.string.generator_email_subdomain_addressing_email_title), model = TextFieldModel2( state = emailSubdomainAddressingEmailState, text = config.email, hint = "username@example.com", error = when { config.email.isEmpty() -> - translate(Res.strings.error_must_not_be_empty) + translate(Res.string.error_must_not_be_empty) config.email.substringAfterLast('@', "") in popularEmailDomains -> - translate(Res.strings.error_must_be_custom_domain) + translate(Res.string.error_must_be_custom_domain) !REGEX_EMAIL.matches(config.email.trim()) -> - translate(Res.strings.error_invalid_email) + translate(Res.string.error_invalid_email) else -> null }, @@ -1050,7 +1053,7 @@ fun produceGeneratorState( ) } - fun createFilter( + suspend fun createFilter( config: PasswordGeneratorConfigBuilder2, ) = when (config) { is PasswordGeneratorConfigBuilder2.Password -> createFilter(config) @@ -1244,7 +1247,7 @@ fun produceGeneratorState( this += when (t.group) { GENERATOR_TYPE_GROUP_INTEGRATION -> ContextItem.Section( - title = translate(Res.strings.emailrelay_list_section_title), + title = translate(Res.string.emailrelay_list_section_title), ) else -> ContextItem.Section() @@ -1268,7 +1271,7 @@ fun produceGeneratorState( .background(backgroundColor, shape = CircleShape), ) }, - title = emailRelay.name, + title = TextHolder.Value(emailRelay.name), onClick = { typeSink.value = t.key }, @@ -1282,7 +1285,7 @@ fun produceGeneratorState( else -> Icons.Outlined.Mail } this += FlatItemAction( - title = translate(t.title), + title = t.title, onClick = { typeSink.value = t.key }, @@ -1390,7 +1393,7 @@ fun produceGeneratorState( val dropdown = buildContextItems { this += copyItemFactory.FlatItemAction( - title = translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = password, type = CopyText.Type.PASSWORD, ) @@ -1400,14 +1403,14 @@ fun produceGeneratorState( if (canWrite && type.username) { list += FlatItemAction( leading = icon(Icons.Outlined.Add), - title = translate(Res.strings.generator_create_item_with_username_title), + title = Res.string.generator_create_item_with_username_title.wrap(), onClick = ::createLoginWithUsername.partially1(password), ) } if (canWrite && type.password) { list += FlatItemAction( leading = icon(Icons.Outlined.Add), - title = translate(Res.strings.generator_create_item_with_password_title), + title = Res.string.generator_create_item_with_password_title.wrap(), onClick = ::createLoginWithPassword.partially1(password), ) } @@ -1452,7 +1455,7 @@ fun produceGeneratorState( val optionsFlow = tipVisibleSink .map { tipVisible -> FlatItemAction( - title = translate(Res.strings.generator_show_tips_title), + title = Res.string.generator_show_tips_title.wrap(), icon = Icons.Outlined.Info, trailing = { Checkbox( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorType.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorType.kt index adf1195e..ec6c9937 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorType.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/GeneratorType.kt @@ -3,6 +3,7 @@ package com.artemchep.keyguard.feature.generator import com.artemchep.keyguard.common.model.DGeneratorEmailRelay import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* const val GENERATOR_TYPE_GROUP_PASSWORD = "password" const val GENERATOR_TYPE_GROUP_USERNAME = "username" @@ -18,7 +19,7 @@ sealed interface GeneratorType2 { data object Password : GeneratorType2 { override val key: String = "PASSWORD" override val group: String = GENERATOR_TYPE_GROUP_PASSWORD - override val title: TextHolder = TextHolder.Res(Res.strings.generator_password_type) + override val title: TextHolder = TextHolder.Res(Res.string.generator_password_type) override val username: Boolean = true override val password: Boolean = true } @@ -26,7 +27,7 @@ sealed interface GeneratorType2 { data object Passphrase : GeneratorType2 { override val key: String = "PASSPHRASE" override val group: String = GENERATOR_TYPE_GROUP_PASSWORD - override val title: TextHolder = TextHolder.Res(Res.strings.generator_passphrase_type) + override val title: TextHolder = TextHolder.Res(Res.string.generator_passphrase_type) override val username: Boolean = false override val password: Boolean = true } @@ -34,7 +35,7 @@ sealed interface GeneratorType2 { data object Username : GeneratorType2 { override val key: String = "USERNAME" override val group: String = GENERATOR_TYPE_GROUP_USERNAME - override val title: TextHolder = TextHolder.Res(Res.strings.generator_username_type) + override val title: TextHolder = TextHolder.Res(Res.string.generator_username_type) override val username: Boolean = true override val password: Boolean = false } @@ -42,7 +43,7 @@ sealed interface GeneratorType2 { data object EmailCatchAll : GeneratorType2 { override val key: String = "EMAIL_CATCH_ALL" override val group: String = GENERATOR_TYPE_GROUP_USERNAME - override val title: TextHolder = TextHolder.Res(Res.strings.generator_email_catch_all_type) + override val title: TextHolder = TextHolder.Res(Res.string.generator_email_catch_all_type) override val username: Boolean = true override val password: Boolean = false } @@ -51,7 +52,7 @@ sealed interface GeneratorType2 { override val key: String = "EMAIL_PLUS_ADDRESSING" override val group: String = GENERATOR_TYPE_GROUP_USERNAME override val title: TextHolder = - TextHolder.Res(Res.strings.generator_email_plus_addressing_type) + TextHolder.Res(Res.string.generator_email_plus_addressing_type) override val username: Boolean = true override val password: Boolean = false } @@ -60,7 +61,7 @@ sealed interface GeneratorType2 { override val key: String = "EMAIL_SUBDOMAIN_ADDRESSING" override val group: String = GENERATOR_TYPE_GROUP_USERNAME override val title: TextHolder = - TextHolder.Res(Res.strings.generator_email_subdomain_addressing_type) + TextHolder.Res(Res.string.generator_email_subdomain_addressing_type) override val username: Boolean = true override val password: Boolean = false } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListRoute.kt index ecdd87b8..7a26270a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListRoute.kt @@ -3,10 +3,12 @@ package com.artemchep.keyguard.feature.generator.emailrelay import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ForwardToInbox import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.iconSmall @@ -25,7 +27,7 @@ object EmailRelayListRoute : Route { navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.ForwardToInbox), - title = translator.translate(Res.strings.emailrelay_list_header_title), + title = Res.string.emailrelay_list_header_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListScreen.kt index c14a9493..07fd87ec 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListScreen.kt @@ -38,6 +38,7 @@ import com.artemchep.keyguard.feature.ErrorView import com.artemchep.keyguard.feature.home.vault.component.rememberSecretAccentColor import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -56,7 +57,7 @@ import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent import com.artemchep.keyguard.ui.util.DividerColor -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.withIndex @@ -120,7 +121,7 @@ fun EmailRelayListScreen( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.emailrelay_list_header_title)) + Text(stringResource(Res.string.emailrelay_list_header_title)) }, navigationIcon = { NavigationIcon() @@ -180,7 +181,7 @@ fun EmailRelayListScreen( }, text = { Text( - text = stringResource(Res.strings.add_integration), + text = stringResource(Res.string.add_integration), ) }, ) @@ -243,7 +244,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.emailrelay_empty_label), + text = stringResource(Res.string.emailrelay_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListStateProducer.kt index 27e521b7..5d8df3d3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/emailrelay/EmailRelayListStateProducer.kt @@ -25,11 +25,15 @@ import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogInten import com.artemchep.keyguard.feature.crashlytics.crashlyticsAttempt import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -81,7 +85,7 @@ fun produceEmailRelayListState( ) { val selectionHandle = selectionHandle("selection") - fun onEdit(model: EmailRelay, entity: DGeneratorEmailRelay?) { + suspend fun onEdit(model: EmailRelay, entity: DGeneratorEmailRelay?) { val keyName = "name" val items2 = model @@ -105,7 +109,7 @@ fun produceEmailRelayListState( key = keyName, value = entity?.name ?: model.name, - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), ) out += it out @@ -122,7 +126,7 @@ fun produceEmailRelayListState( }, ), title = model.name, - subtitle = translate(Res.strings.emailrelay_integration_title), + subtitle = translate(Res.string.emailrelay_integration_title), items = items2, docUrl = model.docUrl, ), @@ -156,9 +160,9 @@ fun produceEmailRelayListState( navigate(intent) } - fun onNew(model: EmailRelay) = onEdit(model, null) + suspend fun onNew(model: EmailRelay) = onEdit(model, null) - fun onDuplicate(entity: DGeneratorEmailRelay) { + suspend fun onDuplicate(entity: DGeneratorEmailRelay) { val createdAt = Clock.System.now() val model = entity.copy( id = null, @@ -168,13 +172,13 @@ fun produceEmailRelayListState( .launchIn(appScope) } - fun onDeleteByItems( + suspend fun onDeleteByItems( items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.emailrelay_delete_many_confirmation_title) + translate(Res.string.emailrelay_delete_many_confirmation_title) } else { - translate(Res.strings.emailrelay_delete_one_confirmation_title) + translate(Res.string.emailrelay_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.name } @@ -197,12 +201,13 @@ fun produceEmailRelayListState( val key = emailRelay.type FlatItemAction( id = key, - title = emailRelay.name, - onClick = ::onNew - .partially1(emailRelay), + title = TextHolder.Value(emailRelay.name), + onClick = onClick { + onNew(emailRelay) + }, ) } - .sortedWith(StringComparatorIgnoreCase { it.title }) + .sortedWith(StringComparatorIgnoreCase { it.let { it.title as TextHolder.Value }.data }) .toImmutableList() val itemsRawFlow = getEmailRelays() @@ -240,9 +245,10 @@ fun produceEmailRelayListState( section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.delete), - onClick = ::onDeleteByItems - .partially1(selectedItems), + title = Res.string.delete.wrap(), + onClick = onClick { + onDeleteByItems(selectedItems) + }, ) } } @@ -273,23 +279,28 @@ fun produceEmailRelayListState( if (relay != null) { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = ::onEdit - .partially1(relay) - .partially1(it), + title = Res.string.edit.wrap(), + onClick = onClick { + onEdit( + model = relay, + entity = it, + ) + }, ) } this += FlatItemAction( icon = Icons.Outlined.CopyAll, - title = translate(Res.strings.duplicate), - onClick = ::onDuplicate - .partially1(it), + title = Res.string.duplicate.wrap(), + onClick = onClick { + onDuplicate(it) + }, ) this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = ::onDeleteByItems - .partially1(listOf(it)), + title = Res.string.delete.wrap(), + onClick = onClick { + onDeleteByItems(listOf(it)) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryScreen.kt index be0a78f5..b7247e2c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryScreen.kt @@ -33,6 +33,7 @@ import com.artemchep.keyguard.feature.EmptyView import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultSelection import com.artemchep.keyguard.ui.ExpandedIfNotEmptyForRow import com.artemchep.keyguard.ui.FlatDropdown @@ -45,7 +46,7 @@ import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun GeneratorHistoryScreen() { @@ -73,7 +74,7 @@ private fun GeneratorPaneMaster( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.generatorhistory_header_title)) + Text(stringResource(Res.string.generatorhistory_header_title)) }, navigationIcon = { NavigationIcon() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryStateProducer.kt index 1c391df0..566be4b8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/history/GeneratorHistoryStateProducer.kt @@ -20,10 +20,14 @@ import com.artemchep.keyguard.feature.auth.common.util.REGEX_EMAIL import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent import com.artemchep.keyguard.feature.decorator.ItemDecoratorDate import com.artemchep.keyguard.feature.largetype.LargeTypeRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.passwordleak.PasswordLeakRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -102,13 +106,13 @@ fun produceGeneratorHistoryState( .onEach { ids -> selectionHandle.setSelection(ids) } .launchIn(screenScope) - fun onDeleteByItems( + suspend fun onDeleteByItems( items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.generatorhistory_delete_many_confirmation_title) + translate(Res.string.generatorhistory_delete_many_confirmation_title) } else { - translate(Res.strings.generatorhistory_delete_one_confirmation_title) + translate(Res.string.generatorhistory_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.value } @@ -126,11 +130,11 @@ fun produceGeneratorHistoryState( navigate(intent) } - fun onDeleteAll() { + suspend fun onDeleteAll() { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.Delete), - title = translate(Res.strings.generatorhistory_clear_history_confirmation_title), - message = translate(Res.strings.generatorhistory_clear_history_confirmation_text), + title = translate(Res.string.generatorhistory_clear_history_confirmation_title), + message = translate(Res.string.generatorhistory_clear_history_confirmation_text), ) { removeGeneratorHistory() .launchIn(appScope) @@ -155,9 +159,10 @@ fun produceGeneratorHistoryState( section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.remove_from_history), - onClick = ::onDeleteByItems - .partially1(selectedItems), + title = Res.string.remove_from_history.wrap(), + onClick = onClick { + onDeleteByItems(selectedItems) + }, ) } } @@ -203,16 +208,20 @@ fun produceGeneratorHistoryState( section { val (copyTitle, copyType) = when (type) { GeneratorHistoryItem.Value.Type.PASSWORD -> - translate(Res.strings.copy_password) to CopyText.Type.PASSWORD + translate(Res.string.copy_password) to CopyText.Type.PASSWORD + GeneratorHistoryItem.Value.Type.EMAIL, - GeneratorHistoryItem.Value.Type.EMAIL_RELAY -> - translate(Res.strings.copy_email) to CopyText.Type.EMAIL + GeneratorHistoryItem.Value.Type.EMAIL_RELAY, + -> + translate(Res.string.copy_email) to CopyText.Type.EMAIL + GeneratorHistoryItem.Value.Type.USERNAME -> - translate(Res.strings.copy_username) to CopyText.Type.USERNAME - null -> translate(Res.strings.copy_value) to CopyText.Type.VALUE + translate(Res.string.copy_username) to CopyText.Type.USERNAME + + null -> translate(Res.string.copy_value) to CopyText.Type.VALUE } this += copyFactory.FlatItemAction( - title = copyTitle, + title = TextHolder.Value(copyTitle), value = item.value, hidden = item.isPassword, type = copyType, @@ -222,9 +231,10 @@ fun produceGeneratorHistoryState( ) this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.remove_from_history), - onClick = ::onDeleteByItems - .partially1(items), + title = Res.string.remove_from_history.wrap(), + onClick = onClick { + onDeleteByItems(items) + }, ) } section { @@ -312,15 +322,15 @@ fun produceGeneratorHistoryState( ) }, ) - sequence { - items.forEach { item -> - val section = decorator.getOrNull(item) - if (section != null) { - yield(section) - } - yield(item) + val out = mutableListOf() + items.forEach { item -> + val section = decorator.getOrNull(item) + if (section != null) { + out += section } - }.toPersistentList() + out += item + } + out.toPersistentList() } val optionsFlow = itemsRawFlow .map { items -> @@ -333,8 +343,10 @@ fun produceGeneratorHistoryState( } else { val action = FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.generatorhistory_clear_history_title), - onClick = ::onDeleteAll, + title = Res.string.generatorhistory_clear_history_title.wrap(), + onClick = onClick { + onDeleteAll() + }, ) persistentListOf(action) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/WordlistsRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/WordlistsRoute.kt index a613945b..6b3f7cbe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/WordlistsRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/WordlistsRoute.kt @@ -2,10 +2,12 @@ package com.artemchep.keyguard.feature.generator.wordlist import androidx.compose.material.icons.Icons import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardWordlist @@ -27,7 +29,7 @@ object WordlistsRoute : Route { navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.KeyguardWordlist), - title = translator.translate(Res.strings.wordlist_list_header_title), + title = Res.string.wordlist_list_header_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListScreen.kt index 978bba29..7242cfd5 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListScreen.kt @@ -54,6 +54,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.navigationNextEntryOrNull import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -69,7 +70,7 @@ import com.artemchep.keyguard.ui.icons.IconBox import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.withIndex @@ -125,7 +126,7 @@ fun WordlistListScreen( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.wordlist_list_header_title)) + Text(stringResource(Res.string.wordlist_list_header_title)) }, navigationIcon = { NavigationIcon() @@ -204,7 +205,7 @@ fun WordlistListScreen( }, text = { Text( - text = stringResource(Res.strings.add), + text = stringResource(Res.string.add), ) }, ) @@ -267,7 +268,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.wordlist_empty_label), + text = stringResource(Res.string.wordlist_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListStateProducer.kt index 5a966dd5..887c786b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/list/WordlistListStateProducer.kt @@ -22,9 +22,12 @@ import com.artemchep.keyguard.feature.generator.wordlist.util.WordlistUtil import com.artemchep.keyguard.feature.generator.wordlist.view.WordlistViewRoute import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -127,22 +130,26 @@ fun produceWordlistListState( val selectedItem = selectedItems.first() this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = WordlistUtil::onRename - .partially1(this@produceScreenState) - .partially1(editWordlist) - .partially1(selectedItem), + title = Res.string.edit.wrap(), + onClick = onClick { + WordlistUtil.onRename( + editWordlist = editWordlist, + entity = selectedItem, + ) + }, ) } } section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.delete), - onClick = WordlistUtil::onDeleteByItems - .partially1(this@produceScreenState) - .partially1(removeWordlistById) - .partially1(selectedItems), + title = Res.string.delete.wrap(), + onClick = onClick { + WordlistUtil.onDeleteByItems( + removeWordlistById = removeWordlistById, + items = selectedItems, + ) + }, ) } } @@ -236,17 +243,21 @@ fun produceWordlistListState( section { this += FlatItemAction( leading = icon(Icons.Outlined.AttachFile), - title = translate(Res.strings.wordlist_add_wordlist_via_file_title), - onClick = WordlistUtil::onNewFromFile - .partially1(this@produceScreenState) - .partially1(addWordlist), + title = Res.string.wordlist_add_wordlist_via_file_title.wrap(), + onClick = onClick { + WordlistUtil.onNewFromFile( + addWordlist = addWordlist, + ) + }, ) this += FlatItemAction( leading = icon(Icons.Outlined.KeyguardWebsite), - title = translate(Res.strings.wordlist_add_wordlist_via_url_title), - onClick = WordlistUtil::onNewFromUrl - .partially1(this@produceScreenState) - .partially1(addWordlist), + title = Res.string.wordlist_add_wordlist_via_url_title.wrap(), + onClick = onClick { + WordlistUtil.onNewFromUrl( + addWordlist = addWordlist, + ) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/util/WordlistUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/util/WordlistUtil.kt index c1a04566..77b9f287 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/util/WordlistUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/util/WordlistUtil.kt @@ -18,13 +18,14 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.KeyguardCipherFilter import com.artemchep.keyguard.ui.icons.KeyguardWordlist import com.artemchep.keyguard.ui.icons.icon object WordlistUtil { context(RememberStateFlowScope) - fun onRename( + suspend fun onRename( editWordlist: EditWordlist, entity: DGeneratorWordlist, ) { @@ -32,7 +33,7 @@ object WordlistUtil { val nameItem = ConfirmationRoute.Args.Item.StringItem( key = nameKey, value = entity.name, - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), type = ConfirmationRoute.Args.Item.StringItem.Type.Text, canBeEmpty = false, ) @@ -47,7 +48,7 @@ object WordlistUtil { main = Icons.Outlined.KeyguardCipherFilter, secondary = Icons.Outlined.Edit, ), - title = translate(Res.strings.wordlist_edit_wordlist_title), + title = translate(Res.string.wordlist_edit_wordlist_title), items = items, docUrl = null, ), @@ -70,14 +71,14 @@ object WordlistUtil { } context(RememberStateFlowScope) - fun onNewFromFile( + suspend fun onNewFromFile( addWordlist: AddWordlist, ) { val nameKey = "name" val nameItem = ConfirmationRoute.Args.Item.StringItem( key = nameKey, value = "", - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), type = ConfirmationRoute.Args.Item.StringItem.Type.Text, canBeEmpty = false, ) @@ -86,7 +87,7 @@ object WordlistUtil { val fileItem = ConfirmationRoute.Args.Item.FileItem( key = fileKey, value = null, - title = translate(Res.strings.wordlist), + title = translate(Res.string.wordlist), ) val items = listOfNotNull( @@ -100,7 +101,7 @@ object WordlistUtil { main = Icons.Outlined.KeyguardWordlist, secondary = Icons.Outlined.Add, ), - title = translate(Res.strings.wordlist_add_wordlist_title), + title = translate(Res.string.wordlist_add_wordlist_title), items = items, docUrl = null, ), @@ -128,14 +129,14 @@ object WordlistUtil { } context(RememberStateFlowScope) - fun onNewFromUrl( + suspend fun onNewFromUrl( addWordlist: AddWordlist, ) { val nameKey = "name" val nameItem = ConfirmationRoute.Args.Item.StringItem( key = nameKey, value = "", - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), type = ConfirmationRoute.Args.Item.StringItem.Type.Text, canBeEmpty = false, ) @@ -144,7 +145,7 @@ object WordlistUtil { val urlItem = ConfirmationRoute.Args.Item.StringItem( key = urlKey, value = "", - title = translate(Res.strings.url), + title = translate(Res.string.url), type = ConfirmationRoute.Args.Item.StringItem.Type.Command, canBeEmpty = false, ) @@ -160,7 +161,7 @@ object WordlistUtil { main = Icons.Outlined.KeyguardWordlist, secondary = Icons.Outlined.Add, ), - title = translate(Res.strings.wordlist_add_wordlist_title), + title = translate(Res.string.wordlist_add_wordlist_title), items = items, docUrl = null, ), @@ -188,14 +189,14 @@ object WordlistUtil { } context(RememberStateFlowScope) - fun onDeleteByItems( + suspend fun onDeleteByItems( removeWordlistById: RemoveWordlistById, items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.wordlist_delete_many_confirmation_title) + translate(Res.string.wordlist_delete_many_confirmation_title) } else { - translate(Res.strings.wordlist_delete_one_confirmation_title) + translate(Res.string.wordlist_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.name } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewScreen.kt index 64cd8be0..1918a8e7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewScreen.kt @@ -53,6 +53,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.tfa.directory.TwoFaServiceListState import com.artemchep.keyguard.feature.tfa.directory.produceTwoFaServiceListState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultProgressBar @@ -72,7 +73,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -193,7 +194,7 @@ fun WordlistViewScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.wordlist_word_search_placeholder), + placeholder = stringResource(Res.string.wordlist_word_search_placeholder), searchIcon = searchIcon, count = count, leading = {}, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewStateProducer.kt index 21de5a53..a555cecb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/generator/wordlist/view/WordlistViewStateProducer.kt @@ -14,12 +14,15 @@ import com.artemchep.keyguard.common.usecase.RemoveWordlistById import com.artemchep.keyguard.feature.crashlytics.crashlyticsAttempt import com.artemchep.keyguard.feature.generator.wordlist.util.WordlistUtil import com.artemchep.keyguard.feature.home.vault.search.IndexedText +import com.artemchep.keyguard.feature.localization.wrap +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.search.search.IndexedModel import com.artemchep.keyguard.feature.search.search.mapSearch import com.artemchep.keyguard.feature.search.search.searchFilter import com.artemchep.keyguard.feature.search.search.searchQueryHandle import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.autoclose.launchAutoPopSelfHandler import com.artemchep.keyguard.ui.buildContextItems @@ -78,22 +81,26 @@ fun produceWordlistViewState( section { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = WordlistUtil::onRename - .partially1(this@produceScreenState) - .partially1(editWordlist) - .partially1(wordlist), + title = Res.string.edit.wrap(), + onClick = onClick { + WordlistUtil.onRename( + editWordlist = editWordlist, + entity = wordlist, + ) + }, ) } section { val wordlistAsItems = listOf(wordlist) this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = WordlistUtil::onDeleteByItems - .partially1(this@produceScreenState) - .partially1(removeWordlistById) - .partially1(wordlistAsItems), + title = Res.string.delete.wrap(), + onClick = onClick { + WordlistUtil.onDeleteByItems( + removeWordlistById = removeWordlistById, + items = wordlistAsItems, + ) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/HomeScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/HomeScreen.kt index 7b68bb5d..cc4b3c6c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/HomeScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/HomeScreen.kt @@ -115,6 +115,7 @@ import com.artemchep.keyguard.platform.leNavigationBars import com.artemchep.keyguard.platform.leStatusBars import com.artemchep.keyguard.platform.leSystemBars import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.icons.ChevronIcon @@ -126,7 +127,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.info import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.theme.ok -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf @@ -178,31 +179,31 @@ fun HomeScreen( route = vaultRoute, icon = Icons.Outlined.Home, iconSelected = Icons.Filled.Home, - label = TextHolder.Res(Res.strings.home_vault_label), + label = TextHolder.Res(Res.string.home_vault_label), ), Rail( route = sendsRoute, icon = Icons.Outlined.Send, iconSelected = Icons.Filled.Send, - label = TextHolder.Res(Res.strings.home_send_label), + label = TextHolder.Res(Res.string.home_send_label), ), Rail( route = generatorRoute, icon = Icons.Outlined.Password, iconSelected = Icons.Filled.Password, - label = TextHolder.Res(Res.strings.home_generator_label), + label = TextHolder.Res(Res.string.home_generator_label), ), Rail( route = watchtowerRoute, icon = Icons.Outlined.Security, iconSelected = Icons.Filled.Security, - label = TextHolder.Res(Res.strings.home_watchtower_label), + label = TextHolder.Res(Res.string.home_watchtower_label), ), Rail( route = SettingsRoute, icon = Icons.Outlined.Settings, iconSelected = Icons.Filled.Settings, - label = TextHolder.Res(Res.strings.home_settings_label), + label = TextHolder.Res(Res.string.home_settings_label), ), ) } @@ -465,7 +466,7 @@ private fun BannerStatusBadge( error != null -> { BannerStatusBadgeContentModel( count = error.count, - title = TextHolder.Res(Res.strings.syncstatus_status_failed), + title = TextHolder.Res(Res.string.syncstatus_status_failed), error = true, onClick = { navigateSyncStatus(updatedNavController) @@ -645,7 +646,7 @@ private fun RailStatusBadge( badge = status.error.count .takeIf { it > 0 } ?.toString(), - text = stringResource(Res.strings.syncstatus_status_failed), + text = stringResource(Res.string.syncstatus_status_failed), ) } @@ -662,7 +663,7 @@ private fun RailStatusBadge( badge = status.pending.count .takeIf { it > 0 } ?.toString(), - text = stringResource(Res.strings.syncstatus_status_syncing), + text = stringResource(Res.string.syncstatus_status_syncing), ) } @@ -688,7 +689,7 @@ private fun RailStatusBadge( contentDescription = null, ) }, - text = stringResource(Res.strings.syncstatus_status_up_to_date), + text = stringResource(Res.string.syncstatus_status_up_to_date), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingListScreen.kt index 7f31157e..76c8e84a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingListScreen.kt @@ -63,6 +63,7 @@ import com.artemchep.keyguard.platform.util.hasAutofill import com.artemchep.keyguard.platform.util.hasSubscription import com.artemchep.keyguard.platform.util.isRelease import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmptyForRow import com.artemchep.keyguard.ui.ScaffoldLazyColumn import com.artemchep.keyguard.ui.icons.IconBox @@ -70,7 +71,7 @@ import com.artemchep.keyguard.ui.icons.KeyguardPremium import com.artemchep.keyguard.ui.pulltosearch.PullToSearch import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance sealed interface SettingsItem2 { @@ -96,8 +97,8 @@ data class SettingsSectionItem( private val items = listOfNotNull( SettingsItem( id = "accounts", - title = TextHolder.Res(Res.strings.pref_item_accounts_title), - text = TextHolder.Res(Res.strings.pref_item_accounts_text), + title = TextHolder.Res(Res.string.pref_item_accounts_title), + text = TextHolder.Res(Res.string.pref_item_accounts_text), icon = Icons.Outlined.AccountBox, trailing = { val getAccountsHasError: GetAccountsHasError by rememberInstance() @@ -125,8 +126,8 @@ private val items = listOfNotNull( ), SettingsItem( id = "subscription", - title = TextHolder.Res(Res.strings.pref_item_subscription_title), - text = TextHolder.Res(Res.strings.pref_item_subscription_text), + title = TextHolder.Res(Res.string.pref_item_subscription_title), + text = TextHolder.Res(Res.string.pref_item_subscription_text), leading = { val getPurchased by rememberInstance() val isPurchased by remember(getPurchased) { @@ -167,50 +168,50 @@ private val items = listOfNotNull( // ), SettingsItem( id = "autofill", - title = TextHolder.Res(Res.strings.pref_item_autofill_title), - text = TextHolder.Res(Res.strings.pref_item_autofill_text), + title = TextHolder.Res(Res.string.pref_item_autofill_title), + text = TextHolder.Res(Res.string.pref_item_autofill_text), icon = Icons.Outlined.AutoAwesome, route = AutofillSettingsRoute, ).takeIf { CurrentPlatform.hasAutofill() }, SettingsItem( id = "security", - title = TextHolder.Res(Res.strings.pref_item_security_title), - text = TextHolder.Res(Res.strings.pref_item_security_text), + title = TextHolder.Res(Res.string.pref_item_security_title), + text = TextHolder.Res(Res.string.pref_item_security_text), icon = Icons.Outlined.Lock, route = SecuritySettingsRoute, ), SettingsItem( id = "watchtower", - title = TextHolder.Res(Res.strings.pref_item_watchtower_title), - text = TextHolder.Res(Res.strings.pref_item_watchtower_text), + title = TextHolder.Res(Res.string.pref_item_watchtower_title), + text = TextHolder.Res(Res.string.pref_item_watchtower_text), icon = Icons.Outlined.Security, route = WatchtowerSettingsRoute, ), SettingsItem( id = "notifications", - title = TextHolder.Res(Res.strings.pref_item_notifications_title), - text = TextHolder.Res(Res.strings.pref_item_notifications_text), + title = TextHolder.Res(Res.string.pref_item_notifications_title), + text = TextHolder.Res(Res.string.pref_item_notifications_text), icon = Icons.Outlined.Notifications, route = NotificationsSettingsRoute, ).takeIf { !isRelease }, SettingsItem( id = "display", - title = TextHolder.Res(Res.strings.pref_item_appearance_title), - text = TextHolder.Res(Res.strings.pref_item_appearance_text), + title = TextHolder.Res(Res.string.pref_item_appearance_title), + text = TextHolder.Res(Res.string.pref_item_appearance_text), icon = Icons.Outlined.ColorLens, route = UiSettingsRoute, ), SettingsItem( id = "debug", - title = TextHolder.Res(Res.strings.pref_item_dev_title), - text = TextHolder.Res(Res.strings.pref_item_dev_text), + title = TextHolder.Res(Res.string.pref_item_dev_title), + text = TextHolder.Res(Res.string.pref_item_dev_text), icon = Icons.Outlined.Code, route = DebugSettingsRoute, ).takeIf { !isRelease }, SettingsItem( id = "about", - title = TextHolder.Res(Res.strings.pref_item_other_title), - text = TextHolder.Res(Res.strings.pref_item_other_text), + title = TextHolder.Res(Res.string.pref_item_other_title), + text = TextHolder.Res(Res.string.pref_item_other_text), icon = Icons.Outlined.Info, route = OtherSettingsRoute, ), @@ -252,7 +253,7 @@ private fun SettingListScreenContent( LargeToolbar( title = { Text( - text = stringResource(Res.strings.settings_main_header_title), + text = stringResource(Res.string.settings_main_header_title), ) }, navigationIcon = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneContent.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneContent.kt index 887d67b8..1238b1d6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneContent.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneContent.kt @@ -320,7 +320,7 @@ fun SettingPaneContent( val shouldAddDivider = // Do not add a divider on top of the // blank list. - componentFlows.isNotEmpty() || !item.title.isNullOrBlank() + componentFlows.isNotEmpty() || item.title != null if (shouldAddDivider) { val divider = create( item = SettingPaneItem.Item(componentDivider), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneItem.kt index a875cbf1..3ec81c3b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/SettingPaneItem.kt @@ -1,13 +1,14 @@ package com.artemchep.keyguard.feature.home.settings import com.artemchep.keyguard.feature.home.settings.component.SettingSectionArgs +import com.artemchep.keyguard.feature.localization.TextHolder sealed interface SettingPaneItem { val key: String data class Group( override val key: String, - val title: String? = null, + val title: TextHolder? = null, val list: List, ) : SettingPaneItem { fun toSectionArgs() = SettingSectionArgs( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListScreen.kt index 1d76607a..bba7b88e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListScreen.kt @@ -25,6 +25,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FabState @@ -34,7 +35,7 @@ import com.artemchep.keyguard.ui.icons.SyncIcon import com.artemchep.keyguard.ui.selection.SelectionBar import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AccountListScreen() { @@ -72,7 +73,7 @@ fun AccountListScreenContent( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.account_main_header_title)) + Text(stringResource(Res.string.account_main_header_title)) }, navigationIcon = { NavigationIcon() @@ -98,7 +99,7 @@ fun AccountListScreenContent( Icon(Icons.Outlined.Add, null) }, text = { - Text(stringResource(Res.strings.account_main_add_account_title)) + Text(stringResource(Res.string.account_main_add_account_title)) }, ) }, @@ -108,7 +109,7 @@ fun AccountListScreenContent( ) { selection -> SelectionBar( title = { - val text = stringResource(Res.strings.selection_n_selected, selection.count) + val text = stringResource(Res.string.selection_n_selected, selection.count) Text(text) }, trailing = { @@ -152,7 +153,7 @@ fun AccountListScreenContent( }, text = { Text( - text = stringResource(Res.strings.accounts_empty_label), + text = stringResource(Res.string.accounts_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListViewModel.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListViewModel.kt index 2f3577f3..8bd5cec8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListViewModel.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/accounts/AccountListViewModel.kt @@ -28,9 +28,12 @@ import com.artemchep.keyguard.feature.home.settings.accounts.model.AccountItem import com.artemchep.keyguard.feature.home.vault.VaultRoute import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.SyncSupervisorImpl import com.artemchep.keyguard.ui.buildContextItems @@ -135,13 +138,13 @@ fun accountListScreenState( queueSyncById(accountId).launchIn(windowCoroutineScope) } - fun onDelete( + suspend fun onDelete( accountIds: Set, ) { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.Logout), - title = translate(Res.strings.account_log_out_confirmation_title), - message = translate(Res.strings.account_log_out_confirmation_text), + title = translate(Res.string.account_log_out_confirmation_title), + message = translate(Res.string.account_log_out_confirmation_text), ) { removeAccountById(accountIds) .launchIn(windowCoroutineScope) @@ -181,8 +184,8 @@ fun accountListScreenState( // to these folders. this += FlatItemAction( leading = icon(Icons.Outlined.KeyguardCipher), - title = translate(Res.strings.items), - onClick = { + title = Res.string.items.wrap(), + onClick = onClick { val accounts = selectedAccounts.values val route = VaultRoute.by(accounts = accounts) val intent = NavigationIntent.NavigateToRoute(route) @@ -193,9 +196,10 @@ fun accountListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Logout, - title = translate(Res.strings.account_action_log_out_title), - onClick = ::onDelete - .partially1(f), + title = Res.string.account_action_log_out_title.wrap(), + onClick = onClick { + onDelete(f) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/autofill/AutofillSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/autofill/AutofillSettingsScreen.kt index 853601ea..92ae1fef 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/autofill/AutofillSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/autofill/AutofillSettingsScreen.kt @@ -1,32 +1,34 @@ package com.artemchep.keyguard.feature.home.settings.autofill import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun AutofillSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_autofill_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Group( key = "credential", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.CREDENTIAL_PROVIDER), ), ), SettingPaneItem.Group( key = "autofill", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.AUTOFILL), ), ), SettingPaneItem.Group( key = "general", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.AUTOFILL_INLINE_SUGGESTIONS), SettingPaneItem.Item(Setting.AUTOFILL_MANUAL_SELECTION), SettingPaneItem.Item(Setting.AUTOFILL_RESPECT_AUTOFILL_OFF), @@ -34,17 +36,21 @@ fun AutofillSettingsScreen() { ), SettingPaneItem.Group( key = "totp", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.AUTOFILL_COPY_TOTP), ), ), SettingPaneItem.Group( key = "save", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.AUTOFILL_SAVE_REQUEST), SettingPaneItem.Item(Setting.AUTOFILL_SAVE_URI), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_autofill_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutApp.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutApp.kt index 4118dec9..713b7419 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutApp.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutApp.kt @@ -3,7 +3,8 @@ package com.artemchep.keyguard.feature.home.settings.component import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.usecase.GetAppVersion import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -39,7 +40,7 @@ private fun SettingAboutApp( appVersion: String, ) { SettingListItem( - title = stringResource(Res.strings.pref_item_app_version_title), + title = stringResource(Res.string.pref_item_app_version_title), text = appVersion, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildDate.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildDate.kt index 4b719077..182cf0e3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildDate.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildDate.kt @@ -3,7 +3,8 @@ package com.artemchep.keyguard.feature.home.settings.component import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.usecase.GetAppBuildDate import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -41,7 +42,7 @@ private fun SettingAboutAppBuildDate( buildDate: String, ) { SettingListItem( - title = stringResource(Res.strings.pref_item_app_build_date_title), + title = stringResource(Res.string.pref_item_app_build_date_title), text = buildDate, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildRef.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildRef.kt index f882ae17..dafe8cff 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildRef.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppBuildRef.kt @@ -8,9 +8,10 @@ import com.artemchep.keyguard.common.usecase.GetAppBuildRef import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -55,7 +56,7 @@ private fun SettingAboutAppBuildRef( FlatItem( title = { Text( - text = stringResource(Res.strings.pref_item_app_build_ref_title), + text = stringResource(Res.string.pref_item_app_build_ref_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppChangelog.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppChangelog.kt index 054ed59a..5175cc57 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppChangelog.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutAppChangelog.kt @@ -9,9 +9,10 @@ import com.artemchep.keyguard.common.usecase.GetVersionLog import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -60,7 +61,7 @@ private fun SettingAboutAppChangelog( FlatItem( title = { Text( - text = stringResource(Res.strings.pref_item_app_changelog_title), + text = stringResource(Res.string.pref_item_app_changelog_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTeam.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTeam.kt index 99582b24..443d4a7e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTeam.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTeam.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.team.AboutTeamRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -56,7 +57,7 @@ private fun SettingAboutTeam( }, title = { Text( - text = stringResource(Res.strings.pref_item_app_team_title), + text = stringResource(Res.string.pref_item_app_team_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTelegram.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTelegram.kt index 903e8934..6136249e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTelegram.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAboutTelegram.kt @@ -10,11 +10,12 @@ import androidx.compose.runtime.rememberUpdatedState import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardWebsite import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -60,7 +61,7 @@ private fun SettingAboutTelegram( }, title = { Text( - text = stringResource(Res.strings.pref_item_reddit_community_title), + text = stringResource(Res.string.pref_item_reddit_community_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingApk.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingApk.kt index 8c47e7c6..2b30092a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingApk.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingApk.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.common.usecase.GetPurchased import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -54,7 +55,7 @@ private fun SettingApk() { leading = icon(Icons.Outlined.FileDownload), title = { Text( - text = stringResource(Res.strings.pref_item_download_apk_title), + text = stringResource(Res.string.pref_item_download_apk_title), ) }, trailing = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAppIcons.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAppIcons.kt index 70735304..96db7a13 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAppIcons.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAppIcons.kt @@ -13,11 +13,12 @@ import com.artemchep.keyguard.common.usecase.GetAppIcons import com.artemchep.keyguard.common.usecase.PutAppIcons import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -79,7 +80,7 @@ private fun SettingAppIcons( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_load_app_icons_title), + text = stringResource(Res.string.pref_item_load_app_icons_title), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillCopyTotp.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillCopyTotp.kt index fd010437..90aabb87 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillCopyTotp.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillCopyTotp.kt @@ -11,8 +11,9 @@ import com.artemchep.keyguard.common.usecase.GetAutofillCopyTotp import com.artemchep.keyguard.common.usecase.PutAutofillCopyTotp import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -74,12 +75,12 @@ private fun SettingAutofillCopyTotp( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_auto_copy_otp_title), + text = stringResource(Res.string.pref_item_autofill_auto_copy_otp_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_auto_copy_otp_text), + text = stringResource(Res.string.pref_item_autofill_auto_copy_otp_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillInlineSuggestions.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillInlineSuggestions.kt index 28c9f273..0caaaf77 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillInlineSuggestions.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillInlineSuggestions.kt @@ -11,8 +11,9 @@ import com.artemchep.keyguard.common.usecase.GetAutofillInlineSuggestions import com.artemchep.keyguard.common.usecase.PutAutofillInlineSuggestions import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -71,12 +72,12 @@ private fun SettingAutofillInlineSuggestions( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_inline_suggestions_title), + text = stringResource(Res.string.pref_item_autofill_inline_suggestions_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_inline_suggestions_text), + text = stringResource(Res.string.pref_item_autofill_inline_suggestions_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillManualSelection.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillManualSelection.kt index c23c65f7..9528072c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillManualSelection.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillManualSelection.kt @@ -11,8 +11,9 @@ import com.artemchep.keyguard.common.usecase.GetAutofillManualSelection import com.artemchep.keyguard.common.usecase.PutAutofillManualSelection import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -71,12 +72,12 @@ private fun SettingAutofillManualSelection( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_manual_selection_title), + text = stringResource(Res.string.pref_item_autofill_manual_selection_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_manual_selection_text), + text = stringResource(Res.string.pref_item_autofill_manual_selection_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillRespectAutofillOff.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillRespectAutofillOff.kt index 682750f8..30de2598 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillRespectAutofillOff.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillRespectAutofillOff.kt @@ -17,11 +17,12 @@ import com.artemchep.keyguard.common.usecase.GetAutofillRespectAutofillOff import com.artemchep.keyguard.common.usecase.PutAutofillRespectAutofillOff import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -82,12 +83,12 @@ private fun SettingAutofillRespectAutofillOff( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_autofill_respect_autofill_disabled_title), + text = stringResource(Res.string.pref_item_autofill_respect_autofill_disabled_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_respect_autofill_disabled_text), + text = stringResource(Res.string.pref_item_autofill_respect_autofill_disabled_text), ) Spacer( modifier = Modifier @@ -97,7 +98,7 @@ private fun SettingAutofillRespectAutofillOff( color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), style = MaterialTheme.typography.bodySmall, - text = stringResource(Res.strings.pref_item_autofill_respect_autofill_disabled_note), + text = stringResource(Res.string.pref_item_autofill_respect_autofill_disabled_note), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveRequest.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveRequest.kt index 7825d07a..ecef1075 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveRequest.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveRequest.kt @@ -12,8 +12,9 @@ import com.artemchep.keyguard.common.usecase.GetCanWrite import com.artemchep.keyguard.common.usecase.PutAutofillSaveRequest import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -79,12 +80,12 @@ private fun SettingAutofillSaveRequest( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_save_request_title), + text = stringResource(Res.string.pref_item_autofill_save_request_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_autofill_save_request_text), + text = stringResource(Res.string.pref_item_autofill_save_request_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveUri.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveUri.kt index 8972e9bc..8adee2d5 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveUri.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingAutofillSaveUri.kt @@ -12,8 +12,9 @@ import com.artemchep.keyguard.common.usecase.GetCanWrite import com.artemchep.keyguard.common.usecase.PutAutofillSaveUri import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -79,7 +80,7 @@ private fun SettingAutofillSaveUri( }, title = { Text( - text = stringResource(Res.strings.pref_item_autofill_auto_save_source_title), + text = stringResource(Res.string.pref_item_autofill_auto_save_source_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometrics.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometrics.kt index 4dfbf284..ddeeac38 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometrics.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometrics.kt @@ -24,9 +24,10 @@ import com.artemchep.keyguard.common.util.flow.EventFlow import com.artemchep.keyguard.feature.biometric.BiometricPromptEffect import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest @@ -104,7 +105,7 @@ private fun createSettingComponentFlow( .map { d -> val cipher = d.getCipher() val prompt = BiometricAuthPrompt( - title = TextHolder.Res(Res.strings.pref_item_biometric_unlock_confirm_title), + title = TextHolder.Res(Res.string.pref_item_biometric_unlock_confirm_title), cipher = cipher, requireConfirmation = requireConfirmation, onComplete = { result -> @@ -154,7 +155,7 @@ private fun SettingBiometrics( }, title = { Text( - text = stringResource(Res.strings.pref_item_biometric_unlock_title), + text = stringResource(Res.string.pref_item_biometric_unlock_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometricsRequireConfirmation.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometricsRequireConfirmation.kt index 2409b8f7..5a9f9c1e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometricsRequireConfirmation.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingBiometricsRequireConfirmation.kt @@ -14,8 +14,9 @@ import com.artemchep.keyguard.common.usecase.GetBiometricRequireConfirmation import com.artemchep.keyguard.common.usecase.PutBiometricRequireConfirmation import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest @@ -110,12 +111,12 @@ private fun SettingBiometricsRequireConfirmation( }, title = { Text( - text = stringResource(Res.strings.pref_item_biometric_unlock_require_confirmation_title), + text = stringResource(Res.string.pref_item_biometric_unlock_require_confirmation_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_biometric_unlock_require_confirmation_text), + text = stringResource(Res.string.pref_item_biometric_unlock_require_confirmation_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPasskeys.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPasskeys.kt index 41baa060..1b7698f7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPasskeys.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPasskeys.kt @@ -14,10 +14,11 @@ import com.artemchep.keyguard.common.usecase.GetCheckPasskeys import com.artemchep.keyguard.common.usecase.PutCheckPasskeys import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.poweredby.PoweredByPasskeys import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -69,11 +70,11 @@ private fun SettingCheckPasskeys( }, title = { Text( - text = stringResource(Res.strings.pref_item_check_inactive_passkeys_title), + text = stringResource(Res.string.pref_item_check_inactive_passkeys_title), ) }, text = { - val text = stringResource(Res.strings.watchtower_item_inactive_passkey_text) + val text = stringResource(Res.string.watchtower_item_inactive_passkey_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedPasswords.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedPasswords.kt index b677feda..e5ba1f82 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedPasswords.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedPasswords.kt @@ -15,10 +15,11 @@ import com.artemchep.keyguard.common.usecase.GetCheckPwnedPasswords import com.artemchep.keyguard.common.usecase.PutCheckPwnedPasswords import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.poweredby.PoweredByHaveibeenpwned import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -70,11 +71,11 @@ private fun SettingCheckPwnedPasswords( }, title = { Text( - text = stringResource(Res.strings.pref_item_check_pwned_passwords_title), + text = stringResource(Res.string.pref_item_check_pwned_passwords_title), ) }, text = { - val text = stringResource(Res.strings.watchtower_item_pwned_passwords_text) + val text = stringResource(Res.string.watchtower_item_pwned_passwords_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedServices.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedServices.kt index 24d5e7a8..b8476410 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedServices.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckPwnedServices.kt @@ -14,10 +14,11 @@ import com.artemchep.keyguard.common.usecase.GetCheckPwnedServices import com.artemchep.keyguard.common.usecase.PutCheckPwnedServices import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.poweredby.PoweredByHaveibeenpwned import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -69,11 +70,11 @@ private fun SettingCheckPwnedServices( }, title = { Text( - text = stringResource(Res.strings.pref_item_check_pwned_services_title), + text = stringResource(Res.string.pref_item_check_pwned_services_title), ) }, text = { - val text = stringResource(Res.strings.watchtower_item_vulnerable_accounts_text) + val text = stringResource(Res.string.watchtower_item_vulnerable_accounts_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckTwoFA.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckTwoFA.kt index e56b1be9..f7ee490c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckTwoFA.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCheckTwoFA.kt @@ -14,11 +14,12 @@ import com.artemchep.keyguard.common.usecase.GetCheckTwoFA import com.artemchep.keyguard.common.usecase.PutCheckTwoFA import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.poweredby.PoweredBy2factorauth import com.artemchep.keyguard.ui.poweredby.PoweredByHaveibeenpwned import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -70,11 +71,11 @@ private fun SettingCheckTwoFA( }, title = { Text( - text = stringResource(Res.strings.pref_item_check_inactive_2fa_title), + text = stringResource(Res.string.pref_item_check_inactive_2fa_title), ) }, text = { - val text = stringResource(Res.strings.watchtower_item_inactive_2fa_text) + val text = stringResource(Res.string.watchtower_item_inactive_2fa_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoClear.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoClear.kt index f0149074..700e29b2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoClear.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoClear.kt @@ -11,16 +11,18 @@ import com.artemchep.keyguard.common.usecase.GetClipboardAutoClear import com.artemchep.keyguard.common.usecase.GetClipboardAutoClearVariants import com.artemchep.keyguard.common.usecase.PutClipboardAutoClear import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.format import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -51,7 +53,7 @@ fun settingClipboardAutoClearProvider( .map { duration -> val title = getAutoClearDurationTitle(duration, context) FlatItemAction( - title = title, + title = TextHolder.Value(title), onClick = { putClipboardAutoClear(duration) .launchIn(windowCoroutineScope) @@ -69,14 +71,14 @@ fun settingClipboardAutoClearProvider( } } -private fun getAutoClearDurationTitle(duration: Duration, context: LeContext) = when (duration) { +private suspend fun getAutoClearDurationTitle(duration: Duration, context: LeContext) = when (duration) { Duration.ZERO -> textResource( - Res.strings.pref_item_clipboard_auto_clear_immediately_text, + Res.string.pref_item_clipboard_auto_clear_immediately_text, context, ) Duration.INFINITE -> textResource( - Res.strings.pref_item_clipboard_auto_clear_never_text, + Res.string.pref_item_clipboard_auto_clear_never_text, context, ) @@ -95,7 +97,7 @@ private fun SettingClipboardAutoClear( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_clipboard_auto_clear_title), + text = stringResource(Res.string.pref_item_clipboard_auto_clear_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoRefresh.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoRefresh.kt index be963046..b5e07941 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoRefresh.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingClipboardAutoRefresh.kt @@ -16,10 +16,12 @@ import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefresh import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefreshVariants import com.artemchep.keyguard.common.usecase.PutClipboardAutoRefresh import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent @@ -28,7 +30,7 @@ import com.artemchep.keyguard.ui.format import com.artemchep.keyguard.ui.icons.KeyguardTwoFa import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -59,7 +61,7 @@ fun settingClipboardAutoRefreshProvider( .map { duration -> val title = getAutoRefreshDurationTitle(duration, context) FlatItemAction( - title = title, + title = TextHolder.Value(title), onClick = { putClipboardAutoRefresh(duration) .launchIn(windowCoroutineScope) @@ -77,9 +79,9 @@ fun settingClipboardAutoRefreshProvider( } } -private fun getAutoRefreshDurationTitle(duration: Duration, context: LeContext) = when (duration) { +private suspend fun getAutoRefreshDurationTitle(duration: Duration, context: LeContext) = when (duration) { Duration.ZERO -> textResource( - Res.strings.pref_item_clipboard_auto_refresh_otp_duration_never_text, + Res.string.pref_item_clipboard_auto_refresh_otp_duration_never_text, context, ) @@ -97,7 +99,7 @@ private fun SettingClipboardAutoRefresh( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_clipboard_auto_refresh_otp_duration_title), + text = stringResource(Res.string.pref_item_clipboard_auto_refresh_otp_duration_title), ) }, text = { @@ -110,7 +112,7 @@ private fun SettingClipboardAutoRefresh( color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), style = MaterialTheme.typography.bodySmall, - text = stringResource(Res.strings.pref_item_clipboard_auto_refresh_otp_duration_note), + text = stringResource(Res.string.pref_item_clipboard_auto_refresh_otp_duration_note), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCloseToTray.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCloseToTray.kt index a27184ba..2efc59b8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCloseToTray.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCloseToTray.kt @@ -16,9 +16,10 @@ import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -83,7 +84,7 @@ private fun SettingCloseToTray( }, title = { Text( - text = stringResource(Res.strings.pref_item_close_to_tray_title), + text = stringResource(Res.string.pref_item_close_to_tray_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorAccent.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorAccent.kt index e6476733..f5fc9295 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorAccent.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorAccent.kt @@ -19,15 +19,17 @@ import com.artemchep.keyguard.common.usecase.GetColors import com.artemchep.keyguard.common.usecase.GetColorsVariants import com.artemchep.keyguard.common.usecase.PutColors import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.composable import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -57,7 +59,7 @@ fun settingColorAccentProvider( .map { colorsVariant -> val actionTitle = getAppColorsTitle(colorsVariant, context) FlatItemAction( - title = actionTitle, + title = TextHolder.Value(actionTitle), onClick = { putColors(colorsVariant) .launchIn(windowCoroutineScope) @@ -95,8 +97,8 @@ fun settingColorAccentProvider( } } -private fun getAppColorsTitle(appColors: AppColors?, context: LeContext) = when (appColors) { - null -> textResource(Res.strings.follow_system_settings, context) +private suspend fun getAppColorsTitle(appColors: AppColors?, context: LeContext) = when (appColors) { + null -> textResource(Res.string.follow_system_settings, context) else -> appColors.title } @@ -111,7 +113,7 @@ private fun SettingFont( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_color_accent_title), + text = stringResource(Res.string.pref_item_color_accent_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorScheme.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorScheme.kt index 04fd4b22..a8204a64 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorScheme.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingColorScheme.kt @@ -11,14 +11,16 @@ import com.artemchep.keyguard.common.usecase.GetTheme import com.artemchep.keyguard.common.usecase.GetThemeVariants import com.artemchep.keyguard.common.usecase.PutTheme import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -48,7 +50,7 @@ fun settingColorSchemeProvider( .map { themeVariant -> val actionTitle = getAppThemeTitle(themeVariant, context) FlatItemAction( - title = actionTitle, + title = TextHolder.Value(actionTitle), onClick = { putTheme(themeVariant) .launchIn(windowCoroutineScope) @@ -75,10 +77,10 @@ fun settingColorSchemeProvider( } } -private fun getAppThemeTitle(appTheme: AppTheme?, context: LeContext) = when (appTheme) { - null -> textResource(Res.strings.follow_system_settings, context) - AppTheme.DARK -> textResource(Res.strings.theme_dark, context) - AppTheme.LIGHT -> textResource(Res.strings.theme_light, context) +private suspend fun getAppThemeTitle(appTheme: AppTheme?, context: LeContext) = when (appTheme) { + null -> textResource(Res.string.follow_system_settings, context) + AppTheme.DARK -> textResource(Res.string.theme_dark, context) + AppTheme.LIGHT -> textResource(Res.string.theme_light, context) } @Composable @@ -92,7 +94,7 @@ private fun SettingFont( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_color_scheme_title), + text = stringResource(Res.string.pref_item_color_scheme_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingConcealedFields.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingConcealedFields.kt index 686627cf..64712158 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingConcealedFields.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingConcealedFields.kt @@ -15,9 +15,10 @@ import com.artemchep.keyguard.common.usecase.GetConcealFields import com.artemchep.keyguard.common.usecase.PutConcealFields import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.IconBox -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -82,12 +83,12 @@ private fun SettingScreenshotsFields( }, title = { Text( - text = stringResource(Res.strings.pref_item_conceal_fields_title), + text = stringResource(Res.string.pref_item_conceal_fields_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_conceal_fields_text), + text = stringResource(Res.string.pref_item_conceal_fields_text), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrash.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrash.kt index 27cff409..af79cde9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrash.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrash.kt @@ -6,8 +6,9 @@ import androidx.compose.material.icons.outlined.BugReport import androidx.compose.runtime.Composable import com.artemchep.keyguard.feature.home.vault.component.VaultViewButtonItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -30,7 +31,7 @@ private fun SettingCrash( ) { VaultViewButtonItem( leading = icon(Icons.Outlined.BugReport), - text = stringResource(Res.strings.pref_item_crash_title), + text = stringResource(Res.string.pref_item_crash_title), onClick = onClick, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrashlytics.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrashlytics.kt index cd88dcc8..444a97c4 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrashlytics.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingCrashlytics.kt @@ -12,10 +12,11 @@ import arrow.core.partially1 import com.artemchep.keyguard.platform.crashlyticsIsEnabledFlow import com.artemchep.keyguard.platform.crashlyticsSetEnabled import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmptyForRow import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.IconBox -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI @@ -74,7 +75,7 @@ private fun SettingCrashlytics( }, title = { Text( - text = stringResource(Res.strings.pref_item_send_crash_reports_title), + text = stringResource(Res.string.pref_item_send_crash_reports_title), ) }, onClick = onCheckedChange?.partially1(checked != true), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingDataSafety.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingDataSafety.kt index 9ababec6..92214f27 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingDataSafety.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingDataSafety.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.datasafety.DataSafetyRoute import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -57,7 +58,7 @@ private fun SettingPermissionDetails( }, title = { Text( - text = stringResource(Res.strings.pref_item_data_safety_title), + text = stringResource(Res.string.pref_item_data_safety_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingExperimental.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingExperimental.kt index ec84d5e0..a6433dd9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingExperimental.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingExperimental.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.home.settings.experimental.ExperimentalSet import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -48,7 +49,7 @@ private fun SettingExperimental( }, title = { Text( - text = stringResource(Res.strings.pref_item_experimental_title), + text = stringResource(Res.string.pref_item_experimental_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeaturesOverview.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeaturesOverview.kt index 99afdd2f..6bee7c8d 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeaturesOverview.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeaturesOverview.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.onboarding.OnboardingRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -58,7 +59,7 @@ private fun SettingFeaturesOverview( }, title = { Text( - text = stringResource(Res.strings.pref_item_features_overview_title), + text = stringResource(Res.string.pref_item_features_overview_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeedbackApp.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeedbackApp.kt index 8f60d396..9a1d08c2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeedbackApp.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFeedbackApp.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.feedback.FeedbackRoute import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -59,7 +60,7 @@ fun SettingFeedbackAppItem( }, title = { Text( - text = stringResource(Res.strings.pref_item_contact_us_title), + text = stringResource(Res.string.pref_item_contact_us_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFont.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFont.kt index 47e752af..943b1332 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFont.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingFont.kt @@ -11,14 +11,16 @@ import com.artemchep.keyguard.common.usecase.GetFont import com.artemchep.keyguard.common.usecase.GetFontVariants import com.artemchep.keyguard.common.usecase.PutFont import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -49,8 +51,8 @@ fun settingFontProvider( val actionTitle = getAppFontTitle(fontVariant, context) val actionText = getAppFontText(fontVariant, context) FlatItemAction( - title = actionTitle, - text = actionText, + title = TextHolder.Value(actionTitle), + text = actionText?.let(TextHolder::Value), onClick = { putFont(fontVariant) .launchIn(windowCoroutineScope) @@ -74,19 +76,19 @@ fun settingFontProvider( } } -private fun getAppFontTitle(appFont: AppFont?, context: LeContext) = when (appFont) { - null -> textResource(Res.strings.follow_system_settings, context) +private suspend fun getAppFontTitle(appFont: AppFont?, context: LeContext) = when (appFont) { + null -> textResource(Res.string.follow_system_settings, context) AppFont.ROBOTO -> "Roboto" AppFont.NOTO -> "Noto" AppFont.ATKINSON_HYPERLEGIBLE -> "Atkinson Hyperlegible" } -private fun getAppFontText(appFont: AppFont?, context: LeContext) = when (appFont) { +private suspend fun getAppFontText(appFont: AppFont?, context: LeContext) = when (appFont) { null -> null AppFont.ROBOTO -> null AppFont.NOTO -> null AppFont.ATKINSON_HYPERLEGIBLE -> textResource( - Res.strings.font_atkinson_hyperlegible_text, + Res.string.font_atkinson_hyperlegible_text, context, ) } @@ -102,7 +104,7 @@ private fun SettingFont( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_font_title), + text = stringResource(Res.string.pref_item_font_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGitHub.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGitHub.kt index 1ea00a1c..4985c61a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGitHub.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGitHub.kt @@ -9,13 +9,14 @@ import androidx.compose.runtime.rememberUpdatedState import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardWebsite import com.artemchep.keyguard.ui.icons.icon import compose.icons.FeatherIcons import compose.icons.feathericons.Github -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -58,7 +59,7 @@ private fun SettingGitHub( }, title = { Text( - text = stringResource(Res.strings.pref_item_github_title), + text = stringResource(Res.string.pref_item_github_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGravatar.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGravatar.kt index 77ccd144..41e6cab2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGravatar.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingGravatar.kt @@ -14,9 +14,10 @@ import com.artemchep.keyguard.common.usecase.GetGravatar import com.artemchep.keyguard.common.usecase.PutGravatar import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import compose.icons.FeatherIcons -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -80,7 +81,7 @@ private fun SettingGravatar( }, title = { Text( - text = stringResource(Res.strings.pref_item_load_gravatar_icons_title), + text = stringResource(Res.string.pref_item_load_gravatar_icons_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingKeepScreenOn.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingKeepScreenOn.kt index 7b18fd90..b83d46a0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingKeepScreenOn.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingKeepScreenOn.kt @@ -11,8 +11,9 @@ import com.artemchep.keyguard.common.usecase.GetKeepScreenOn import com.artemchep.keyguard.common.usecase.PutKeepScreenOn import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -72,7 +73,7 @@ private fun SettingKeepScreenOn( }, title = { Text( - text = stringResource(Res.strings.pref_item_keep_screen_on_title), + text = stringResource(Res.string.pref_item_keep_screen_on_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingLocalization.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingLocalization.kt index 3d101101..8ea24da6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingLocalization.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingLocalization.kt @@ -10,11 +10,12 @@ import androidx.compose.runtime.rememberUpdatedState import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardWebsite import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -58,7 +59,7 @@ private fun SettingLocalization( }, title = { Text( - text = stringResource(Res.strings.pref_item_crowdin_title), + text = stringResource(Res.string.pref_item_crowdin_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMarkdown.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMarkdown.kt index 9c6b35cd..4486f8ff 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMarkdown.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMarkdown.kt @@ -23,10 +23,11 @@ import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -98,12 +99,12 @@ private fun SettingMarkdown( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_markdown_title), + text = stringResource(Res.string.pref_item_markdown_title), ) }, text = { Text( - text = stringResource(Res.strings.pref_item_markdown_text), + text = stringResource(Res.string.pref_item_markdown_text), ) }, ) @@ -119,7 +120,7 @@ private fun SettingMarkdown( }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMasterPassword.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMasterPassword.kt index c1706ce4..aa60394b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMasterPassword.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingMasterPassword.kt @@ -12,10 +12,11 @@ import com.artemchep.keyguard.feature.changepassword.ChangePasswordRoute import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -58,7 +59,7 @@ private fun SettingMasterPassword( }, title = { Text( - text = stringResource(Res.strings.pref_item_change_app_password_title), + text = stringResource(Res.string.pref_item_change_app_password_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavAnimation.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavAnimation.kt index 56b30610..08443493 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavAnimation.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavAnimation.kt @@ -11,13 +11,15 @@ import com.artemchep.keyguard.common.usecase.GetNavAnimationVariants import com.artemchep.keyguard.common.usecase.PutNavAnimation import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.feature.localization.textResource +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -45,9 +47,8 @@ fun settingNavAnimationProvider( val text = textResource(navAnimation.title, context) val dropdown = variants .map { navAnimationVariant -> - val title = textResource(navAnimationVariant.title, context) FlatItemAction( - title = title, + title = navAnimationVariant.title.wrap(), onClick = { putNavAnimation(navAnimationVariant) .launchIn(windowCoroutineScope) @@ -83,7 +84,7 @@ private fun SettingNavAnimation( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_nav_animation_title), + text = stringResource(Res.string.pref_item_nav_animation_title), ) }, text = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavLabel.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavLabel.kt index 2f4a1d4f..eb0aae02 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavLabel.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingNavLabel.kt @@ -14,9 +14,10 @@ import com.artemchep.keyguard.common.usecase.GetNavLabel import com.artemchep.keyguard.common.usecase.PutNavLabel import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -76,7 +77,7 @@ private fun SettingNavLabel( }, title = { Text( - text = stringResource(Res.strings.pref_item_nav_label_title), + text = stringResource(Res.string.pref_item_nav_label_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingOpenSourceLicenses.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingOpenSourceLicenses.kt index c4f3fd05..aca3f5fe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingOpenSourceLicenses.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingOpenSourceLicenses.kt @@ -11,10 +11,11 @@ import com.artemchep.keyguard.feature.license.LicenseRoute import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -56,7 +57,7 @@ private fun SettingOpenSourceLicenses( }, title = { Text( - text = stringResource(Res.strings.pref_item_open_source_licenses_title), + text = stringResource(Res.string.pref_item_open_source_licenses_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPrivacyPolicy.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPrivacyPolicy.kt index 251e9138..25703188 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPrivacyPolicy.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingPrivacyPolicy.kt @@ -10,12 +10,13 @@ import androidx.compose.runtime.rememberUpdatedState import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardWebsite import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.flowOf +import org.jetbrains.compose.resources.stringResource import org.kodein.di.DirectDI fun settingPrivacyPolicyProvider( @@ -56,7 +57,7 @@ private fun SettingPrivacyPolicy( }, title = { Text( - text = stringResource(Res.strings.pref_item_privacy_policy_title), + text = stringResource(Res.string.pref_item_privacy_policy_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRateApp.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRateApp.kt index c06f6efa..7ae67170 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRateApp.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRateApp.kt @@ -10,10 +10,11 @@ import androidx.compose.runtime.rememberUpdatedState import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -56,7 +57,7 @@ fun SettingRateAppItem( }, title = { Text( - text = stringResource(Res.strings.pref_item_rate_on_play_store_title), + text = stringResource(Res.string.pref_item_rate_on_play_store_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRequireMasterPassword.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRequireMasterPassword.kt index 2c75022e..eb0a8fc0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRequireMasterPassword.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingRequireMasterPassword.kt @@ -17,16 +17,18 @@ import com.artemchep.keyguard.common.usecase.GetBiometricTimeout import com.artemchep.keyguard.common.usecase.GetBiometricTimeoutVariants import com.artemchep.keyguard.common.usecase.PutBiometricTimeout import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.format import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest @@ -75,7 +77,7 @@ fun settingRequireMasterPasswordProvider( } } -private fun ah( +private suspend fun ah( fingerprintReadRepository: FingerprintReadRepository, getBiometricTimeout: GetBiometricTimeout, getBiometricTimeoutVariants: GetBiometricTimeoutVariants, @@ -99,7 +101,7 @@ private fun ah( .map { duration -> val title = getRequirePasswordDurationTitle(duration, context) FlatItemAction( - title = title, + title = TextHolder.Value(title), onClick = { putBiometricTimeout(duration) .launchIn(windowCoroutineScope) @@ -123,15 +125,15 @@ private fun ah( } } -private fun getRequirePasswordDurationTitle(duration: Duration, context: LeContext) = +private suspend fun getRequirePasswordDurationTitle(duration: Duration, context: LeContext) = when (duration) { Duration.ZERO -> textResource( - Res.strings.pref_item_require_app_password_immediately_text, + Res.string.pref_item_require_app_password_immediately_text, context, ) Duration.INFINITE -> textResource( - Res.strings.pref_item_require_app_password_never_text, + Res.string.pref_item_require_app_password_never_text, context, ) @@ -160,7 +162,7 @@ private fun ColumnScope.SettingRequireMasterPasswordContent( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_require_app_password_title), + text = stringResource(Res.string.pref_item_require_app_password_title), ) }, text = { @@ -173,7 +175,7 @@ private fun ColumnScope.SettingRequireMasterPasswordContent( color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), style = MaterialTheme.typography.bodySmall, - text = stringResource(Res.strings.pref_item_require_app_password_note), + text = stringResource(Res.string.pref_item_require_app_password_note), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingScreenshots.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingScreenshots.kt index 70776287..2fbb6f83 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingScreenshots.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingScreenshots.kt @@ -15,9 +15,10 @@ import com.artemchep.keyguard.common.usecase.PutAllowScreenshots import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -80,14 +81,14 @@ private fun SettingScreenshotsFields( }, title = { Text( - text = stringResource(Res.strings.pref_item_allow_screenshots_title), + text = stringResource(Res.string.pref_item_allow_screenshots_title), ) }, text = { val text = if (checked) { - stringResource(Res.strings.pref_item_allow_screenshots_text_on) + stringResource(Res.string.pref_item_allow_screenshots_text_on) } else { - stringResource(Res.strings.pref_item_allow_screenshots_text_off) + stringResource(Res.string.pref_item_allow_screenshots_text_off) } Text(text) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSection.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSection.kt index aa634586..2896b9bf 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSection.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSection.kt @@ -5,6 +5,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.home.settings.LocalSettingItemArgs import com.artemchep.keyguard.feature.home.vault.component.Section +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.ui.util.HorizontalDivider import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -22,7 +24,7 @@ fun settingSectionProvider(): SettingComponent = kotlin.run { if (title != null) { Section( - text = title, + text = textResource(title), ) } else { HorizontalDivider( @@ -35,5 +37,5 @@ fun settingSectionProvider(): SettingComponent = kotlin.run { } data class SettingSectionArgs( - val title: String? = null, + val title: TextHolder? = null, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSelectLocale.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSelectLocale.kt index 8aa613d1..b97c8d75 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSelectLocale.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSelectLocale.kt @@ -17,16 +17,18 @@ import com.artemchep.keyguard.common.usecase.GetLocale import com.artemchep.keyguard.common.usecase.GetLocaleVariants import com.artemchep.keyguard.common.usecase.PutLocale import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -70,7 +72,7 @@ fun settingSelectLocaleProvider( .map { item -> FlatItemAction( // leading = if (item.locale != null) null else icon(Icons.Outlined.AutoAwesome), - title = item.title, + title = TextHolder.Value(item.title), onClick = { putLocale(item.locale) .launchIn(windowCoroutineScope) @@ -107,14 +109,14 @@ private data class LocaleItem( val title: String, ) -private fun getLocaleTitle(locale: String?, context: LeContext) = locale +private suspend fun getLocaleTitle(locale: String?, context: LeContext) = locale ?.let { Locale.forLanguageTag(it).let { locale -> locale.getDisplayName(locale) .capitalize(locale) } } - ?: textResource(Res.strings.follow_system_settings, context) + ?: textResource(Res.string.follow_system_settings, context) @Composable private fun SettingLocale( @@ -129,7 +131,7 @@ private fun SettingLocale( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_locale_title), + text = stringResource(Res.string.pref_item_locale_title), ) }, text = { @@ -148,7 +150,7 @@ private fun SettingLocale( }, ) { Text( - text = stringResource(Res.strings.pref_item_locale_help_translation_button), + text = stringResource(Res.string.pref_item_locale_help_translation_button), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptions.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptions.kt index 24632838..d880434e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptions.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingSubscriptions.kt @@ -40,6 +40,7 @@ import com.artemchep.keyguard.feature.onboarding.OnboardingCard import com.artemchep.keyguard.feature.onboarding.onboardingItemsPremium import com.artemchep.keyguard.platform.LocalLeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Ah import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.ExpandedIfNotEmpty @@ -50,7 +51,7 @@ import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.shimmer.shimmer import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map @@ -113,13 +114,13 @@ private fun SettingSubscriptions( .fillMaxWidth(), ) { Text( - stringResource(Res.strings.pref_item_premium_membership_title), + stringResource(Res.string.pref_item_premium_membership_title), style = MaterialTheme.typography.bodyLarge, modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), ) Text( - stringResource(Res.strings.pref_item_premium_membership_text), + stringResource(Res.string.pref_item_premium_membership_text), style = MaterialTheme.typography.bodyMedium, modifier = Modifier .padding(top = 4.dp) @@ -143,7 +144,7 @@ private fun SettingSubscriptions( ) } } - Section(text = stringResource(Res.strings.pref_item_premium_membership_section_subscriptions_title)) + Section(text = stringResource(Res.string.pref_item_premium_membership_section_subscriptions_title)) loadableSubscriptions.fold( ifLoading = { repeat(SubscriptionsCountDefault) { @@ -153,7 +154,7 @@ private fun SettingSubscriptions( ifOk = { subscriptions -> if (subscriptions == null) { FlatSimpleNote( - text = stringResource(Res.strings.pref_item_premium_membership_failed_to_load_subscriptions), + text = stringResource(Res.string.pref_item_premium_membership_failed_to_load_subscriptions), type = SimpleNote.Type.WARNING, ) return@fold @@ -165,7 +166,7 @@ private fun SettingSubscriptions( } }, ) - Section(text = stringResource(Res.strings.pref_item_premium_membership_section_products_title)) + Section(text = stringResource(Res.string.pref_item_premium_membership_section_products_title)) loadableProducts.fold( ifLoading = { repeat(ProductsCountDefault) { @@ -175,7 +176,7 @@ private fun SettingSubscriptions( ifOk = { products -> if (products == null) { FlatSimpleNote( - text = stringResource(Res.strings.pref_item_premium_membership_failed_to_load_products), + text = stringResource(Res.string.pref_item_premium_membership_failed_to_load_products), type = SimpleNote.Type.WARNING, ) return@fold @@ -276,7 +277,7 @@ private fun SettingSubscriptionItem( ) { Ah( score = 1f, - text = stringResource(Res.strings.pref_item_premium_status_active), + text = stringResource(Res.string.pref_item_premium_status_active), ) val isCancelled = !status.willRenew @@ -287,7 +288,7 @@ private fun SettingSubscriptionItem( ) { Ah( score = 0f, - text = stringResource(Res.strings.pref_item_premium_status_will_not_renew), + text = stringResource(Res.string.pref_item_premium_status_will_not_renew), ) } } @@ -351,7 +352,7 @@ private fun SettingProductItem( ) { Ah( score = 1f, - text = stringResource(Res.strings.pref_item_premium_status_active), + text = stringResource(Res.string.pref_item_premium_status_active), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingThemeUseAmoledDark.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingThemeUseAmoledDark.kt index ae2d73b6..8c9beb14 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingThemeUseAmoledDark.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingThemeUseAmoledDark.kt @@ -13,10 +13,11 @@ import com.artemchep.keyguard.common.usecase.GetThemeUseAmoledDark import com.artemchep.keyguard.common.usecase.PutThemeUseAmoledDark import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -80,7 +81,7 @@ private fun SettingThemeUseAmoledDark( }, title = { Text( - text = stringResource(Res.strings.pref_item_color_scheme_amoled_dark_title), + text = stringResource(Res.string.pref_item_color_scheme_amoled_dark_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutLandscape.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutLandscape.kt index cc001f24..5613e2fa 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutLandscape.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutLandscape.kt @@ -14,9 +14,10 @@ import com.artemchep.keyguard.common.usecase.GetAllowTwoPanelLayoutInLandscape import com.artemchep.keyguard.common.usecase.PutAllowTwoPanelLayoutInLandscape import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -78,7 +79,7 @@ private fun SettingTwoPanelLayoutLandscape( }, title = { Text( - text = stringResource(Res.strings.pref_item_allow_two_panel_layout_in_landscape_title), + text = stringResource(Res.string.pref_item_allow_two_panel_layout_in_landscape_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutPortrait.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutPortrait.kt index e72ec695..e26f98ae 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutPortrait.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingTwoPanelLayoutPortrait.kt @@ -14,9 +14,10 @@ import com.artemchep.keyguard.common.usecase.GetAllowTwoPanelLayoutInPortrait import com.artemchep.keyguard.common.usecase.PutAllowTwoPanelLayoutInPortrait import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -78,7 +79,7 @@ private fun SettingTwoPanelLayoutPortrait( }, title = { Text( - text = stringResource(Res.strings.pref_item_allow_two_panel_layout_in_portrait_title), + text = stringResource(Res.string.pref_item_allow_two_panel_layout_in_portrait_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUrlOverride.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUrlOverride.kt index 533658cc..f8666073 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUrlOverride.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUrlOverride.kt @@ -12,10 +12,11 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.urloverride.UrlOverrideListRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI @@ -59,7 +60,7 @@ private fun SettingUrlOverride( }, title = { Text( - text = stringResource(Res.strings.pref_item_url_override_title), + text = stringResource(Res.string.pref_item_url_override_title), ) }, onClick = onClick, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUseExternalBrowser.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUseExternalBrowser.kt index 11d67d7e..edb9529e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUseExternalBrowser.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingUseExternalBrowser.kt @@ -16,9 +16,10 @@ import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -84,7 +85,7 @@ private fun SettingUseExternalBrowser( }, title = { Text( - text = stringResource(Res.strings.pref_item_open_links_in_external_browser_title), + text = stringResource(Res.string.pref_item_open_links_in_external_browser_title), ) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLock.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLock.kt index f6a055e8..2655d6d8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLock.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLock.kt @@ -9,8 +9,9 @@ import com.artemchep.keyguard.common.usecase.ClearVaultSession import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.feature.home.vault.component.VaultViewButtonItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.flowOf import org.kodein.di.DirectDI import org.kodein.di.instance @@ -51,7 +52,7 @@ fun SettingVaultLock( ) { VaultViewButtonItem( leading = icon(Icons.Outlined.Lock), - text = stringResource(Res.strings.pref_item_lock_vault_title), + text = stringResource(Res.string.pref_item_lock_vault_title), onClick = onClick, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterReboot.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterReboot.kt index 3dbf8cf3..5630850c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterReboot.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterReboot.kt @@ -14,11 +14,12 @@ import com.artemchep.keyguard.common.usecase.GetVaultPersist import com.artemchep.keyguard.common.usecase.PutVaultLockAfterReboot import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.Stub import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -89,10 +90,10 @@ private fun SettingLockAfterReboot( } }, title = { - Text(stringResource(Res.strings.pref_item_lock_vault_after_reboot_title)) + Text(stringResource(Res.string.pref_item_lock_vault_after_reboot_title)) }, text = { - val text = stringResource(Res.strings.pref_item_lock_vault_after_reboot_text) + val text = stringResource(Res.string.pref_item_lock_vault_after_reboot_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterScreenOff.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterScreenOff.kt index 46dd2d1a..56150f3b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterScreenOff.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterScreenOff.kt @@ -16,9 +16,10 @@ import com.artemchep.keyguard.common.usecase.PutVaultLockAfterScreenOff import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -84,10 +85,10 @@ private fun SettingLockAfterScreenOff( } }, title = { - Text(stringResource(Res.strings.pref_item_lock_vault_after_screen_off_title)) + Text(stringResource(Res.string.pref_item_lock_vault_after_screen_off_title)) }, text = { - val text = stringResource(Res.strings.pref_item_lock_vault_after_screen_off_text) + val text = stringResource(Res.string.pref_item_lock_vault_after_screen_off_text) Text(text) }, onClick = onCheckedChange?.partially1(!checked), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterTimeout.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterTimeout.kt index 69f66379..1d0bb9f6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterTimeout.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultLockAfterTimeout.kt @@ -10,15 +10,17 @@ import com.artemchep.keyguard.common.usecase.GetVaultLockAfterTimeout import com.artemchep.keyguard.common.usecase.GetVaultLockAfterTimeoutVariants import com.artemchep.keyguard.common.usecase.PutVaultLockAfterTimeout import com.artemchep.keyguard.common.usecase.WindowCoroutineScope +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.format import com.artemchep.keyguard.ui.icons.icon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.combine import org.kodein.di.DirectDI import org.kodein.di.instance @@ -49,7 +51,7 @@ fun settingVaultLockAfterTimeoutProvider( .map { duration -> val title = getLockAfterDurationTitle(duration, context) FlatItemAction( - title = title, + title = TextHolder.Value(title), onClick = { putVaultLockAfterTimeout(duration) .launchIn(windowCoroutineScope) @@ -74,14 +76,14 @@ fun settingVaultLockAfterTimeoutProvider( } } -private fun getLockAfterDurationTitle(duration: Duration, context: LeContext) = when (duration) { +private suspend fun getLockAfterDurationTitle(duration: Duration, context: LeContext) = when (duration) { Duration.ZERO -> textResource( - Res.strings.pref_item_lock_vault_after_delay_immediately_text, + Res.string.pref_item_lock_vault_after_delay_immediately_text, context, ) Duration.INFINITE -> textResource( - Res.strings.pref_item_lock_vault_after_delay_never_text, + Res.string.pref_item_lock_vault_after_delay_never_text, context, ) @@ -99,7 +101,7 @@ fun SettingLockAfterTimeout( content = { FlatItemTextContent( title = { - Text(stringResource(Res.strings.pref_item_lock_vault_after_delay_title)) + Text(stringResource(Res.string.pref_item_lock_vault_after_delay_title)) }, text = { Text(text) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultPersist.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultPersist.kt index 600bb318..d1475893 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultPersist.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingVaultPersist.kt @@ -20,6 +20,7 @@ import com.artemchep.keyguard.common.usecase.GetVaultPersist import com.artemchep.keyguard.common.usecase.PutVaultPersist import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent @@ -27,7 +28,7 @@ import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -91,13 +92,13 @@ private fun SettingVaultPersist( content = { FlatItemTextContent( title = { - Text(stringResource(Res.strings.pref_item_persist_vault_key_title)) + Text(stringResource(Res.string.pref_item_persist_vault_key_title)) }, text = { val text = if (checked) { - stringResource(Res.strings.pref_item_persist_vault_key_text_on) + stringResource(Res.string.pref_item_persist_vault_key_text_on) } else { - stringResource(Res.strings.pref_item_persist_vault_key_text_off) + stringResource(Res.string.pref_item_persist_vault_key_text_off) } Text( modifier = Modifier @@ -121,7 +122,7 @@ private fun SettingVaultPersist( start = Dimens.horizontalPadding * 1 + 24.dp, ), type = SimpleNote.Type.WARNING, - text = stringResource(Res.strings.pref_item_persist_vault_key_note), + text = stringResource(Res.string.pref_item_persist_vault_key_note), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingWebsiteIcons.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingWebsiteIcons.kt index f5c1c783..6e54b375 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingWebsiteIcons.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/component/SettingWebsiteIcons.kt @@ -26,13 +26,14 @@ import com.artemchep.keyguard.common.usecase.WindowCoroutineScope import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.icons.KeyguardWebsite import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.map import org.kodein.di.DirectDI import org.kodein.di.instance @@ -103,7 +104,7 @@ private fun SettingMarkdown( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.pref_item_load_website_icons_title), + text = stringResource(Res.string.pref_item_load_website_icons_title), ) }, ) @@ -115,7 +116,7 @@ private fun SettingMarkdown( color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), style = MaterialTheme.typography.bodySmall, - text = stringResource(Res.strings.pref_item_load_website_icons_text), + text = stringResource(Res.string.pref_item_load_website_icons_text), ) }, onClick = onCheckedChange?.partially1(!checked), @@ -129,7 +130,7 @@ private fun SettingMarkdown( }, ) { Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/debug/DebugSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/debug/DebugSettingsScreen.kt index e675af6c..72a0bc15 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/debug/DebugSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/debug/DebugSettingsScreen.kt @@ -1,21 +1,24 @@ package com.artemchep.keyguard.feature.home.settings.debug import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem +import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun DebugSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_dev_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Group( key = "ui", - title = "UI", - list = listOf( + title = "UI".let(TextHolder::Value), + list = persistentListOf( SettingPaneItem.Item(Setting.EMIT_MESSAGE), SettingPaneItem.Item(Setting.EMIT_TOTP), SettingPaneItem.Item(Setting.CLEAR_CACHE), @@ -27,18 +30,22 @@ fun DebugSettingsScreen() { ), SettingPaneItem.Group( key = "billing", - title = "Billing", - list = listOf( + title = "Billing".let(TextHolder::Value), + list = persistentListOf( SettingPaneItem.Item(Setting.SUBSCRIPTIONS_DEBUG), ), ), SettingPaneItem.Group( key = "security", - title = "Security", - list = listOf( + title = "Security".let(TextHolder::Value), + list = persistentListOf( SettingPaneItem.Item(Setting.ROTATE_DEVICE_ID), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_dev_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/display/UiSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/display/UiSettingsScreen.kt index 404e8fbb..03d9ccd2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/display/UiSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/display/UiSettingsScreen.kt @@ -1,26 +1,28 @@ package com.artemchep.keyguard.feature.home.settings.display import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun UiSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_appearance_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Group( key = "locale", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.LOCALE), ), ), SettingPaneItem.Group( key = "color_scheme", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.COLOR_SCHEME), SettingPaneItem.Item(Setting.COLOR_SCHEME_AMOLED_DARK), SettingPaneItem.Item(Setting.COLOR_ACCENT), @@ -32,7 +34,7 @@ fun UiSettingsScreen() { ), SettingPaneItem.Group( key = "icons", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.APP_ICONS), SettingPaneItem.Item(Setting.WEBSITE_ICONS), SettingPaneItem.Item(Setting.GRAVATAR), @@ -40,7 +42,7 @@ fun UiSettingsScreen() { ), SettingPaneItem.Group( key = "experience", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.USE_EXTERNAL_BROWSER), SettingPaneItem.Item(Setting.KEEP_SCREEN_ON), SettingPaneItem.Item(Setting.CLOSE_TO_TRAY), @@ -48,11 +50,15 @@ fun UiSettingsScreen() { ), SettingPaneItem.Group( key = "layout", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.TWO_PANEL_LAYOUT_PORTRAIT), SettingPaneItem.Item(Setting.TWO_PANEL_LAYOUT_LANDSCAPE), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_appearance_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/experimental/ExperimentalSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/experimental/ExperimentalSettingsScreen.kt index e1b11643..f08669eb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/experimental/ExperimentalSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/experimental/ExperimentalSettingsScreen.kt @@ -1,18 +1,24 @@ package com.artemchep.keyguard.feature.home.settings.experimental import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun ExperimentalSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_experimental_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Item(Setting.WRITE_ACCESS), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_experimental_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/notifications/NotificationsSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/notifications/NotificationsSettingsScreen.kt index 61cd95fb..9481bd45 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/notifications/NotificationsSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/notifications/NotificationsSettingsScreen.kt @@ -1,19 +1,25 @@ package com.artemchep.keyguard.feature.home.settings.notifications import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun NotificationsSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_notifications_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Item(Setting.PERMISSION_CAMERA), SettingPaneItem.Item(Setting.PERMISSION_POST_NOTIFICATION), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_notifications_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/other/OtherSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/other/OtherSettingsScreen.kt index f8809628..3b9bd0c0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/other/OtherSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/other/OtherSettingsScreen.kt @@ -1,46 +1,42 @@ package com.artemchep.keyguard.feature.home.settings.other import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun OtherSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_other_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Group( key = "features", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.FEATURES_OVERVIEW), ), ), SettingPaneItem.Group( key = "other", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.URL_OVERRIDE), ), ), SettingPaneItem.Group( key = "security", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.CRASHLYTICS), SettingPaneItem.Item(Setting.DATA_SAFETY), SettingPaneItem.Item(Setting.PERMISSION_DETAILS), ), ), -// SettingPaneItem.Group( -// key = "exp", -// list = listOf( -// SettingPaneItem.Item(Setting.EXPERIMENTAL), -// ), -// ), SettingPaneItem.Group( key = "social", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.RATE_APP), SettingPaneItem.Item(Setting.ABOUT_TEAM), SettingPaneItem.Item(Setting.REDDIT), @@ -55,6 +51,10 @@ fun OtherSettingsScreen() { SettingPaneItem.Item(Setting.ABOUT_APP_BUILD_DATE), SettingPaneItem.Item(Setting.ABOUT_APP_BUILD_REF), SettingPaneItem.Item(Setting.ABOUT_APP_CHANGELOG), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_other_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/permissions/PermissionsSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/permissions/PermissionsSettingsScreen.kt index 8c5189fc..87051ffe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/permissions/PermissionsSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/permissions/PermissionsSettingsScreen.kt @@ -1,20 +1,22 @@ package com.artemchep.keyguard.feature.home.settings.permissions import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun PermissionsSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_permissions_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Group( key = "runtime", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.PERMISSION_CAMERA), SettingPaneItem.Item(Setting.PERMISSION_POST_NOTIFICATION), SettingPaneItem.Item(Setting.PERMISSION_WRITE_EXTERNAL_STORAGE), @@ -22,10 +24,14 @@ fun PermissionsSettingsScreen() { ), SettingPaneItem.Group( key = "other", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.PERMISSION_OTHER), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_permissions_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/search/SearchSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/search/SearchSettingsScreen.kt index efde6a73..a42e8066 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/search/SearchSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/search/SearchSettingsScreen.kt @@ -28,6 +28,7 @@ import com.artemchep.keyguard.feature.EmptySearchView import com.artemchep.keyguard.feature.home.vault.component.SearchTextField import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -36,7 +37,7 @@ import com.artemchep.keyguard.ui.focus.focusRequester2 import com.artemchep.keyguard.ui.pulltosearch.PullToSearch import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.CustomToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay @Composable @@ -92,7 +93,7 @@ fun SearchSettingsScreenContent( .align(Alignment.CenterVertically), ) { Text( - text = stringResource(Res.strings.settingssearch_header_subtitle), + text = stringResource(Res.string.settingssearch_header_subtitle), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -100,7 +101,7 @@ fun SearchSettingsScreenContent( maxLines = 2, ) Text( - text = stringResource(Res.strings.settingssearch_header_title), + text = stringResource(Res.string.settingssearch_header_title), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -114,7 +115,7 @@ fun SearchSettingsScreenContent( modifier = Modifier .focusRequester2(focusRequester), text = state.query.state.value, - placeholder = stringResource(Res.strings.settingssearch_search_placeholder), + placeholder = stringResource(Res.string.settingssearch_search_placeholder), searchIcon = false, count = count, leading = {}, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/security/SecuritySettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/security/SecuritySettingsScreen.kt index 9728f666..c683881b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/security/SecuritySettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/security/SecuritySettingsScreen.kt @@ -1,17 +1,19 @@ package com.artemchep.keyguard.feature.home.settings.security import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun SecuritySettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_security_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Item(Setting.VAULT_PERSIST), SettingPaneItem.Item(Setting.VAULT_LOCK_AFTER_TIMEOUT), SettingPaneItem.Item(Setting.VAULT_LOCK_AFTER_SCREEN_OFF), @@ -19,14 +21,14 @@ fun SecuritySettingsScreen() { SettingPaneItem.Item(Setting.VAULT_LOCK), SettingPaneItem.Group( key = "clipboard", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.CLIPBOARD_AUTO_REFRESH), SettingPaneItem.Item(Setting.CLIPBOARD_NOTIFICATION_SETTINGS), ), ), SettingPaneItem.Group( key = "visuals", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.CONCEAL), SettingPaneItem.Item(Setting.SCREENSHOTS), SettingPaneItem.Item(Setting.WEBSITE_ICONS), @@ -35,7 +37,7 @@ fun SecuritySettingsScreen() { ), SettingPaneItem.Group( key = "biometric", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.BIOMETRIC), SettingPaneItem.Item(Setting.BIOMETRIC_REQUIRE_CONFIRMATION), SettingPaneItem.Item(Setting.REQUIRE_MASTER_PASSWORD), @@ -43,10 +45,14 @@ fun SecuritySettingsScreen() { ), SettingPaneItem.Group( key = "password", - list = listOf( + list = persistentListOf( SettingPaneItem.Item(Setting.MASTER_PASSWORD), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_security_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/subscriptions/SubscriptionsSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/subscriptions/SubscriptionsSettingsScreen.kt index ae089451..77b761f1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/subscriptions/SubscriptionsSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/subscriptions/SubscriptionsSettingsScreen.kt @@ -1,28 +1,35 @@ package com.artemchep.keyguard.feature.home.settings.subscriptions import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun SubscriptionsSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_subscriptions_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Item(Setting.SUBSCRIPTIONS), SettingPaneItem.Group( key = "other", - title = stringResource(Res.strings.misc), - list = listOf( + title = Res.string.misc.wrap(), + list = persistentListOf( SettingPaneItem.Item(Setting.SUBSCRIPTIONS_IN_STORE), SettingPaneItem.Item(Setting.ABOUT_TEAM), SettingPaneItem.Item(Setting.FEEDBACK_APP), SettingPaneItem.Item(Setting.APK), ), ), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_subscriptions_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/watchtower/WatchtowerSettingsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/watchtower/WatchtowerSettingsScreen.kt index fdf65b4b..240c75db 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/watchtower/WatchtowerSettingsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/settings/watchtower/WatchtowerSettingsScreen.kt @@ -1,21 +1,27 @@ package com.artemchep.keyguard.feature.home.settings.watchtower import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.artemchep.keyguard.feature.home.settings.Setting import com.artemchep.keyguard.feature.home.settings.SettingPaneContent import com.artemchep.keyguard.feature.home.settings.SettingPaneItem import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import kotlinx.collections.immutable.persistentListOf +import org.jetbrains.compose.resources.stringResource @Composable fun WatchtowerSettingsScreen() { - SettingPaneContent( - title = stringResource(Res.strings.settings_watchtower_header_title), - items = listOf( + val items = remember { + persistentListOf( SettingPaneItem.Item(Setting.CHECK_PWNED_PASSWORDS), SettingPaneItem.Item(Setting.CHECK_PWNED_SERVICES), SettingPaneItem.Item(Setting.CHECK_TWO_FA), SettingPaneItem.Item(Setting.CHECK_PASSKEYS), - ), + ) + } + SettingPaneContent( + title = stringResource(Res.string.settings_watchtower_header_title), + items = items, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/VaultRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/VaultRoute.kt index a6d20b36..91b567de 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/VaultRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/VaultRoute.kt @@ -10,6 +10,7 @@ import com.artemchep.keyguard.feature.home.vault.search.sort.Sort import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* data class VaultRoute( val args: Args = Args(), @@ -52,20 +53,20 @@ data class VaultRoute( // Organization // - fun by(translator: TranslatorScope, organization: DOrganization) = by( + suspend fun by(translator: TranslatorScope, organization: DOrganization) = by( translator = translator, organizations = listOf(organization), ) @JvmName("byOrganizations") - fun by(translator: TranslatorScope, organizations: Collection) = VaultRoute( + suspend fun by(translator: TranslatorScope, organizations: Collection) = VaultRoute( args = Args( appBar = Args.AppBar( title = organizations.joinToString { it.name }, subtitle = if (organizations.size > 1) { - translator.translate(Res.strings.organizations) + translator.translate(Res.string.organizations) } else { - translator.translate(Res.strings.organization) + translator.translate(Res.string.organization) }, ), filter = DFilter.Or( @@ -94,20 +95,20 @@ data class VaultRoute( // Collection // - fun by(translator: TranslatorScope, collection: DCollection) = by( + suspend fun by(translator: TranslatorScope, collection: DCollection) = by( translator = translator, collections = listOf(collection), ) @JvmName("byCollections") - fun by(translator: TranslatorScope, collections: Collection) = VaultRoute( + suspend fun by(translator: TranslatorScope, collections: Collection) = VaultRoute( args = Args( appBar = Args.AppBar( title = collections.joinToString { it.name }, subtitle = if (collections.size > 1) { - translator.translate(Res.strings.collections) + translator.translate(Res.string.collections) } else { - translator.translate(Res.strings.collection) + translator.translate(Res.string.collection) }, ), filter = DFilter.Or( @@ -136,20 +137,20 @@ data class VaultRoute( // Folder // - fun by(translator: TranslatorScope, folder: DFolder) = by( + suspend fun by(translator: TranslatorScope, folder: DFolder) = by( translator = translator, folders = listOf(folder), ) @JvmName("byFolders") - fun by(translator: TranslatorScope, folders: Collection) = VaultRoute( + suspend fun by(translator: TranslatorScope, folders: Collection) = VaultRoute( args = Args( appBar = Args.AppBar( title = folders.joinToString { it.name }, subtitle = if (folders.size > 1) { - translator.translate(Res.strings.folders) + translator.translate(Res.string.folders) } else { - translator.translate(Res.strings.folder) + translator.translate(Res.string.folder) }, ), filter = DFilter.Or( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddScreen.kt index b73ca85a..e126f507 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.filepicker.FilePickerEffect import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FabState @@ -47,7 +48,7 @@ import com.artemchep.keyguard.ui.button.FavouriteToggleButton import com.artemchep.keyguard.ui.shimmer.shimmer import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AddScreen( @@ -155,7 +156,7 @@ private fun AddScreenContent( }, text = { Text( - text = stringResource(Res.strings.save), + text = stringResource(Res.string.save), ) }, ) @@ -332,7 +333,7 @@ private fun AddScreenMergeItem( }, content = { Text( - text = stringResource(Res.strings.additem_merge_remove_origin_ciphers_title), + text = stringResource(Res.string.additem_merge_remove_origin_ciphers_title), ) }, onClick = { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddStateProducer.kt index 3483c59c..def2d9ee 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/add/AddStateProducer.kt @@ -127,18 +127,22 @@ import com.artemchep.keyguard.feature.home.vault.add.attachment.SkeletonAttachme import com.artemchep.keyguard.feature.home.vault.add.attachment.SkeletonAttachmentItemFactory import com.artemchep.keyguard.feature.home.vault.component.obscurePassword import com.artemchep.keyguard.feature.home.vault.screen.VaultViewRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.leParseUri import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.provider.bitwarden.usecase.autofill import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.buildContextItems @@ -261,7 +265,7 @@ fun produceAddScreenState( val ciphersHaveAttachments = args.merge.ciphers.any { it.attachments.isNotEmpty() } val note = when { ciphersHaveAttachments -> { - val text = translate(Res.strings.additem_merge_attachments_note) + val text = translate(Res.string.additem_merge_attachments_note) SimpleNote( text = text, type = SimpleNote.Type.INFO, @@ -346,7 +350,7 @@ fun produceAddScreenState( val header = AddStateItem.Section( id = "passkey.section", - text = translate(Res.strings.passkeys), + text = translate(Res.string.passkeys), ) add(0, header) }, @@ -377,7 +381,7 @@ fun produceAddScreenState( afterList = { val header = AddStateItem.Section( id = "uri.section", - text = translate(Res.strings.uris), + text = translate(Res.string.uris), ) add(0, header) }, @@ -389,7 +393,7 @@ fun produceAddScreenState( listOf( Foo2Type( type = "uri", - name = translate(Res.strings.uri), + name = translate(Res.string.uri), ), ), ), @@ -446,13 +450,13 @@ fun produceAddScreenState( val header = AddStateItem.Section( id = "attachment.section", - text = translate(Res.strings.attachments), + text = translate(Res.string.attachments), ) add(0, header) }, extra = { val action = FlatItemAction( - title = "Attachment", + title = TextHolder.Value("Attachment"), onClick = { val intent = FilePickerIntent.OpenDocument { info -> val msg = ToastMessage( @@ -479,7 +483,7 @@ fun produceAddScreenState( ) val item = AddStateItem.Add( id = "attachment.add", - text = translate(Res.strings.list_add), + text = translate(Res.string.list_add), actions = persistentListOf(action), ) flowOf(emptyList()) @@ -542,8 +546,8 @@ fun produceAddScreenState( val reprompt = AddStateItem.Switch( id = "reprompt", - title = translate(Res.strings.additem_auth_reprompt_title), - text = translate(Res.strings.additem_auth_reprompt_text), + title = translate(Res.string.additem_auth_reprompt_title), + text = translate(Res.string.additem_auth_reprompt_text), state = LocalStateItem( flow = kotlin.run { val sink = mutablePersistedFlow("reprompt") { @@ -578,8 +582,8 @@ fun produceAddScreenState( .map { model -> FlatItemAction( id = item.id, - title = item.title, - text = item.text, + title = item.title.let(TextHolder::Value), + text = item.text?.let(TextHolder::Value), leading = icon(Icons.Outlined.Password), trailing = { Switch( @@ -628,7 +632,7 @@ fun produceAddScreenState( afterList = { val header = AddStateItem.Section( id = "field.section", - text = translate(Res.strings.custom_fields), + text = translate(Res.string.custom_fields), ) add(0, header) }, @@ -640,15 +644,15 @@ fun produceAddScreenState( .map { type -> val textType = Foo2Type( type = "field.text", - name = translate(Res.strings.field_type_text), + name = translate(Res.string.field_type_text), ) val booleanType = Foo2Type( type = "field.boolean", - name = translate(Res.strings.field_type_boolean), + name = translate(Res.string.field_type_boolean), ) val linkedIdType = Foo2Type( type = "field.linked_id", - name = translate(Res.strings.field_type_linked), + name = translate(Res.string.field_type_linked), ) when (type) { DSecret.Type.Login, @@ -743,11 +747,11 @@ fun produceAddScreenState( } val title = if (args.merge != null) { - translate(Res.strings.additem_header_merge_title) + translate(Res.string.additem_header_merge_title) } else if (args.ownershipRo) { - translate(Res.strings.additem_header_edit_title) + translate(Res.string.additem_header_edit_title) } else { - translate(Res.strings.additem_header_new_title) + translate(Res.string.additem_header_new_title) } val itfff = combine( typeItemsFlow, @@ -962,7 +966,7 @@ class AddStateItemUriFactory( val actionsAppPickerItem = FlatItemAction( leading = icon(Icons.Outlined.Apps), - title = translate(Res.strings.uri_match_app_title), + title = Res.string.uri_match_app_title.wrap(), trailing = { ChevronIcon() }, @@ -983,12 +987,11 @@ class AddStateItemUriFactory( // match type via an option. val actionsMatchTypeItemFlow = matchTypeSink .map { selectedMatchType -> - val text = translate(selectedMatchType.titleH()) FlatItemAction( leading = icon(Icons.Stub), - title = translate(Res.strings.uri_match_detection_title), - text = text, - onClick = { + title = Res.string.uri_match_detection_title.wrap(), + text = selectedMatchType.titleH().wrap(), + onClick = onClick { val items = DSecret.Uri.MatchType.entries .map { type -> val typeTitle = translate(type.titleH()) @@ -1004,32 +1007,32 @@ class AddStateItemUriFactory( items = items, docs = mapOf( DSecret.Uri.MatchType.Domain.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_domain_note), + text = translate(Res.string.uri_match_detection_domain_note), url = "https://bitwarden.com/help/uri-match-detection/#base-domain", ), DSecret.Uri.MatchType.Host.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_host_note), + text = translate(Res.string.uri_match_detection_host_note), url = "https://bitwarden.com/help/uri-match-detection/#host", ), DSecret.Uri.MatchType.StartsWith.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_startswith_note), + text = translate(Res.string.uri_match_detection_startswith_note), url = "https://bitwarden.com/help/uri-match-detection/#starts-with", ), DSecret.Uri.MatchType.Exact.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_exact_note), + text = translate(Res.string.uri_match_detection_exact_note), url = "https://bitwarden.com/help/uri-match-detection/#regular-expression", ), DSecret.Uri.MatchType.RegularExpression.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_regex_note), + text = translate(Res.string.uri_match_detection_regex_note), url = "https://bitwarden.com/help/uri-match-detection/#regular-expression", ), DSecret.Uri.MatchType.Never.name to ConfirmationRoute.Args.Item.EnumItem.Doc( - text = translate(Res.strings.uri_match_detection_never_note), + text = translate(Res.string.uri_match_detection_never_note), url = "https://bitwarden.com/help/uri-match-detection/#exact", ), ), ), - title = translate(Res.strings.uri_match_detection_title), + title = translate(Res.string.uri_match_detection_title), ) { newMatchTypeKey -> matchTypeSink.value = DSecret.Uri.MatchType.valueOf(newMatchTypeKey) @@ -1075,7 +1078,7 @@ class AddStateItemUriFactory( if (isUnsecure) { TextFieldModel2.Vl( type = TextFieldModel2.Vl.Type.WARNING, - text = translate(Res.strings.uri_unsecure), + text = translate(Res.string.uri_unsecure), ) } else { null @@ -1353,7 +1356,7 @@ class AddStateItemFieldTextFactory : AddStateItemFieldFactory() { ) } }, - title = "Conceal value", + title = TextHolder.Value("Conceal value"), trailing = { Checkbox( checked = conceal, @@ -1505,7 +1508,7 @@ class AddStateItemFieldLinkedIdFactory( onClick = null, ) }, - title = translate(actionLinkedId.titleH()), + title = actionLinkedId.titleH().wrap(), onClick = { valueSink.value = actionLinkedId }, @@ -1576,14 +1579,14 @@ data class Foo2InitialState( ) } -fun RememberStateFlowScope.foo3( +suspend fun RememberStateFlowScope.foo3( logRepository: LogRepository, scope: String, initial: List, initialType: (Argument) -> String, factories: List>, - afterList: MutableList.() -> Unit, - extra: FieldBakeryScope.() -> Flow> = { + afterList: suspend MutableList.() -> Unit, + extra: suspend FieldBakeryScope.() -> Flow> = { flowOf(emptyList()) }, ): Flow> where T : AddStateItem, T : AddStateItem.HasOptions { @@ -1624,12 +1627,12 @@ fun RememberStateFlowScope.foo3( } } -fun RememberStateFlowScope.foo2( +suspend fun RememberStateFlowScope.foo2( scope: String, initialState: Foo2InitialState, factories: List>, - afterList: MutableList.() -> Unit, - extra: FieldBakeryScope.() -> Flow> = { + afterList: suspend MutableList.() -> Unit, + extra: suspend FieldBakeryScope.() -> Flow> = { flowOf(emptyList()) }, ): Flow> where T : AddStateItem, T : AddStateItem.HasOptions { @@ -1676,7 +1679,7 @@ private fun FieldBakeryScope.typeBasedAddItem( val actions = buildContextItems { types.forEach { type -> this += FlatItemAction( - title = type.name, + title = TextHolder.Value(type.name), onClick = ::add .partially1(type.type) .partially1(null), @@ -1685,20 +1688,20 @@ private fun FieldBakeryScope.typeBasedAddItem( } AddStateItem.Add( id = "$scope.add", - text = translator.translate(Res.strings.list_add), + text = translator.translate(Res.string.list_add), actions = actions, ) } .map { listOfNotNull(it) } -fun RememberStateFlowScope.foo( +suspend fun RememberStateFlowScope.foo( // scope name, scope: String, initialState: Foo2InitialState, entryAdd: RememberStateFlowScope.(Foo2Persistable, Argument?) -> T, entryRelease: RememberStateFlowScope.(Foo2Persistable) -> Unit, - afterList: MutableList.() -> Unit, - extra: FieldBakeryScope.() -> Flow> = { + afterList: suspend MutableList.() -> Unit, + extra: suspend FieldBakeryScope.() -> Flow> = { flowOf(emptyList()) }, ): Flow> where T : AddStateItem, T : AddStateItem.HasOptions { @@ -1827,24 +1830,24 @@ fun RememberStateFlowScope.foo( if (index > 0) { this += FlatItemAction( icon = Icons.Outlined.ArrowUpward, - title = translate(Res.strings.list_move_up), + title = Res.string.list_move_up.wrap(), onClick = ::moveUp.partially1(entry.key), ) } if (index < state.size - 1) { this += FlatItemAction( icon = Icons.Outlined.ArrowDownward, - title = translate(Res.strings.list_move_down), + title = Res.string.list_move_down.wrap(), onClick = ::moveDown.partially1(entry.key), ) } this += FlatItemAction( icon = Icons.Outlined.DeleteForever, - title = translate(Res.strings.list_remove), - onClick = { + title = Res.string.list_remove.wrap(), + onClick = onClick { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.DeleteForever), - title = translate(Res.strings.list_remove_confirmation_title), + title = translate(Res.string.list_remove_confirmation_title), ) { delete(entry.key) } @@ -1864,7 +1867,8 @@ fun RememberStateFlowScope.foo( .widen() .toMutableList() out += customItems - out.apply(afterList) + afterList(out) + out } .shareIn(screenScope, SharingStarted.WhileSubscribed(5000L), replay = 1) } @@ -1920,7 +1924,7 @@ private suspend fun RememberStateFlowScope.produceOwnershipFlow( if (organizationId == null) { val item = AddStateOwnership.Element.Item( key = "organization.empty", - title = translate(Res.strings.organization_none), + title = translate(Res.string.organization_none), stub = true, ) val el = AddStateOwnership.Element( @@ -1994,7 +1998,7 @@ private suspend fun RememberStateFlowScope.produceOwnershipFlow( is FolderInfo.None -> { val item = AddStateOwnership.Element.Item( key = "folder.empty", - title = translate(Res.strings.folder_none), + title = translate(Res.string.folder_none), stub = true, ) val el = AddStateOwnership.Element( @@ -2069,12 +2073,12 @@ private suspend fun RememberStateFlowScope.produceOwnershipFlow( organization = organization.element.takeIf { account.value != null }, collection = collection.element.takeIf { account.value != null }, folder = folder.element, - onClick = { + onClick = onClick { val route = registerRouteResultReceiver( route = OrganizationConfirmationRoute( args = OrganizationConfirmationRoute.Args( decor = OrganizationConfirmationRoute.Args.Decor( - title = translate(Res.strings.save_to), + title = translate(Res.string.save_to), icon = Icons.Outlined.AccountBox, ), flags = flags, @@ -2570,7 +2574,7 @@ private suspend fun RememberStateFlowScope.produceCardState( val badge = if (!isValid) { TextFieldModel2.Vl( type = TextFieldModel2.Vl.Type.WARNING, - text = translate(Res.strings.error_invalid_card_number), + text = translate(Res.string.error_invalid_card_number), ) } else { null @@ -2613,7 +2617,7 @@ private suspend fun RememberStateFlowScope.produceCardState( val card = args.initialValue?.card val number = createItem4( key = "number", - label = translate(Res.strings.card_number), + label = translate(Res.string.card_number), initialValue = card?.number, keyboardOptions = KeyboardOptions( autoCorrect = false, @@ -2657,7 +2661,7 @@ private suspend fun RememberStateFlowScope.produceCardState( ) val cardholderName = createItem( key = "cardholderName", - label = translate(Res.strings.cardholder_name), + label = translate(Res.string.cardholder_name), initialValue = card?.cardholderName, singleLine = true, lens = CreateRequest.card.cardholderName, @@ -2675,7 +2679,7 @@ private suspend fun RememberStateFlowScope.produceCardState( .toPersistentList() val brand = createItem( key = "brand", - label = translate(Res.strings.card_type), + label = translate(Res.string.card_type), initialValue = card?.brand, singleLine = true, hint = brandAutocompleteVariants @@ -2693,7 +2697,7 @@ private suspend fun RememberStateFlowScope.produceCardState( val fromDate = createItem2( prefix = prefix, key = "from", - label = translate(Res.strings.valid_from), + label = translate(Res.string.valid_from), initialMonth = card?.fromMonth, initialYear = card?.fromYear, populator = { @@ -2732,7 +2736,7 @@ private suspend fun RememberStateFlowScope.produceCardState( val expDate = createItem2( prefix = prefix, key = "exp", - label = translate(Res.strings.expiry_date), + label = translate(Res.string.expiry_date), initialMonth = card?.expMonth, initialYear = card?.expYear, populator = { @@ -2770,7 +2774,7 @@ private suspend fun RememberStateFlowScope.produceCardState( // ) val code = createItem( key = "code", - label = translate(Res.strings.card_cvv), + label = translate(Res.string.card_cvv), hint = "111", initialValue = card?.code, singleLine = true, @@ -2861,7 +2865,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( val identity = args.initialValue?.identity val title = createItem( key = "title", - label = translate(Res.strings.identity_title), + label = translate(Res.string.identity_title), initialValue = identity?.title, singleLine = true, lens = CreateRequest.identity.title, @@ -2875,7 +2879,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val firstName = createItem( key = "firstName", - label = translate(Res.strings.identity_first_name), + label = translate(Res.string.identity_first_name), initialValue = identity?.firstName ?: args.autofill?.personName, singleLine = true, lens = CreateRequest.identity.firstName, @@ -2889,7 +2893,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val middleName = createItem( key = "middleName", - label = translate(Res.strings.identity_middle_name), + label = translate(Res.string.identity_middle_name), initialValue = identity?.middleName, singleLine = true, lens = CreateRequest.identity.middleName, @@ -2903,7 +2907,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val lastName = createItem( key = "lastName", - label = translate(Res.strings.identity_last_name), + label = translate(Res.string.identity_last_name), initialValue = identity?.lastName, singleLine = true, lens = CreateRequest.identity.lastName, @@ -2917,7 +2921,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val address1 = createItem( key = "address1", - label = translate(Res.strings.address1), + label = translate(Res.string.address1), initialValue = identity?.address1, singleLine = true, lens = CreateRequest.identity.address1, @@ -2931,7 +2935,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val address2 = createItem( key = "address2", - label = translate(Res.strings.address2), + label = translate(Res.string.address2), initialValue = identity?.address2, singleLine = true, lens = CreateRequest.identity.address2, @@ -2945,7 +2949,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val address3 = createItem( key = "address3", - label = translate(Res.strings.address3), + label = translate(Res.string.address3), initialValue = identity?.address3, singleLine = true, lens = CreateRequest.identity.address3, @@ -2959,7 +2963,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val city = createItem( key = "city", - label = translate(Res.strings.city), + label = translate(Res.string.city), initialValue = identity?.city, singleLine = true, lens = CreateRequest.identity.city, @@ -2973,7 +2977,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val state = createItem( key = "state", - label = translate(Res.strings.state), + label = translate(Res.string.state), initialValue = identity?.state, singleLine = true, lens = CreateRequest.identity.state, @@ -2987,7 +2991,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val postalCode = createItem( key = "postalCode", - label = translate(Res.strings.postal_code), + label = translate(Res.string.postal_code), initialValue = identity?.postalCode, singleLine = true, lens = CreateRequest.identity.postalCode, @@ -3001,7 +3005,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val country = createItem( key = "country", - label = translate(Res.strings.country), + label = translate(Res.string.country), initialValue = identity?.country, singleLine = true, lens = CreateRequest.identity.country, @@ -3015,7 +3019,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val company = createItem( key = "company", - label = translate(Res.strings.company), + label = translate(Res.string.company), initialValue = identity?.company, singleLine = true, lens = CreateRequest.identity.company, @@ -3029,7 +3033,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val email = createItem( key = "email", - label = translate(Res.strings.email), + label = translate(Res.string.email), initialValue = args.autofill?.email ?: identity?.email, singleLine = true, keyboardOptions = KeyboardOptions( @@ -3047,7 +3051,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val phone = createItem( key = "phone", - label = translate(Res.strings.phone_number), + label = translate(Res.string.phone_number), initialValue = args.autofill?.phone ?: identity?.phone, singleLine = true, keyboardOptions = KeyboardOptions( @@ -3065,7 +3069,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val ssn = createItem( key = "ssn", - label = translate(Res.strings.ssn), + label = translate(Res.string.ssn), initialValue = identity?.ssn, singleLine = true, lens = CreateRequest.identity.ssn, @@ -3079,7 +3083,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val username = createItem( key = "username", - label = translate(Res.strings.username), + label = translate(Res.string.username), initialValue = args.autofill?.username ?: identity?.username, singleLine = true, lens = CreateRequest.identity.username, @@ -3093,7 +3097,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val passportNumber = createItem( key = "passportNumber", - label = translate(Res.strings.passport_number), + label = translate(Res.string.passport_number), initialValue = identity?.passportNumber, singleLine = true, keyboardOptions = KeyboardOptions( @@ -3110,7 +3114,7 @@ private suspend fun RememberStateFlowScope.produceIdentityState( ) val licenseNumber = createItem( key = "licenseNumber", - label = translate(Res.strings.license_number), + label = translate(Res.string.license_number), initialValue = identity?.licenseNumber, singleLine = true, lens = CreateRequest.identity.licenseNumber, @@ -3207,7 +3211,7 @@ private suspend fun RememberStateFlowScope.produceNoteState( val model = TextFieldModel2( state = state, text = value, - hint = translate(Res.strings.additem_note_placeholder), + hint = translate(Res.string.additem_note_placeholder), onChange = state::value::set, ) model diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collection/CollectionScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collection/CollectionScreen.kt index 3f8b0bcd..ba3ea9d2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collection/CollectionScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collection/CollectionScreen.kt @@ -17,11 +17,12 @@ import androidx.compose.ui.unit.dp import com.artemchep.keyguard.common.model.fold import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun CollectionScreen( @@ -60,7 +61,7 @@ fun CollectionScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsScreen.kt index 6a2470b5..e06b1450 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsScreen.kt @@ -27,6 +27,7 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevationSemi import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AhLayout import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -40,7 +41,7 @@ import com.artemchep.keyguard.ui.animatedNumberText import com.artemchep.keyguard.ui.skeleton.SkeletonItemPilled import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun CollectionsScreen( @@ -68,7 +69,7 @@ fun CollectionsScreenContent( title = { Column { Text( - text = stringResource(Res.strings.account), + text = stringResource(Res.string.account), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -76,7 +77,7 @@ fun CollectionsScreenContent( maxLines = 2, ) Text( - text = stringResource(Res.strings.collections), + text = stringResource(Res.string.collections), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -136,7 +137,7 @@ fun CollectionsScreenContent( EmptyView( text = { Text( - text = stringResource(Res.strings.collections_empty_label), + text = stringResource(Res.string.collections_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsStateProducer.kt index cc71219a..331e3d47 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/collections/CollectionsStateProducer.kt @@ -14,9 +14,12 @@ import com.artemchep.keyguard.common.usecase.GetCollections import com.artemchep.keyguard.common.usecase.GetOrganizations import com.artemchep.keyguard.feature.home.vault.VaultRoute import com.artemchep.keyguard.feature.home.vault.collection.CollectionRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -200,11 +203,11 @@ fun collectionsScreenState( if (ciphersCount > 0) { actions += FlatItemAction( icon = Icons.Outlined.KeyguardCipher, - title = translate(Res.strings.items), + title = Res.string.items.wrap(), trailing = { ChevronIcon() }, - onClick = { + onClick = onClick { val collections = selectedCollections.values .map { it.collection } val route = VaultRoute.by( @@ -254,8 +257,8 @@ fun collectionsScreenState( if (ciphers.isNotEmpty()) { this += FlatItemAction( icon = Icons.Outlined.KeyguardCipher, - title = translate(Res.strings.items), - onClick = { + title = Res.string.items.wrap(), + onClick = onClick { val route = VaultRoute.by( translator = this@produceScreenState, collection = collection, @@ -269,7 +272,7 @@ fun collectionsScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Info, - title = translate(Res.strings.info), + title = Res.string.info.wrap(), onClick = { val intent = NavigationIntent.NavigateToRoute( CollectionRoute( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/AddAccount.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/AddAccount.kt index 74c4cfc9..e050c98f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/AddAccount.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/AddAccount.kt @@ -9,9 +9,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.ChevronIcon -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AddAccountView( @@ -23,7 +24,7 @@ fun AddAccountView( elevation = 1.dp, title = { Text( - text = stringResource(Res.strings.account_main_add_account_title), + text = stringResource(Res.string.account_main_add_account_title), style = MaterialTheme.typography.titleMedium, ) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/SearchTextField.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/SearchTextField.kt index d8520964..ba542bbe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/SearchTextField.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/SearchTextField.kt @@ -43,12 +43,14 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.ExpandedIfNotEmptyForRow import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.PlainTextField import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.pluralStringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SearchTextField( @@ -152,7 +154,7 @@ fun SearchTextField( singleLine = true, ) if (count != null) { - val resultsCount = stringResource( + val resultsCount = pluralStringResource( Res.plurals.result_count_plural, count, count.toString(), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultListItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultListItem.kt index 3848fbb1..e1088049 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultListItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultListItem.kt @@ -75,6 +75,7 @@ import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBadgeIcon import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DisabledEmphasisAlpha @@ -94,9 +95,9 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.isDark import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList +import org.jetbrains.compose.resources.painterResource import kotlin.math.ln @Composable @@ -114,7 +115,7 @@ fun VaultListItem( }, text = { Text( - text = stringResource(Res.strings.vault_main_no_suggested_items), + text = stringResource(Res.string.vault_main_no_suggested_items), ) }, ) @@ -127,7 +128,7 @@ fun VaultListItem( }, text = { Text( - text = stringResource(Res.strings.items_empty_label), + text = stringResource(Res.string.items_empty_label), ) }, ) @@ -312,7 +313,7 @@ fun VaultListItemText( ) } else { Text( - text = stringResource(Res.strings.empty_value), + text = stringResource(Res.string.empty_value), color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha), overflow = TextOverflow.Ellipsis, @@ -588,7 +589,7 @@ private fun SmartBadge( .widthIn(max = 128.dp) .alignByBaseline(), text = title - ?: stringResource(Res.strings.empty_value), + ?: stringResource(Res.string.empty_value), color = if (title != null) { LocalContentColor.current } else { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewCardItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewCardItem.kt index 2eb498b6..7c59105d 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewCardItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewCardItem.kt @@ -29,12 +29,13 @@ import androidx.compose.ui.unit.sp import com.artemchep.keyguard.feature.auth.common.VisibilityToggle import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlin.math.roundToInt const val ObscureChar = '•' @@ -205,7 +206,7 @@ fun VaultViewCardItem( .width(8.dp), ) Text( - text = stringResource(Res.strings.card_number_empty_label), + text = stringResource(Res.string.card_number_empty_label), color = contentColor, style = MaterialTheme.typography.titleLarge, fontSize = 18.sp, @@ -226,12 +227,12 @@ fun VaultViewCardItem( ) Row { DateLabel( - label = stringResource(Res.strings.card_valid_from), + label = stringResource(Res.string.card_valid_from), month = item.data.fromMonth, year = item.data.fromYear, ) DateLabel( - label = stringResource(Res.strings.card_valid_to), + label = stringResource(Res.string.card_valid_to), month = item.data.expMonth, year = item.data.expYear, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewIdentityItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewIdentityItem.kt index bcec17d2..d2982b19 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewIdentityItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewIdentityItem.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem +import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha @@ -74,7 +75,7 @@ fun VaultViewIdentityItem( Icon(action.icon, null) } }, - title = action.title, + title = textResource(action.title), onClick = action.onClick, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactivePasskeyItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactivePasskeyItem.kt index eabc5183..09fea47b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactivePasskeyItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactivePasskeyItem.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent @@ -19,7 +20,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.info import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.theme.onInfoContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewInactivePasskeyItem( @@ -46,7 +47,7 @@ fun VaultViewInactivePasskeyItem( FlatItemTextContent( title = { Text( - stringResource(Res.strings.passkey_available), + stringResource(Res.string.passkey_available), style = MaterialTheme.typography.titleSmall, ) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactiveTotpItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactiveTotpItem.kt index 2f2ae5fc..60e86a13 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactiveTotpItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInactiveTotpItem.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemTextContent @@ -20,7 +21,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.onWarningContainer import com.artemchep.keyguard.ui.theme.warning import com.artemchep.keyguard.ui.theme.warningContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewInactiveTotpItem( @@ -47,7 +48,7 @@ fun VaultViewInactiveTotpItem( FlatItemTextContent( title = { Text( - text = stringResource(Res.strings.twofa_available), + text = stringResource(Res.string.twofa_available), style = MaterialTheme.typography.titleSmall, ) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInfoItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInfoItem.kt index 041c127d..f518ffc0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInfoItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewInfoItem.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -51,7 +52,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.info import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.theme.onInfoContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlin.math.ln @Composable @@ -226,7 +227,7 @@ private fun LearnButton( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.learn_more), + text = stringResource(Res.string.learn_more), style = MaterialTheme.typography.labelLarge, color = color, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewNoteItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewNoteItem.kt index 99c40b44..5fd5872a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewNoteItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewNoteItem.kt @@ -14,12 +14,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.icons.VisibilityIcon import com.artemchep.keyguard.ui.markdown.MarkdownText import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewNoteItem( @@ -43,9 +44,9 @@ fun VaultViewNoteItem( }, title = { val text = if (visibilityState.value) { - stringResource(Res.strings.hide_secure_note) + stringResource(Res.string.hide_secure_note) } else { - stringResource(Res.strings.reveal_secure_note) + stringResource(Res.string.reveal_secure_note) } Text( text = text, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewPasskeyItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewPasskeyItem.kt index 480a976c..44c58878 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewPasskeyItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewPasskeyItem.kt @@ -23,12 +23,13 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewPasskeyItem( @@ -93,7 +94,7 @@ fun VaultViewPasskeyItem( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.passkey_use_short), + text = stringResource(Res.string.passkey_use_short), textAlign = TextAlign.Center, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewReusedPasswordItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewReusedPasswordItem.kt index db5482d8..0f2f145b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewReusedPasswordItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewReusedPasswordItem.kt @@ -11,12 +11,13 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewReusedPasswordItem( @@ -43,7 +44,7 @@ fun VaultViewReusedPasswordItem( FlatItemTextContent( title = { Text( - stringResource(Res.strings.reused_password), + stringResource(Res.string.reused_password), style = MaterialTheme.typography.titleSmall, ) }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewValueItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewValueItem.kt index 59a0843b..c98c5712 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewValueItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/component/VaultViewValueItem.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.auth.common.VisibilityToggle import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatDropdown import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -36,7 +37,7 @@ import com.artemchep.keyguard.ui.animatedConcealedText import com.artemchep.keyguard.ui.colorizePassword import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.MutableSharedFlow @OptIn(ExperimentalLayoutApi::class) @@ -97,7 +98,7 @@ fun VaultViewValueItem( modifier = Modifier .animateContentSize() .alpha(MediumEmphasisAlpha), - text = stringResource(Res.strings.empty_value), + text = stringResource(Res.string.empty_value), fontFamily = if (item.monospace) monoFontFamily else null, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersScreen.kt index 42d22288..de146641 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersScreen.kt @@ -31,6 +31,7 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevationSemi import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AhLayout import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -45,7 +46,7 @@ import com.artemchep.keyguard.ui.icons.OfflineIcon import com.artemchep.keyguard.ui.skeleton.SkeletonItemPilled import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun FoldersScreen( @@ -74,7 +75,7 @@ fun FoldersScreenContent( title = { Column { Text( - text = stringResource(Res.strings.account), + text = stringResource(Res.string.account), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -82,7 +83,7 @@ fun FoldersScreenContent( maxLines = 2, ) Text( - text = stringResource(Res.strings.folders), + text = stringResource(Res.string.folders), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -117,7 +118,7 @@ fun FoldersScreenContent( }, text = { Text( - text = stringResource(Res.strings.folder_new), + text = stringResource(Res.string.folder_new), ) }, ) @@ -147,7 +148,7 @@ fun FoldersScreenContent( }, text = { Text( - text = stringResource(Res.strings.folders_empty_label), + text = stringResource(Res.string.folders_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersStateProducer.kt index 1b02e3ab..0476c6fa 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/folders/FoldersStateProducer.kt @@ -25,12 +25,16 @@ import com.artemchep.keyguard.feature.confirmation.ConfirmationResult import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent import com.artemchep.keyguard.feature.home.vault.VaultRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.provider.bitwarden.usecase.util.canDelete import com.artemchep.keyguard.provider.bitwarden.usecase.util.canEdit import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -177,7 +181,7 @@ fun foldersScreenState( navigate(intent) } - fun onRename( + suspend fun onRename( folders: List, ) { val route = registerRouteResultReceiver( @@ -185,9 +189,9 @@ fun foldersScreenState( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.Edit), title = if (folders.size > 1) { - translate(Res.strings.folder_action_change_names_title) + translate(Res.string.folder_action_change_names_title) } else { - translate(Res.strings.folder_action_change_name_title) + translate(Res.string.folder_action_change_name_title) }, items = folders .sortedWith(StringComparatorIgnoreCase { it.name }) @@ -250,7 +254,7 @@ fun foldersScreenState( navigate(intent) } - fun onDelete( + suspend fun onDelete( folderIds: Set, /** * `true` if any of the folders contain ciphers in it, @@ -262,7 +266,7 @@ fun foldersScreenState( val cascadeRemoveItem = if (hasCiphers) { ConfirmationRoute.Args.Item.BooleanItem( key = cascadeRemoveKey, - title = translate(Res.strings.ciphers_action_cascade_trash_associated_items_title), + title = translate(Res.string.ciphers_action_cascade_trash_associated_items_title), ) } else { null @@ -273,11 +277,11 @@ fun foldersScreenState( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.Delete), title = if (folderIds.size > 1) { - translate(Res.strings.folder_delete_many_confirmation_title) + translate(Res.string.folder_delete_many_confirmation_title) } else { - translate(Res.strings.folder_delete_one_confirmation_title) + translate(Res.string.folder_delete_one_confirmation_title) }, - message = translate(Res.strings.folder_delete_confirmation_text), + message = translate(Res.string.folder_delete_confirmation_text), items = listOfNotNull( cascadeRemoveItem, ), @@ -340,11 +344,11 @@ fun foldersScreenState( if (ciphersCount > 0) { this += FlatItemAction( icon = Icons.Outlined.KeyguardCipher, - title = translate(Res.strings.items), + title = Res.string.items.wrap(), trailing = { ChevronIcon() }, - onClick = { + onClick = onClick { val folders = selectedFolders.values .map { it.folder } val route = VaultRoute.by( @@ -361,8 +365,8 @@ fun foldersScreenState( if (canEdit) { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.rename), - onClick = { + title = Res.string.rename.wrap(), + onClick = onClick { val folders = selectedFolders.values .map { it.folder } onRename(folders) @@ -377,7 +381,7 @@ fun foldersScreenState( selectedFolders.values.maxBy { it.ciphers.size }.folder.name this += FlatItemAction( icon = Icons.Outlined.Merge, - title = "Merge into…", + title = TextHolder.Value("Merge into…"), onClick = ::onMerge .partially1(folderName) .partially1(selectedFolderIds), @@ -389,10 +393,10 @@ fun foldersScreenState( val hasCiphers = selectedFolders.any { it.value.ciphers.isNotEmpty() } this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = ::onDelete - .partially1(selectedFolderIds) - .partially1(hasCiphers), + title = Res.string.delete.wrap(), + onClick = onClick { + onDelete(selectedFolderIds, hasCiphers) + }, ) } } @@ -431,11 +435,11 @@ fun foldersScreenState( if (!folder.deleted && ciphers.isNotEmpty()) { this += FlatItemAction( icon = Icons.Outlined.KeyguardCipher, - title = translate(Res.strings.items), + title = Res.string.items.wrap(), trailing = { ChevronIcon() }, - onClick = { + onClick = onClick { val route = VaultRoute.by( translator = this@produceScreenState, folder = folder, @@ -450,18 +454,24 @@ fun foldersScreenState( if (!folder.deleted && canEdit) { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.rename), - onClick = ::onRename - .partially1(listOf(folder)), + title = Res.string.rename.wrap(), + onClick = onClick { + onRename( + folders = listOf(folder), + ) + }, ) } if (!folder.deleted && canDelete) { this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = ::onDelete - .partially1(setOf(folder.id)) - .partially1(folderWithCiphers.ciphers.isNotEmpty()), + title = Res.string.delete.wrap(), + onClick = onClick { + onDelete( + folderIds = setOf(folder.id), + hasCiphers = folderWithCiphers.ciphers.isNotEmpty(), + ) + }, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/model/VaultItemIcon.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/model/VaultItemIcon.kt index 9254fae0..462d5a9a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/model/VaultItemIcon.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/model/VaultItemIcon.kt @@ -2,11 +2,10 @@ package com.artemchep.keyguard.feature.home.vault.model import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.vector.ImageVector -import com.artemchep.keyguard.common.util.asCodePointsSequence import com.artemchep.keyguard.common.util.nextSymbol import com.artemchep.keyguard.feature.favicon.AppIconUrl import com.artemchep.keyguard.feature.favicon.FaviconUrl -import dev.icerock.moko.resources.ImageResource +import org.jetbrains.compose.resources.DrawableResource @Immutable sealed interface VaultItemIcon { @@ -29,7 +28,7 @@ sealed interface VaultItemIcon { @Immutable data class ImageIcon( - val imageRes: ImageResource, + val imageRes: DrawableResource, ) : VaultItemIcon @Immutable diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organization/OrganizationScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organization/OrganizationScreen.kt index f555ab6a..89e6af2f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organization/OrganizationScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organization/OrganizationScreen.kt @@ -17,11 +17,12 @@ import androidx.compose.ui.unit.dp import com.artemchep.keyguard.common.model.fold import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun OrganizationScreen( @@ -60,7 +61,7 @@ fun OrganizationScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsScreen.kt index eb050203..aee19a61 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsScreen.kt @@ -28,6 +28,7 @@ import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.feature.EmptyView import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AhLayout import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -42,7 +43,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItemPilled import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.isDark import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun FoldersScreen( @@ -71,7 +72,7 @@ fun FoldersScreenContent( title = { Column { Text( - text = stringResource(Res.strings.account), + text = stringResource(Res.string.account), style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -79,7 +80,7 @@ fun FoldersScreenContent( maxLines = 2, ) Text( - text = stringResource(Res.strings.organizations), + text = stringResource(Res.string.organizations), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -139,7 +140,7 @@ fun FoldersScreenContent( EmptyView( text = { Text( - text = stringResource(Res.strings.organizations_empty_label), + text = stringResource(Res.string.organizations_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsStateProducer.kt index ea786fb0..f032685b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/organizations/OrganizationsStateProducer.kt @@ -16,9 +16,12 @@ import com.artemchep.keyguard.common.usecase.GetOrganizations import com.artemchep.keyguard.feature.home.vault.VaultRoute import com.artemchep.keyguard.feature.home.vault.collections.CollectionsRoute import com.artemchep.keyguard.feature.home.vault.organization.OrganizationRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -176,11 +179,11 @@ fun organizationsScreenState( if (ciphers.isNotEmpty()) { this += FlatItemAction( icon = Icons.Outlined.KeyguardCipher, - title = translate(Res.strings.items), + title = Res.string.items.wrap(), trailing = { ChevronIcon() }, - onClick = { + onClick = onClick { val route = VaultRoute.by( translator = this@produceScreenState, organization = organization, @@ -195,7 +198,7 @@ fun organizationsScreenState( if (collections.isNotEmpty()) { this += FlatItemAction( icon = Icons.Outlined.KeyguardCollection, - title = translate(Res.strings.collections), + title = Res.string.collections.wrap(), trailing = { ChevronIcon() }, @@ -216,7 +219,7 @@ fun organizationsScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Info, - title = translate(Res.strings.info), + title = Res.string.info.wrap(), onClick = { val intent = NavigationIntent.NavigateToRoute( OrganizationRoute( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListFilter.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListFilter.kt index 7785d67c..970b94c1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListFilter.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListFilter.kt @@ -46,6 +46,7 @@ import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.AccentColors import com.artemchep.keyguard.ui.icons.IconBox import com.artemchep.keyguard.ui.icons.KeyguardAttachment @@ -98,31 +99,31 @@ enum class FilterSection( ) { CUSTOM( id = "custom", - title = TextHolder.Res(Res.strings.custom), + title = TextHolder.Res(Res.string.custom), ), ACCOUNT( id = "account", - title = TextHolder.Res(Res.strings.account), + title = TextHolder.Res(Res.string.account), ), ORGANIZATION( id = "organization", - title = TextHolder.Res(Res.strings.organization), + title = TextHolder.Res(Res.string.organization), ), TYPE( id = "type", - title = TextHolder.Res(Res.strings.type), + title = TextHolder.Res(Res.string.type), ), FOLDER( id = "folder", - title = TextHolder.Res(Res.strings.folder), + title = TextHolder.Res(Res.string.folder), ), COLLECTION( id = "collection", - title = TextHolder.Res(Res.strings.collection), + title = TextHolder.Res(Res.string.collection), ), MISC( id = "misc", - title = TextHolder.Res(Res.strings.misc), + title = TextHolder.Res(Res.string.misc), ), } @@ -152,23 +153,25 @@ suspend fun RememberStateFlowScope.createFilter( filterSink.value = emptyState } val onSave = { state: Map> -> - val intent = createConfirmationDialogIntent( - item = ConfirmationRoute.Args.Item.StringItem( - key = "name", - title = translate(Res.strings.generic_name), - canBeEmpty = false, - ), - icon = icon(Icons.Outlined.KeyguardCipherFilter, Icons.Outlined.Add), - title = translate(Res.strings.customfilters_add_filter_title), - ) { name -> - val request = AddCipherFilterRequest( - name = name, - filter = state, - ) - addCipherFilter(request) - .launchIn(appScope) + action { + val intent = createConfirmationDialogIntent( + item = ConfirmationRoute.Args.Item.StringItem( + key = "name", + title = translate(Res.string.generic_name), + canBeEmpty = false, + ), + icon = icon(Icons.Outlined.KeyguardCipherFilter, Icons.Outlined.Add), + title = translate(Res.string.customfilters_add_filter_title), + ) { name -> + val request = AddCipherFilterRequest( + name = name, + filter = state, + ) + addCipherFilter(request) + .launchIn(appScope) + } + navigate(intent) } - navigate(intent) } val onToggle = { sectionId: String, filters: Set -> filterSink.update { holder -> @@ -468,7 +471,7 @@ suspend fun < icon = icon, ) - fun createTypeFilterAction( + suspend fun createTypeFilterAction( type: DSecret.Type, sectionId: String = FilterSection.TYPE.id, ) = createFilterAction( @@ -650,7 +653,7 @@ suspend fun < .toList() + createFolderFilterAction( folderIds = setOfNull, - title = translate(Res.strings.folder_none), + title = translate(Res.string.folder_none), icon = Icons.Outlined.FolderOff, fill = false, indent = 0, @@ -696,7 +699,7 @@ suspend fun < .toList() + createCollectionFilterAction( collectionIds = setOfNull, - title = translate(Res.strings.collection_none), + title = translate(Res.string.collection_none), ) } .combine(filterCollectionsWithCiphers) { items, collectionIds -> @@ -739,7 +742,7 @@ suspend fun < .toList() + createOrganizationFilterAction( organizationIds = setOfNull, - title = translate(Res.strings.organization_none), + title = translate(Res.string.organization_none), ) } .combine(filterOrganizationsWithCiphers) { items, organizationIds -> @@ -794,7 +797,7 @@ suspend fun < DFilter.ByReprompt(reprompt = true), ), filterSectionId = "${FilterSection.MISC.id}.reprompt", - title = translate(Res.strings.filter_auth_reprompt_items), + title = translate(Res.string.filter_auth_reprompt_items), icon = Icons.Outlined.KeyguardAuthReprompt, ), createFilterAction( @@ -803,7 +806,7 @@ suspend fun < DFilter.BySync(synced = false), ), filterSectionId = "${FilterSection.MISC.id}.sync", - title = translate(Res.strings.filter_pending_items), + title = translate(Res.string.filter_pending_items), icon = Icons.Outlined.KeyguardPendingSyncItems, ), createFilterAction( @@ -812,7 +815,7 @@ suspend fun < DFilter.ByError(error = true), ), filterSectionId = "${FilterSection.MISC.id}.error", - title = translate(Res.strings.filter_failed_items), + title = translate(Res.string.filter_failed_items), icon = Icons.Outlined.KeyguardFailedItems, ), createFilterAction( @@ -821,7 +824,7 @@ suspend fun < DFilter.ByIgnoredAlerts, ), filterSectionId = "${FilterSection.MISC.id}.watchtower_alerts", - title = translate(Res.strings.ignored_alerts), + title = translate(Res.string.ignored_alerts), icon = Icons.Outlined.KeyguardIgnoredAlerts, ), ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListItemMapping.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListItemMapping.kt index c45a0d58..c0b60de5 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListItemMapping.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListItemMapping.kt @@ -23,8 +23,10 @@ import com.artemchep.keyguard.feature.home.vault.component.obscureCardNumber import com.artemchep.keyguard.feature.home.vault.model.VaultItem2 import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.concealedText import kotlinx.collections.immutable.toImmutableList @@ -214,18 +216,18 @@ private suspend fun DSecret.createLogin( ): TypeSpecific { val actions = listOfNotNull( copy.FlatItemAction( - title = translator.translate(Res.strings.copy_username), + title = Res.string.copy_username.wrap(), value = login?.username, ), copy.FlatItemAction( - title = translator.translate(Res.strings.copy_password), + title = Res.string.copy_password.wrap(), value = login?.password, hidden = concealFields, ), login?.totp?.run { FlatItemAction( icon = Icons.Outlined.ContentCopy, - title = translator.translate(Res.strings.copy_otp_code), + title = Res.string.copy_otp_code.wrap(), trailing = { Row { VaultViewTotpBadge( @@ -265,12 +267,12 @@ private fun DSecret.createCard( ): TypeSpecific { val actions = listOfNotNull( copy.FlatItemAction( - title = translator.translate(Res.strings.copy_card_number), + title = Res.string.copy_card_number.wrap(), value = card?.number, hidden = concealFields, ), copy.FlatItemAction( - title = translator.translate(Res.strings.copy_cvv_code), + title = Res.string.copy_cvv_code.wrap(), value = card?.code, hidden = concealFields, ), @@ -292,20 +294,20 @@ private fun DSecret.createIdentity( ): TypeSpecific { val actions = listOfNotNull( copy.FlatItemAction( - title = translator.translate(Res.strings.copy_phone_number), + title = Res.string.copy_phone_number.wrap(), value = identity?.phone, ), copy.FlatItemAction( - title = translator.translate(Res.strings.copy_email), + title = Res.string.copy_email.wrap(), value = identity?.email, ), copy.FlatItemAction( - title = translator.translate(Res.strings.copy_passport_number), + title = Res.string.copy_passport_number.wrap(), value = identity?.passportNumber, hidden = concealFields, ), copy.FlatItemAction( - title = translator.translate(Res.strings.copy_license_number), + title = Res.string.copy_license_number.wrap(), value = identity?.licenseNumber, hidden = concealFields, ), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListScreen.kt index ce8dc444..82a1e470 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListScreen.kt @@ -67,6 +67,7 @@ import com.artemchep.keyguard.feature.search.filter.component.FilterItemComposab import com.artemchep.keyguard.feature.search.sort.SortButton import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.CollectedEffect import com.artemchep.keyguard.ui.Compose import com.artemchep.keyguard.ui.DefaultFab @@ -92,7 +93,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomSearchbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first @@ -173,7 +174,7 @@ fun VaultListScreen( searchFieldModifier = Modifier .focusRequester2(focusRequester), searchFieldModel = state.query, - searchFieldPlaceholder = stringResource(Res.strings.vault_main_search_placeholder), + searchFieldPlaceholder = stringResource(Res.string.vault_main_search_placeholder), title = args.appBar?.title, subtitle = args.appBar?.subtitle, icon = { @@ -374,7 +375,7 @@ fun VaultHomeScreenListPane( searchFieldModifier = Modifier .focusRequester2(focusRequester), searchFieldModel = state.query, - searchFieldPlaceholder = stringResource(Res.strings.vault_main_search_placeholder), + searchFieldPlaceholder = stringResource(Res.string.vault_main_search_placeholder), title = title, subtitle = subtitle, icon = { @@ -475,7 +476,7 @@ fun VaultHomeScreenListPane( }, text = { Text( - text = stringResource(Res.strings.vault_main_new_item_button), + text = stringResource(Res.string.vault_main_new_item_button), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt index 5f700724..d920b314 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt @@ -97,10 +97,12 @@ import com.artemchep.keyguard.feature.home.vault.search.sort.PasswordStrengthSor import com.artemchep.keyguard.feature.home.vault.search.sort.Sort import com.artemchep.keyguard.feature.home.vault.util.AlphabeticalSortMinItemsSize import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.passkeys.PasskeysCredentialViewRoute import com.artemchep.keyguard.feature.search.search.SEARCH_DEBOUNCE @@ -108,6 +110,7 @@ import com.artemchep.keyguard.leof import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.buildContextItems import com.artemchep.keyguard.ui.icons.ChevronIcon @@ -115,7 +118,7 @@ import com.artemchep.keyguard.ui.icons.SyncIcon import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.icons.iconSmall import com.artemchep.keyguard.ui.selection.selectionHandle -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -281,15 +284,15 @@ fun vaultListScreenState( fun onRename( folders: List, - ) { + ) = action { val route = registerRouteResultReceiver( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.Edit), title = if (folders.size > 1) { - translate(Res.strings.folder_action_change_names_title) + translate(Res.string.folder_action_change_names_title) } else { - translate(Res.strings.folder_action_change_name_title) + translate(Res.string.folder_action_change_name_title) }, items = folders .sortedWith(StringComparatorIgnoreCase { it.name }) @@ -395,16 +398,16 @@ fun vaultListScreenState( leading = { Icon(Icons.Outlined.Delete, null) }, - title = translate(Res.strings.trash), + title = Res.string.trash.wrap(), trailing = { ChevronIcon() }, - onClick = { + onClick = onClick { val newArgs = args.copy( appBar = VaultRoute.Args.AppBar( subtitle = args.appBar?.subtitle - ?: translate(Res.strings.home_vault_label), - title = translate(Res.strings.trash), + ?: translate(Res.string.home_vault_label), + title = translate(Res.string.trash), ), trash = true, preselect = false, @@ -420,7 +423,7 @@ fun vaultListScreenState( leading = { Icon(Icons.Outlined.Download, null) }, - title = translate(Res.strings.downloads), + title = Res.string.downloads.wrap(), trailing = { ChevronIcon() }, @@ -463,7 +466,7 @@ fun vaultListScreenState( onCheckedChange = showKeyboardSink::value::set, ) }, - title = translate(Res.strings.vault_action_always_show_keyboard_title), + title = Res.string.vault_action_always_show_keyboard_title.wrap(), onClick = showKeyboardSink::value::set.partially1(!showKeyboard), ) } @@ -484,7 +487,7 @@ fun vaultListScreenState( rotating = syncing, ) }, - title = translate(Res.strings.vault_action_sync_vault_title), + title = Res.string.vault_action_sync_vault_title.wrap(), onClick = if (!syncing) { // lambda { @@ -500,7 +503,7 @@ fun vaultListScreenState( leading = { Icon(Icons.Outlined.Lock, null) }, - title = translate(Res.strings.vault_action_lock_vault_title), + title = Res.string.vault_action_lock_vault_title.wrap(), onClick = { clearVaultSession() .launchIn(appScope) @@ -525,7 +528,7 @@ fun vaultListScreenState( leading = { Icon(Icons.Outlined.Edit, null) }, - title = translate(Res.strings.vault_action_rename_folder_title), + title = Res.string.vault_action_rename_folder_title.wrap(), onClick = { onRename(listOf(folder)) }, @@ -704,7 +707,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.AutoAwesome, - title = translate(Res.strings.autofill), + title = Res.string.autofill.wrap(), onClick = { val extra = AppMode.Pick.Extra() mode.onAutofill(secret, extra) @@ -716,7 +719,7 @@ fun vaultListScreenState( Icons.Outlined.AutoAwesome, Icons.Outlined.Save, ), - title = translate(Res.strings.autofill_and_save_uri), + title = Res.string.autofill_and_save_uri.wrap(), onClick = { val extra = AppMode.Pick.Extra( forceAddUri = true, @@ -734,7 +737,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Info, - title = translate(Res.strings.ciphers_view_details), + title = Res.string.ciphers_view_details.wrap(), trailing = { ChevronIcon() }, @@ -749,7 +752,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Save, - title = translate(Res.strings.ciphers_save_to), + title = Res.string.ciphers_save_to.wrap(), onClick = { val route = LeAddRoute( args = AddRoute.Args( @@ -771,7 +774,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Info, - title = translate(Res.strings.ciphers_view_details), + title = Res.string.ciphers_view_details.wrap(), trailing = { ChevronIcon() }, @@ -786,7 +789,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Save, - title = translate(Res.strings.ciphers_save_to), + title = Res.string.ciphers_save_to.wrap(), onClick = { mode.onComplete(secret) }, @@ -795,7 +798,7 @@ fun vaultListScreenState( section { this += FlatItemAction( icon = Icons.Outlined.Info, - title = translate(Res.strings.ciphers_view_details), + title = Res.string.ciphers_view_details.wrap(), trailing = { ChevronIcon() }, @@ -1036,7 +1039,7 @@ fun vaultListScreenState( item = createComparatorAction( id = "title", icon = Icons.Outlined.SortByAlpha, - title = Res.strings.sortby_title_title, + title = Res.string.sortby_title_title, config = ComparatorHolder( comparator = AlphabeticalSort, favourites = true, @@ -1045,7 +1048,7 @@ fun vaultListScreenState( subItems = listOf( createComparatorAction( id = "title_normal", - title = Res.strings.sortby_title_normal_mode, + title = Res.string.sortby_title_normal_mode, config = ComparatorHolder( comparator = AlphabeticalSort, favourites = true, @@ -1053,7 +1056,7 @@ fun vaultListScreenState( ), createComparatorAction( id = "title_rev", - title = Res.strings.sortby_title_reverse_mode, + title = Res.string.sortby_title_reverse_mode, config = ComparatorHolder( comparator = AlphabeticalSort, reversed = true, @@ -1066,7 +1069,7 @@ fun vaultListScreenState( item = createComparatorAction( id = "modify_date", icon = Icons.Outlined.CalendarMonth, - title = Res.strings.sortby_modification_date_title, + title = Res.string.sortby_modification_date_title, config = ComparatorHolder( comparator = LastModifiedSort, ), @@ -1074,14 +1077,14 @@ fun vaultListScreenState( subItems = listOf( createComparatorAction( id = "modify_date_normal", - title = Res.strings.sortby_modification_date_normal_mode, + title = Res.string.sortby_modification_date_normal_mode, config = ComparatorHolder( comparator = LastModifiedSort, ), ), createComparatorAction( id = "modify_date_rev", - title = Res.strings.sortby_modification_date_reverse_mode, + title = Res.string.sortby_modification_date_reverse_mode, config = ComparatorHolder( comparator = LastModifiedSort, reversed = true, @@ -1093,7 +1096,7 @@ fun vaultListScreenState( item = createComparatorAction( id = "password", icon = Icons.Outlined.Password, - title = Res.strings.sortby_password_title, + title = Res.string.sortby_password_title, config = ComparatorHolder( comparator = PasswordSort, ), @@ -1101,14 +1104,14 @@ fun vaultListScreenState( subItems = listOf( createComparatorAction( id = "password_normal", - title = Res.strings.sortby_password_normal_mode, + title = Res.string.sortby_password_normal_mode, config = ComparatorHolder( comparator = PasswordSort, ), ), createComparatorAction( id = "password_rev", - title = Res.strings.sortby_password_reverse_mode, + title = Res.string.sortby_password_reverse_mode, config = ComparatorHolder( comparator = PasswordSort, reversed = true, @@ -1120,7 +1123,7 @@ fun vaultListScreenState( item = createComparatorAction( id = "password_last_modified_strength", icon = Icons.Outlined.CalendarMonth, - title = Res.strings.sortby_password_modification_date_title, + title = Res.string.sortby_password_modification_date_title, config = ComparatorHolder( comparator = PasswordLastModifiedSort, ), @@ -1128,14 +1131,14 @@ fun vaultListScreenState( subItems = listOf( createComparatorAction( id = "password_last_modified_normal", - title = Res.strings.sortby_password_modification_date_normal_mode, + title = Res.string.sortby_password_modification_date_normal_mode, config = ComparatorHolder( comparator = PasswordLastModifiedSort, ), ), createComparatorAction( id = "password_last_modified_rev", - title = Res.strings.sortby_password_modification_date_reverse_mode, + title = Res.string.sortby_password_modification_date_reverse_mode, config = ComparatorHolder( comparator = PasswordLastModifiedSort, reversed = true, @@ -1147,7 +1150,7 @@ fun vaultListScreenState( item = createComparatorAction( id = "password_strength", icon = Icons.Outlined.Security, - title = Res.strings.sortby_password_strength_title, + title = Res.string.sortby_password_strength_title, config = ComparatorHolder( comparator = PasswordStrengthSort, ), @@ -1155,14 +1158,14 @@ fun vaultListScreenState( subItems = listOf( createComparatorAction( id = "password_strength_normal", - title = Res.strings.sortby_password_strength_normal_mode, + title = Res.string.sortby_password_strength_normal_mode, config = ComparatorHolder( comparator = PasswordStrengthSort, ), ), createComparatorAction( id = "password_strength_rev", - title = Res.strings.sortby_password_strength_reverse_mode, + title = Res.string.sortby_password_strength_reverse_mode, config = ComparatorHolder( comparator = PasswordStrengthSort, reversed = true, @@ -1191,7 +1194,7 @@ fun vaultListScreenState( if (subItems.isNotEmpty()) { out += SortItem.Section( id = "sub_items_section", - text = TextHolder.Res(Res.strings.options), + text = TextHolder.Res(Res.string.options), ) out += subItems } @@ -1458,7 +1461,7 @@ fun vaultListScreenState( type: DSecret.Type, ) = FlatItemAction( leading = icon(type.iconImageVector()), - title = translate(type.titleH()), + title = type.titleH().wrap(), onClick = { val autofill = when (mode) { is AppMode.Main -> null @@ -1808,35 +1811,37 @@ private fun hahah( else -> ItemDecoratorNone } - val items = sequence { + val items = run { + val out = mutableListOf() if (state.preferredList != null) { // We want to show the 'No suggestions' text if the suggestions // target does exist, but searching for suggestions returns no // items. if (state.preferredList.isEmpty()) { - yield(VaultItem2.NoSuggestions) + out += VaultItem2.NoSuggestions } state.preferredList.forEach { item -> - yield(item) + out += item } // A section item for all items. if (state.list.isNotEmpty()) { val section = VaultItem2.Section( id = "preferred.end", - text = TextHolder.Res(Res.strings.items_all), + text = TextHolder.Res(Res.string.items_all), ) - yield(section) + out += section } } state.list.forEach { item -> if (!item.favourite || orderConfig?.favourites != true) { val section = decorator.getOrNull(item) - if (section != null) yield(section) + if (section != null) out += section } - yield(item) + out += item } - }.toList().ifEmpty { + out + }.ifEmpty { listOf(VaultItem2.NoItems) } FilteredBoo( @@ -1858,7 +1863,7 @@ private class PasswordDecorator : Decorator { */ private var lastPassword: Any? = Any() - override fun getOrNull(item: VaultItem2.Item): VaultItem2? { + override suspend fun getOrNull(item: VaultItem2.Item): VaultItem2? { val pw = item.password if (pw == lastPassword) { return null @@ -1887,7 +1892,7 @@ private class PasswordStrengthDecorator : Decorator { */ private var lastScore: Any? = Any() - override fun getOrNull(item: VaultItem2.Item): VaultItem2? { + override suspend fun getOrNull(item: VaultItem2.Item): VaultItem2? { val score = item.score?.score if (score == lastScore) { return null diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryScreen.kt index 5ddd2ef9..c9bee1fc 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryScreen.kt @@ -19,6 +19,7 @@ import com.artemchep.keyguard.feature.home.vault.component.VaultPasswordHistoryI import com.artemchep.keyguard.feature.home.vault.model.VaultPasswordHistoryItem import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultSelection import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.OptionsButton @@ -27,7 +28,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList private const val SKELETON_ITEMS_COUNT = 2 @@ -163,7 +164,7 @@ private fun ToolbarTitle( } } Text( - text = stringResource(Res.strings.passwordhistory_header_title), + text = stringResource(Res.string.passwordhistory_header_title), style = MaterialTheme.typography.titleMedium, overflow = TextOverflow.Ellipsis, maxLines = 1, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryStateProducer.kt index 93cd649f..7fe3406c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewPasswordHistoryStateProducer.kt @@ -17,10 +17,13 @@ import com.artemchep.keyguard.common.usecase.GetCiphers import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent import com.artemchep.keyguard.feature.home.vault.model.VaultPasswordHistoryItem import com.artemchep.keyguard.feature.largetype.LargeTypeRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.passwordleak.PasswordLeakRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ContextItem import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection @@ -116,13 +119,13 @@ fun vaultViewPasswordHistoryScreenState( .onEach { ids -> selectionHandle.setSelection(ids) } .launchIn(screenScope) - fun onDeleteByItems( + suspend fun onDeleteByItems( items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.passwordhistory_delete_many_confirmation_title) + translate(Res.string.passwordhistory_delete_many_confirmation_title) } else { - translate(Res.strings.passwordhistory_delete_one_confirmation_title) + translate(Res.string.passwordhistory_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.password } @@ -141,11 +144,11 @@ fun vaultViewPasswordHistoryScreenState( navigate(intent) } - fun onDeleteAll() { + suspend fun onDeleteAll() { val intent = createConfirmationDialogIntent( icon = icon(Icons.Outlined.Delete), - title = translate(Res.strings.passwordhistory_clear_history_confirmation_title), - message = translate(Res.strings.passwordhistory_clear_history_confirmation_text), + title = translate(Res.string.passwordhistory_clear_history_confirmation_title), + message = translate(Res.string.passwordhistory_clear_history_confirmation_text), ) { cipherRemovePasswordHistory( itemId, @@ -171,9 +174,10 @@ fun vaultViewPasswordHistoryScreenState( section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.remove_from_history), - onClick = ::onDeleteByItems - .partially1(selectedItems), + title = Res.string.remove_from_history.wrap(), + onClick = onClick { + onDeleteByItems(selectedItems) + }, ) } } @@ -207,7 +211,7 @@ fun vaultViewPasswordHistoryScreenState( actions = buildContextItems { section { this += copyFactory.FlatItemAction( - title = translate(Res.strings.copy_password), + title = Res.string.copy_password.wrap(), value = password.password, type = CopyText.Type.PASSWORD, ) @@ -216,9 +220,10 @@ fun vaultViewPasswordHistoryScreenState( ) this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.remove_from_history), - onClick = ::onDeleteByItems - .partially1(items), + title = Res.string.remove_from_history.wrap(), + onClick = onClick { + onDeleteByItems(items) + }, ) } section { @@ -274,8 +279,10 @@ fun vaultViewPasswordHistoryScreenState( persistentListOf( FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.passwordhistory_clear_history_title), - onClick = ::onDeleteAll, + title = Res.string.passwordhistory_clear_history_title.wrap(), + onClick = onClick { + onDeleteAll() + }, ), ), ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewScreen.kt index 2944ccc7..97a75136 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewScreen.kt @@ -49,8 +49,10 @@ import com.artemchep.keyguard.feature.home.vault.component.VaultViewItem import com.artemchep.keyguard.feature.home.vault.component.rememberSecretAccentColor import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevationSemi import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon +import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Avatar import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DisabledEmphasisAlpha @@ -68,7 +70,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.text.AutoSizeText import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultViewScreen( @@ -149,7 +151,7 @@ fun VaultViewScreenContent( }, text = { Text( - text = action.title, + text = textResource(action.title), ) }, ) @@ -330,7 +332,7 @@ private fun VaultViewTitle( ) } else { Text( - text = stringResource(Res.strings.empty_value), + text = stringResource(Res.string.empty_value), color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha), maxLines = 1, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewStateProducer.kt index ad00c6ec..8767f2f1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultViewStateProducer.kt @@ -164,9 +164,12 @@ import com.artemchep.keyguard.feature.justdeleteme.directory.JustDeleteMeService import com.artemchep.keyguard.feature.justgetdata.directory.JustGetMyDataViewDialogRoute import com.artemchep.keyguard.feature.largetype.LargeTypeRoute import com.artemchep.keyguard.feature.loading.getErrorReadableMessage +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.copy +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.passkeys.PasskeysCredentialViewRoute import com.artemchep.keyguard.feature.passkeys.directory.PasskeysServiceViewDialogRoute @@ -177,6 +180,7 @@ import com.artemchep.keyguard.feature.tfa.directory.TwoFaServiceViewDialogRoute import com.artemchep.keyguard.feature.websiteleak.WebsiteLeakRoute import com.artemchep.keyguard.platform.util.isRelease import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ContextItem import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -211,6 +215,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.toList import kotlinx.datetime.Clock +import org.jetbrains.compose.resources.stringResource import org.kodein.di.allInstances import org.kodein.di.compose.localDI import org.kodein.di.direct @@ -597,7 +602,7 @@ fun vaultViewScreenState( is AppMode.Main -> null is AppMode.Pick -> { FlatItemAction( - title = translate(Res.strings.autofill), + title = Res.string.autofill.wrap(), leading = icon(Icons.Outlined.AutoAwesome), onClick = { val cipher = secretOrNull @@ -610,7 +615,7 @@ fun vaultViewScreenState( is AppMode.Save -> null is AppMode.SavePasskey -> { FlatItemAction( - title = translate(Res.strings.passkey_save), + title = Res.string.passkey_save.wrap(), leading = icon(Icons.Outlined.Save), onClick = { val cipher = secretOrNull @@ -862,8 +867,8 @@ private fun RememberStateFlowScope.oh( ) { val model = VaultViewItem.Info( id = "info.incomplete", - name = translate(Res.strings.item_incomplete_title), - message = translate(Res.strings.item_incomplete_text), + name = translate(Res.string.item_incomplete_title), + message = translate(Res.string.item_incomplete_text), ) emit(model) } @@ -876,21 +881,21 @@ private fun RememberStateFlowScope.oh( ) { val expired = expiring <= now val expiringTitle = if (expired) { - translate(Res.strings.expired) + translate(Res.string.expired) } else { - translate(Res.strings.expiring_soon) + translate(Res.string.expiring_soon) } val expiringDate = dateFormatter.formatDate(expiring) val expiringMessage = when (cipher.type) { DSecret.Type.Card -> listOf( - translate(Res.strings.expiry_tips_card_line1, expiringDate), - translate(Res.strings.expiry_tips_card_line2, expiringDate), - translate(Res.strings.expiry_tips_card_line3, expiringDate), - translate(Res.strings.expiry_tips_card_line4, expiringDate), + translate(Res.string.expiry_tips_card_line1, expiringDate), + translate(Res.string.expiry_tips_card_line2, expiringDate), + translate(Res.string.expiry_tips_card_line3, expiringDate), + translate(Res.string.expiry_tips_card_line4, expiringDate), ).joinToString(separator = "\n") - else -> translate(Res.strings.expiry_tips_item_line1, expiringDate) + else -> translate(Res.string.expiry_tips_item_line1, expiringDate) } val model = VaultViewItem.Info( id = "info.expiring", @@ -917,7 +922,7 @@ private fun RememberStateFlowScope.oh( copy = copy, id = "card.cvv", accountId = account.id, - title = translate(Res.strings.vault_view_card_cvv_label), + title = translate(Res.string.vault_view_card_cvv_label), value = cipherCardCode, verify = verify.takeIf { concealFields }, private = concealFields, @@ -939,7 +944,7 @@ private fun RememberStateFlowScope.oh( copy = copy, id = "login.username", accountId = account.id, - title = translate(Res.strings.username), + title = translate(Res.string.username), value = cipherLoginUsername, username = true, elevated = true, @@ -964,7 +969,7 @@ private fun RememberStateFlowScope.oh( !cipher.ignores(DWatchtowerAlert.PWNED_PASSWORD) ) VaultViewItem.Value.Badge( - text = translate(Res.strings.password_pwned_label), + text = translate(Res.string.password_pwned_label), score = 0f, ) else null @@ -974,7 +979,7 @@ private fun RememberStateFlowScope.oh( copy = copy, id = "login.password", accountId = account.id, - title = translate(Res.strings.password), + title = translate(Res.string.password), value = cipherLoginPassword, verify = verify.takeIf { concealFields }, private = concealFields, @@ -1013,11 +1018,11 @@ private fun RememberStateFlowScope.oh( val reusedPasswordsModel = VaultViewItem.ReusedPassword( id = "login.password.reused", count = reusedPasswords, - onClick = { + onClick = onClick { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.reused_passwords), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.reused_passwords), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.ByPasswordValue(cipherLoginPassword), sort = PasswordSort, ), @@ -1035,7 +1040,7 @@ private fun RememberStateFlowScope.oh( id = "login.password.revision", text = AnnotatedString( translate( - Res.strings.vault_view_password_revision_label, + Res.string.vault_view_password_revision_label, dateFormatter.formatDateTime(passwordDate), ), ), @@ -1054,12 +1059,12 @@ private fun RememberStateFlowScope.oh( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_otp_code), + title = Res.string.copy_otp_code.wrap(), value = it.code, ) this += copy.FlatItemAction( leading = iconSmall(Icons.Outlined.ContentCopy, Icons.Outlined.Key), - title = translate(Res.strings.copy_otp_secret_code), + title = Res.string.copy_otp_secret_code.wrap(), value = cipherLoginTotp.token.raw, hidden = true, ).verify(verify) @@ -1068,7 +1073,7 @@ private fun RememberStateFlowScope.oh( this += BarcodeTypeRoute.showInBarcodeTypeActionOrNull( translator = this@oh, data = cipherLoginTotp.token.raw, - text = translate(Res.strings.barcodetype_copy_otp_secret_code_note), + text = translate(Res.string.barcodetype_copy_otp_secret_code_note), single = true, navigate = ::navigate, ) @@ -1099,7 +1104,7 @@ private fun RememberStateFlowScope.oh( val model = VaultViewItem.Totp( id = "login.totp", elevation = 1.dp, - title = translate(Res.strings.one_time_password), + title = translate(Res.string.one_time_password), copy = copy, totp = cipherLoginTotp.token, verify = verify, @@ -1175,7 +1180,7 @@ private fun RememberStateFlowScope.oh( if (fido2Credentials.isNotEmpty()) { val loginPasskeysItem = VaultViewItem.Section( id = "login.passkey.header", - text = translate(Res.strings.passkeys), + text = translate(Res.string.passkeys), ) emit(loginPasskeysItem) fido2Credentials.forEachIndexed { index, item -> @@ -1227,7 +1232,7 @@ private fun RememberStateFlowScope.oh( if (cipherIdentity.phone != null) { actions += FlatItemAction( icon = Icons.Outlined.Call, - title = translate(Res.strings.vault_view_call_phone_action), + title = Res.string.vault_view_call_phone_action.wrap(), onClick = { val intent = NavigationIntent.NavigateToPhone( phoneNumber = cipherIdentity.phone, @@ -1237,7 +1242,7 @@ private fun RememberStateFlowScope.oh( ) actions += FlatItemAction( icon = Icons.Outlined.Textsms, - title = translate(Res.strings.vault_view_text_phone_action), + title = Res.string.vault_view_text_phone_action.wrap(), onClick = { val intent = NavigationIntent.NavigateToSms( phoneNumber = cipherIdentity.phone, @@ -1249,7 +1254,7 @@ private fun RememberStateFlowScope.oh( if (cipherIdentity.email != null) { actions += FlatItemAction( icon = Icons.Outlined.Email, - title = translate(Res.strings.vault_view_email_action), + title = Res.string.vault_view_email_action.wrap(), onClick = { val intent = NavigationIntent.NavigateToEmail( email = cipherIdentity.email, @@ -1269,7 +1274,7 @@ private fun RememberStateFlowScope.oh( ) { actions += FlatItemAction( icon = Icons.Outlined.Directions, - title = translate(Res.strings.vault_view_navigate_action), + title = Res.string.vault_view_navigate_action.wrap(), onClick = { val intent = NavigationIntent.NavigateToMaps( address1 = cipherIdentity.address1, @@ -1324,17 +1329,17 @@ private fun RememberStateFlowScope.oh( ) { val contactHeaderItem = VaultViewItem.Section( id = "identity.contact.header", - text = translate(Res.strings.contact_info), + text = translate(Res.string.contact_info), ) emit(contactHeaderItem) } - yieldContactField("phone", cipherIdentity.phone, translate(Res.strings.phone_number)) - yieldContactField("email", cipherIdentity.email, translate(Res.strings.email)) + yieldContactField("phone", cipherIdentity.phone, translate(Res.string.phone_number)) + yieldContactField("email", cipherIdentity.email, translate(Res.string.email)) yieldContactField( "username", value = cipherIdentity.username, - title = translate(Res.strings.username), + title = translate(Res.string.username), username = true, ) @@ -1370,28 +1375,28 @@ private fun RememberStateFlowScope.oh( ) { val miscHeaderItem = VaultViewItem.Section( id = "identity.misc.header", - text = translate(Res.strings.misc), + text = translate(Res.string.misc), ) emit(miscHeaderItem) } - yieldMiscField("company", cipherIdentity.company, translate(Res.strings.company)) + yieldMiscField("company", cipherIdentity.company, translate(Res.string.company)) yieldMiscField( "ssn", cipherIdentity.ssn, - title = translate(Res.strings.ssn), + title = translate(Res.string.ssn), conceal = concealFields, ) yieldMiscField( "passportNumber", cipherIdentity.passportNumber, - title = translate(Res.strings.passport_number), + title = translate(Res.string.passport_number), conceal = concealFields, ) yieldMiscField( "licenseNumber", cipherIdentity.licenseNumber, - title = translate(Res.strings.license_number), + title = translate(Res.string.license_number), conceal = concealFields, ) @@ -1428,7 +1433,7 @@ private fun RememberStateFlowScope.oh( ) { val addressSectionModel = VaultViewItem.Section( id = "identity.address.header", - text = translate(Res.strings.address), + text = translate(Res.string.address), ) emit(addressSectionModel) } @@ -1436,14 +1441,14 @@ private fun RememberStateFlowScope.oh( yieldAddressField("address1", cipherIdentity.address1) yieldAddressField("address2", cipherIdentity.address2) yieldAddressField("address3", cipherIdentity.address3) - yieldAddressField("city", cipherIdentity.city, translate(Res.strings.city)) - yieldAddressField("state", cipherIdentity.state, translate(Res.strings.state)) + yieldAddressField("city", cipherIdentity.city, translate(Res.string.city)) + yieldAddressField("state", cipherIdentity.state, translate(Res.string.state)) yieldAddressField( "postalCode", cipherIdentity.postalCode, - translate(Res.strings.postal_code), + translate(Res.string.postal_code), ) - yieldAddressField("country", cipherIdentity.country, translate(Res.strings.country)) + yieldAddressField("country", cipherIdentity.country, translate(Res.string.country)) } if (cipher.type == DSecret.Type.SecureNote && cipher.notes.isNotEmpty()) { @@ -1473,7 +1478,7 @@ private fun RememberStateFlowScope.oh( if (linkedApps.isNotEmpty()) { val section = VaultViewItem.Section( id = "link.app", - text = translate(Res.strings.linked_apps), + text = translate(Res.string.linked_apps), ) emit(section) // items @@ -1515,7 +1520,7 @@ private fun RememberStateFlowScope.oh( if (linkedWebsites.isNotEmpty()) { val section = VaultViewItem.Section( id = "link.website", - text = translate(Res.strings.linked_uris), + text = translate(Res.string.linked_uris), ) emit(section) // items @@ -1547,7 +1552,7 @@ private fun RememberStateFlowScope.oh( if (cipher.fields.isNotEmpty()) { val section = VaultViewItem.Section( id = "custom", - text = translate(Res.strings.custom_fields), + text = translate(Res.string.custom_fields), ) emit(section) // items @@ -1556,7 +1561,7 @@ private fun RememberStateFlowScope.oh( fun createAction( value: Boolean, ) = FlatItemAction( - title = "Toggle value", + title = TextHolder.Value("Toggle value"), trailing = { Switch( checked = !value, @@ -1600,34 +1605,34 @@ private fun RememberStateFlowScope.oh( if (field.type == DSecret.Field.Type.Linked) { val t = annotate( when (field.linkedId) { - DSecret.Field.LinkedId.Login_Username -> Res.strings.field_linked_to_username - DSecret.Field.LinkedId.Login_Password -> Res.strings.field_linked_to_password - DSecret.Field.LinkedId.Card_CardholderName -> Res.strings.field_linked_to_card_cardholdername - DSecret.Field.LinkedId.Card_ExpMonth -> Res.strings.field_linked_to_card_expmonth - DSecret.Field.LinkedId.Card_ExpYear -> Res.strings.field_linked_to_card_expyear - DSecret.Field.LinkedId.Card_Code -> Res.strings.field_linked_to_card_code - DSecret.Field.LinkedId.Card_Brand -> Res.strings.field_linked_to_card_brand - DSecret.Field.LinkedId.Card_Number -> Res.strings.field_linked_to_card_number - DSecret.Field.LinkedId.Identity_Title -> Res.strings.field_linked_to_identity_title - DSecret.Field.LinkedId.Identity_MiddleName -> Res.strings.field_linked_to_identity_middlename - DSecret.Field.LinkedId.Identity_Address1 -> Res.strings.field_linked_to_identity_address1 - DSecret.Field.LinkedId.Identity_Address2 -> Res.strings.field_linked_to_identity_address2 - DSecret.Field.LinkedId.Identity_Address3 -> Res.strings.field_linked_to_identity_address3 - DSecret.Field.LinkedId.Identity_City -> Res.strings.field_linked_to_identity_city - DSecret.Field.LinkedId.Identity_State -> Res.strings.field_linked_to_identity_state - DSecret.Field.LinkedId.Identity_PostalCode -> Res.strings.field_linked_to_identity_postalcode - DSecret.Field.LinkedId.Identity_Country -> Res.strings.field_linked_to_identity_country - DSecret.Field.LinkedId.Identity_Company -> Res.strings.field_linked_to_identity_company - DSecret.Field.LinkedId.Identity_Email -> Res.strings.field_linked_to_identity_email - DSecret.Field.LinkedId.Identity_Phone -> Res.strings.field_linked_to_identity_phone - DSecret.Field.LinkedId.Identity_Ssn -> Res.strings.field_linked_to_identity_ssn - DSecret.Field.LinkedId.Identity_Username -> Res.strings.field_linked_to_identity_username - DSecret.Field.LinkedId.Identity_PassportNumber -> Res.strings.field_linked_to_identity_passportnumber - DSecret.Field.LinkedId.Identity_LicenseNumber -> Res.strings.field_linked_to_identity_licensenumber - DSecret.Field.LinkedId.Identity_FirstName -> Res.strings.field_linked_to_identity_firstname - DSecret.Field.LinkedId.Identity_LastName -> Res.strings.field_linked_to_identity_lastname - DSecret.Field.LinkedId.Identity_FullName -> Res.strings.field_linked_to_identity_fullname - null -> Res.strings.field_linked_to_unknown_field + DSecret.Field.LinkedId.Login_Username -> Res.string.field_linked_to_username + DSecret.Field.LinkedId.Login_Password -> Res.string.field_linked_to_password + DSecret.Field.LinkedId.Card_CardholderName -> Res.string.field_linked_to_card_cardholdername + DSecret.Field.LinkedId.Card_ExpMonth -> Res.string.field_linked_to_card_expmonth + DSecret.Field.LinkedId.Card_ExpYear -> Res.string.field_linked_to_card_expyear + DSecret.Field.LinkedId.Card_Code -> Res.string.field_linked_to_card_code + DSecret.Field.LinkedId.Card_Brand -> Res.string.field_linked_to_card_brand + DSecret.Field.LinkedId.Card_Number -> Res.string.field_linked_to_card_number + DSecret.Field.LinkedId.Identity_Title -> Res.string.field_linked_to_identity_title + DSecret.Field.LinkedId.Identity_MiddleName -> Res.string.field_linked_to_identity_middlename + DSecret.Field.LinkedId.Identity_Address1 -> Res.string.field_linked_to_identity_address1 + DSecret.Field.LinkedId.Identity_Address2 -> Res.string.field_linked_to_identity_address2 + DSecret.Field.LinkedId.Identity_Address3 -> Res.string.field_linked_to_identity_address3 + DSecret.Field.LinkedId.Identity_City -> Res.string.field_linked_to_identity_city + DSecret.Field.LinkedId.Identity_State -> Res.string.field_linked_to_identity_state + DSecret.Field.LinkedId.Identity_PostalCode -> Res.string.field_linked_to_identity_postalcode + DSecret.Field.LinkedId.Identity_Country -> Res.string.field_linked_to_identity_country + DSecret.Field.LinkedId.Identity_Company -> Res.string.field_linked_to_identity_company + DSecret.Field.LinkedId.Identity_Email -> Res.string.field_linked_to_identity_email + DSecret.Field.LinkedId.Identity_Phone -> Res.string.field_linked_to_identity_phone + DSecret.Field.LinkedId.Identity_Ssn -> Res.string.field_linked_to_identity_ssn + DSecret.Field.LinkedId.Identity_Username -> Res.string.field_linked_to_identity_username + DSecret.Field.LinkedId.Identity_PassportNumber -> Res.string.field_linked_to_identity_passportnumber + DSecret.Field.LinkedId.Identity_LicenseNumber -> Res.string.field_linked_to_identity_licensenumber + DSecret.Field.LinkedId.Identity_FirstName -> Res.string.field_linked_to_identity_firstname + DSecret.Field.LinkedId.Identity_LastName -> Res.string.field_linked_to_identity_lastname + DSecret.Field.LinkedId.Identity_FullName -> Res.string.field_linked_to_identity_fullname + null -> Res.string.field_linked_to_unknown_field }, field.name.orEmpty() to SpanStyle( fontFamily = FontFamily.Monospace, @@ -1658,7 +1663,7 @@ private fun RememberStateFlowScope.oh( if (cipher.type != DSecret.Type.SecureNote && cipher.notes.isNotEmpty()) { val section = VaultViewItem.Section( id = "note", - text = translate(Res.strings.notes), + text = translate(Res.string.notes), ) emit(section) val content = VaultViewItem.Note.Content.of( @@ -1677,7 +1682,7 @@ private fun RememberStateFlowScope.oh( if (cipher.attachments.isNotEmpty()) { val section = VaultViewItem.Section( id = "attachment", - text = translate(Res.strings.attachments), + text = translate(Res.string.attachments), ) emit(section) // items @@ -1731,7 +1736,7 @@ private fun RememberStateFlowScope.oh( if (folder != null) { val section = VaultViewItem.Section( id = "folder", - text = translate(Res.strings.folder), + text = translate(Res.string.folder), ) emit(section) @@ -1741,7 +1746,7 @@ private fun RememberStateFlowScope.oh( .map { VaultViewItem.Folder.FolderNode( name = it.name, - onClick = { + onClick = onClick { val route = VaultRoute.by( translator = this@oh, folder = it.folder, @@ -1751,7 +1756,7 @@ private fun RememberStateFlowScope.oh( }, ) }, - onClick = { + onClick = onClick { val route = VaultRoute.by( translator = this@oh, folder = folder.folder, @@ -1768,9 +1773,9 @@ private fun RememberStateFlowScope.oh( id = "collection", text = if (collections.size == 1) { - translate(Res.strings.collection) + translate(Res.string.collection) } else { - translate(Res.strings.collections) + translate(Res.string.collections) }, ) emit(section) @@ -1778,7 +1783,7 @@ private fun RememberStateFlowScope.oh( val f = VaultViewItem.Collection( id = "collection.${collection.id}", title = collection.name, - onClick = { + onClick = onClick { val route = VaultRoute.by( translator = this@oh, collection = collection, @@ -1794,7 +1799,7 @@ private fun RememberStateFlowScope.oh( if (organization != null) { val section = VaultViewItem.Section( id = "organization", - text = translate(Res.strings.organization), + text = translate(Res.string.organization), ) emit(section) val f = VaultViewItem.Organization( @@ -1823,7 +1828,7 @@ private fun RememberStateFlowScope.oh( val x = VaultViewItem.Label( id = "account", text = annotate( - Res.strings.vault_view_saved_to_label, + Res.string.vault_view_saved_to_label, account.username to SpanStyle( color = contentColor, ), @@ -1839,7 +1844,7 @@ private fun RememberStateFlowScope.oh( id = "created", text = AnnotatedString( translate( - Res.strings.vault_view_created_at_label, + Res.string.vault_view_created_at_label, dateFormatter.formatDateTime(createdDate), ), ), @@ -1851,7 +1856,7 @@ private fun RememberStateFlowScope.oh( id = "revision", text = AnnotatedString( translate( - Res.strings.vault_view_revision_label, + Res.string.vault_view_revision_label, dateFormatter.formatDateTime(cipher.revisionDate), ), ), @@ -1863,7 +1868,7 @@ private fun RememberStateFlowScope.oh( id = "deleted", text = AnnotatedString( translate( - Res.strings.vault_view_deleted_at_label, + Res.string.vault_view_deleted_at_label, dateFormatter.formatDateTime(deletedDate), ), ), @@ -1961,7 +1966,7 @@ private suspend fun RememberStateFlowScope.createUriItem( .height(12.dp), ) Text( - text = translate(Res.strings.error_failed_format_placeholder), + text = stringResource(Res.string.error_failed_format_placeholder), style = MaterialTheme.typography.labelLarge, ) Text( @@ -2095,7 +2100,7 @@ private suspend fun RememberStateFlowScope.createUriItem( serverId = accountId, url = url, ).takeIf { websiteIcons } - val warningTitle = translate(Res.strings.uri_unsecure) + val warningTitle = translate(Res.string.uri_unsecure) .takeIf { isUnsecure } return VaultViewItem.Uri( id = id, @@ -2251,7 +2256,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_package_name), + title = Res.string.copy_package_name.wrap(), value = platformMarker.packageName, ) } @@ -2266,7 +2271,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( contentDescription = null, ) }, - title = translate(Res.strings.uri_action_launch_app_title), + title = Res.string.uri_action_launch_app_title.wrap(), trailing = { ChevronIcon() }, @@ -2278,7 +2283,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( ) this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_play_store_title), + title = Res.string.uri_action_launch_play_store_title.wrap(), trailing = { ChevronIcon() }, @@ -2310,14 +2315,14 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_package_name), + title = Res.string.copy_package_name.wrap(), value = platformMarker.packageName, ) } section { this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_play_store_title), + title = Res.string.uri_action_launch_play_store_title.wrap(), trailing = { ChevronIcon() }, @@ -2351,7 +2356,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_package_name), + title = Res.string.copy_package_name.wrap(), value = platformMarker.packageName, ) } @@ -2375,15 +2380,15 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_url), + title = Res.string.copy_url.wrap(), value = url, ) } section { this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_browser_title), - text = url, + title = Res.string.uri_action_launch_browser_title.wrap(), + text = TextHolder.Value(url), trailing = { ChevronIcon() }, @@ -2399,8 +2404,8 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val launchUrl = platformMarker.frontPageUrl.toString() this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_browser_main_page_title), - text = launchUrl, + title = Res.string.uri_action_launch_browser_main_page_title.wrap(), + text = TextHolder.Value(launchUrl), trailing = { ChevronIcon() }, @@ -2415,8 +2420,8 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( section { this += FlatItemAction( icon = Icons.Outlined.AutoAwesome, - title = translate(Res.strings.uri_action_autofix_unsecure_title), - text = translate(Res.strings.uri_action_autofix_unsecure_text), + title = Res.string.uri_action_autofix_unsecure_title.wrap(), + text = Res.string.uri_action_autofix_unsecure_text.wrap(), onClick = { val ff = mapOf( cipherId to setOf(uri), @@ -2473,7 +2478,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = uri, ) } @@ -2481,7 +2486,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( if (canExecute != null) { this += FlatItemAction( icon = Icons.Outlined.Terminal, - title = translate(Res.strings.execute_command), + title = Res.string.execute_command.wrap(), trailing = { ChevronIcon() }, @@ -2495,7 +2500,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( if (canLuanch.apps.size > 1) { this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_in_smth_title), + title = Res.string.uri_action_launch_in_smth_title.wrap(), trailing = { ChevronIcon() }, @@ -2521,9 +2526,9 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( } }, title = translate( - Res.strings.uri_action_launch_in_app_title, + Res.string.uri_action_launch_in_app_title, canLuanch.apps.first().label, - ), + ).let(TextHolder::Value), trailing = { ChevronIcon() }, @@ -2566,7 +2571,7 @@ private suspend fun RememberStateFlowScope.createUriItemContextItems( } } -fun RememberStateFlowScope.create( +suspend fun RememberStateFlowScope.create( copy: CopyText, id: String, accountId: AccountId, @@ -2588,7 +2593,7 @@ fun RememberStateFlowScope.create( buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = value, hidden = private, ) @@ -2668,7 +2673,7 @@ fun RememberStateFlowScope.create( ) } -private fun RememberStateFlowScope.create( +private suspend fun RememberStateFlowScope.create( copy: CopyText, id: String, verify: ((() -> Unit) -> Unit)? = null, @@ -2679,23 +2684,23 @@ private fun RememberStateFlowScope.create( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_card_number), + title = Res.string.copy_card_number.wrap(), value = data.number, hidden = concealFields, type = CopyText.Type.CARD_NUMBER, )?.verify(verify) this += copy.FlatItemAction( - title = translate(Res.strings.copy_cardholder_name), + title = Res.string.copy_cardholder_name.wrap(), value = data.cardholderName, type = CopyText.Type.CARD_CARDHOLDER_NAME, ) this += copy.FlatItemAction( - title = translate(Res.strings.copy_expiration_month), + title = Res.string.copy_expiration_month.wrap(), value = data.expMonth, type = CopyText.Type.CARD_EXP_MONTH, ) this += copy.FlatItemAction( - title = translate(Res.strings.copy_expiration_year), + title = Res.string.copy_expiration_year.wrap(), value = data.expYear, type = CopyText.Type.CARD_EXP_YEAR, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/util/changePasswordAction.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/util/changePasswordAction.kt index 5ed33fbb..0f9fc979 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/util/changePasswordAction.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/util/changePasswordAction.kt @@ -56,10 +56,14 @@ import com.artemchep.keyguard.feature.export.ExportRoute import com.artemchep.keyguard.feature.home.vault.add.AddRoute import com.artemchep.keyguard.feature.home.vault.add.LeAddRoute import com.artemchep.keyguard.feature.home.vault.screen.VaultViewPasswordHistoryRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope +import com.artemchep.keyguard.feature.navigation.state.onClick +import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.icons.ChevronIcon @@ -74,7 +78,7 @@ fun RememberStateFlowScope.cipherEnableConfirmAccessAction( ) = kotlin.run { FlatItemAction( icon = Icons.Filled.Lock, - title = translate(Res.strings.ciphers_action_enable_auth_reprompt_title), + title = Res.string.ciphers_action_enable_auth_reprompt_title.wrap(), onClick = { before?.invoke() @@ -106,7 +110,7 @@ fun RememberStateFlowScope.cipherDisableConfirmAccessAction( ) = kotlin.run { FlatItemAction( icon = Icons.Outlined.LockOpen, - title = translate(Res.strings.ciphers_action_disable_auth_reprompt_title), + title = Res.string.ciphers_action_disable_auth_reprompt_title.wrap(), onClick = { before?.invoke() @@ -145,7 +149,7 @@ fun RememberStateFlowScope.cipherEditAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.Edit) - val title = translate(Res.strings.ciphers_action_edit_title) + val title = Res.string.ciphers_action_edit_title.wrap() FlatItemAction( leading = icon, title = title, @@ -173,7 +177,7 @@ fun RememberStateFlowScope.cipherMergeIntoAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.Merge) - val title = translate(Res.strings.ciphers_action_merge_title) + val title = Res.string.ciphers_action_merge_title.wrap() FlatItemAction( leading = icon, title = title, @@ -217,7 +221,7 @@ fun RememberStateFlowScope.cipherExportAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val iconImageVector = Icons.Outlined.SaveAlt - val title = translate(Res.strings.ciphers_action_export_title) + val title = Res.string.ciphers_action_export_title.wrap() FlatItemAction( icon = iconImageVector, title = title, @@ -253,11 +257,11 @@ fun RememberStateFlowScope.cipherCopyToAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val iconImageVector = Icons.Outlined.FileCopy - val title = translate(Res.strings.ciphers_action_copy_title) + val title = Res.string.ciphers_action_copy_title.wrap() FlatItemAction( icon = iconImageVector, title = title, - onClick = { + onClick = onClick { before?.invoke() val ciphersHaveAttachments = ciphers.any { it.attachments.isNotEmpty() } @@ -277,7 +281,7 @@ fun RememberStateFlowScope.cipherCopyToAction( route = OrganizationConfirmationRoute( args = OrganizationConfirmationRoute.Args( decor = OrganizationConfirmationRoute.Args.Decor( - title = title, + title = translate(title), note = note, icon = iconImageVector, ), @@ -322,7 +326,7 @@ fun RememberStateFlowScope.cipherMoveToFolderAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.Folder) - val title = translate(Res.strings.ciphers_action_change_folder_title) + val title = Res.string.ciphers_action_change_folder_title.wrap() FlatItemAction( leading = icon, title = title, @@ -406,14 +410,14 @@ fun RememberStateFlowScope.cipherChangeNameAction( ) = kotlin.run { val icon = icon(Icons.Outlined.Edit) val title = if (ciphers.size > 1) { - translate(Res.strings.ciphers_action_change_names_title) + Res.string.ciphers_action_change_names_title } else { - translate(Res.strings.ciphers_action_change_name_title) - } + Res.string.ciphers_action_change_name_title + }.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = ciphers @@ -431,7 +435,7 @@ fun RememberStateFlowScope.cipherChangeNameAction( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon, - title = title, + title = translate(title), items = items, ), ), @@ -470,22 +474,22 @@ fun RememberStateFlowScope.cipherChangePasswordAction( val hasPasswords = ciphers.any { !it.login?.password.isNullOrEmpty() } if (hasPasswords) { if (ciphers.size > 1) { - translate(Res.strings.ciphers_action_change_passwords_title) + Res.string.ciphers_action_change_passwords_title } else { - translate(Res.strings.ciphers_action_change_password_title) + Res.string.ciphers_action_change_password_title } } else { if (ciphers.size > 1) { - translate(Res.strings.ciphers_action_add_passwords_title) + Res.string.ciphers_action_add_passwords_title } else { - translate(Res.strings.ciphers_action_add_password_title) + Res.string.ciphers_action_add_password_title } - } + }.wrap() } FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = ciphers @@ -504,8 +508,8 @@ fun RememberStateFlowScope.cipherChangePasswordAction( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon, - title = title, - message = translate(Res.strings.generator_password_note, 16), + title = translate(title), + message = translate(Res.string.generator_password_note, 16), items = items, ), ), @@ -538,7 +542,7 @@ fun RememberStateFlowScope.cipherViewPasswordHistoryAction( cipher: DSecret, before: (() -> Unit)? = null, ) = kotlin.run { - val title = translate(Res.strings.ciphers_action_view_password_history_title) + val title = Res.string.ciphers_action_view_password_history_title.wrap() FlatItemAction( leading = { BadgedBox( @@ -579,7 +583,7 @@ fun RememberStateFlowScope.cipherTrashAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.Delete) - val title = translate(Res.strings.ciphers_action_trash_title) + val title = Res.string.ciphers_action_trash_title.wrap() FlatItemAction( leading = icon, title = title, @@ -625,7 +629,7 @@ fun RememberStateFlowScope.cipherRestoreAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.RestoreFromTrash) - val title = translate(Res.strings.ciphers_action_restore_title) + val title = Res.string.ciphers_action_restore_title.wrap() FlatItemAction( leading = icon, title = title, @@ -670,18 +674,18 @@ fun RememberStateFlowScope.cipherDeleteAction( after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.DeleteForever) - val title = translate(Res.strings.ciphers_action_delete_title) + val title = Res.string.ciphers_action_delete_title.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val route = registerRouteResultReceiver( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.DeleteForever), - title = translate(Res.strings.ciphers_action_delete_confirmation_title), + title = translate(Res.string.ciphers_action_delete_confirmation_title), ), ), ) { result -> @@ -719,7 +723,7 @@ fun RememberStateFlowScope.cipherWatchtowerAlerts( .flatMap { cipher -> cipher.ignoredAlerts.keys } .toSet() .count() - val title = translate(Res.strings.ciphers_action_configure_watchtower_alerts_title) + val title = Res.string.ciphers_action_configure_watchtower_alerts_title.wrap() FlatItemAction( leading = { BadgedBox( @@ -740,7 +744,7 @@ fun RememberStateFlowScope.cipherWatchtowerAlerts( } }, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = DWatchtowerAlert.entries @@ -760,7 +764,7 @@ fun RememberStateFlowScope.cipherWatchtowerAlerts( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.EditNotifications), - title = title, + title = translate(title), items = items, ), ), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/JustDeleteMeComponent.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/JustDeleteMeComponent.kt index 0e06df4b..9b328220 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/JustDeleteMeComponent.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/JustDeleteMeComponent.kt @@ -4,8 +4,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.artemchep.keyguard.common.service.justdeleteme.JustDeleteMeServiceInfo import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Ah -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AhDifficulty( @@ -22,11 +23,11 @@ fun AhDifficulty( else -> 0.0f } val text = when (difficulty) { - "easy" -> stringResource(Res.strings.justdeleteme_difficulty_easy_label) - "medium" -> stringResource(Res.strings.justdeleteme_difficulty_medium_label) - "hard" -> stringResource(Res.strings.justdeleteme_difficulty_hard_label) - "limited" -> stringResource(Res.strings.justdeleteme_difficulty_limited_availability_label) - "impossible" -> stringResource(Res.strings.justdeleteme_difficulty_impossible_label) + "easy" -> stringResource(Res.string.justdeleteme_difficulty_easy_label) + "medium" -> stringResource(Res.string.justdeleteme_difficulty_medium_label) + "hard" -> stringResource(Res.string.justdeleteme_difficulty_hard_label) + "limited" -> stringResource(Res.string.justdeleteme_difficulty_limited_availability_label) + "impossible" -> stringResource(Res.string.justdeleteme_difficulty_impossible_label) else -> "" } Ah( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceListScreen.kt index ef863fd5..247d9bc1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceListScreen.kt @@ -38,6 +38,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.navigationNextEntryOrNull import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -49,7 +50,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -132,7 +133,7 @@ fun JustDeleteMeListScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.justdeleteme_title), + title = stringResource(Res.string.justdeleteme_title), icon = { NavigationIcon() }, @@ -166,7 +167,7 @@ fun JustDeleteMeListScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.justdeleteme_search_placeholder), + placeholder = stringResource(Res.string.justdeleteme_search_placeholder), searchIcon = false, count = count, leading = {}, @@ -249,7 +250,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.justdeleteme_empty_label), + text = stringResource(Res.string.justdeleteme_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewDialogRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewDialogRoute.kt index 718faae2..a11694be 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewDialogRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewDialogRoute.kt @@ -5,10 +5,12 @@ import androidx.compose.material.icons.outlined.AccountBox import androidx.compose.material.icons.outlined.Delete import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.service.justdeleteme.JustDeleteMeServiceInfo +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.iconSmall @@ -32,7 +34,7 @@ data class JustDeleteMeServiceViewDialogRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.AccountBox, Icons.Outlined.Delete), - title = translator.translate(Res.strings.uri_action_how_to_delete_account_title), + title = Res.string.uri_action_how_to_delete_account_title.wrap(), onClick = { val route = JustDeleteMeServiceViewDialogRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewScreen.kt index fbf86d50..38b3d1b8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServiceViewScreen.kt @@ -29,6 +29,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.tfa.directory.FlatLaunchBrowserItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldColumn @@ -40,7 +41,7 @@ import com.artemchep.keyguard.ui.poweredby.PoweredByJustDeleteMe import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun JustDeleteMeDialogScreen( @@ -57,7 +58,7 @@ fun JustDeleteMeDialogScreen( text = title, ) Text( - text = stringResource(Res.strings.justdeleteme_title), + text = stringResource(Res.string.justdeleteme_title), style = MaterialTheme.typography.titleSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -84,7 +85,7 @@ fun JustDeleteMeDialogScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -160,7 +161,7 @@ fun ColumnScope.Content( }, title = { Text( - text = stringResource(Res.strings.justdeleteme_send_email_title), + text = stringResource(Res.string.justdeleteme_send_email_title), ) }, trailing = { @@ -184,7 +185,7 @@ fun ColumnScope.Content( val websiteUrl = args.justDeleteMe.url if (websiteUrl != null) { FlatLaunchBrowserItem( - title = stringResource(Res.strings.uri_action_launch_website_title), + title = stringResource(Res.string.uri_action_launch_website_title), url = websiteUrl, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServicesRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServicesRoute.kt index 28167346..08f73ca3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServicesRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justdeleteme/directory/JustDeleteMeServicesRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AccountBox import androidx.compose.material.icons.outlined.Delete import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.iconSmall @@ -28,7 +30,7 @@ object JustDeleteMeServicesRoute : Route { navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.AccountBox, Icons.Outlined.Delete), - title = translator.translate(Res.strings.uri_action_how_to_delete_account_title), + title = Res.string.uri_action_how_to_delete_account_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/JustGetMyDataComponent.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/JustGetMyDataComponent.kt index 0e35b35e..0d2a8616 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/JustGetMyDataComponent.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/JustGetMyDataComponent.kt @@ -4,8 +4,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.artemchep.keyguard.common.service.justgetmydata.JustGetMyDataServiceInfo import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Ah -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun AhDifficulty( @@ -22,11 +23,11 @@ fun AhDifficulty( else -> 0.0f } val text = when (difficulty) { - "easy" -> stringResource(Res.strings.justgetmydata_difficulty_easy_label) - "medium" -> stringResource(Res.strings.justgetmydata_difficulty_medium_label) - "hard" -> stringResource(Res.strings.justgetmydata_difficulty_hard_label) - "limited" -> stringResource(Res.strings.justgetmydata_difficulty_limited_availability_label) - "impossible" -> stringResource(Res.strings.justgetmydata_difficulty_impossible_label) + "easy" -> stringResource(Res.string.justgetmydata_difficulty_easy_label) + "medium" -> stringResource(Res.string.justgetmydata_difficulty_medium_label) + "hard" -> stringResource(Res.string.justgetmydata_difficulty_hard_label) + "limited" -> stringResource(Res.string.justgetmydata_difficulty_limited_availability_label) + "impossible" -> stringResource(Res.string.justgetmydata_difficulty_impossible_label) else -> "" } Ah( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataListScreen.kt index 3d6774e4..f3cee381 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataListScreen.kt @@ -39,6 +39,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.navigationNextEntryOrNull import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -50,7 +51,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -133,7 +134,7 @@ fun JustGetMyDataListScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.justgetmydata_title), + title = stringResource(Res.string.justgetmydata_title), icon = { NavigationIcon() }, @@ -167,7 +168,7 @@ fun JustGetMyDataListScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.justgetmydata_search_placeholder), + placeholder = stringResource(Res.string.justgetmydata_search_placeholder), searchIcon = false, count = count, leading = {}, @@ -250,7 +251,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.justgetmydata_empty_label), + text = stringResource(Res.string.justgetmydata_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataServicesRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataServicesRoute.kt index cb14c96a..08f7ba23 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataServicesRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataServicesRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AccountBox import androidx.compose.material.icons.outlined.Dataset import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.iconSmall @@ -28,7 +30,7 @@ object JustGetMyDataServicesRoute : Route { navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.AccountBox, Icons.Outlined.Dataset), - title = translator.translate(Res.strings.uri_action_get_my_data_account_title), + title = Res.string.uri_action_get_my_data_account_title.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewDialogRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewDialogRoute.kt index 4012bb10..a22f8861 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewDialogRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewDialogRoute.kt @@ -5,10 +5,12 @@ import androidx.compose.material.icons.outlined.AccountBox import androidx.compose.material.icons.outlined.Dataset import androidx.compose.runtime.Composable import com.artemchep.keyguard.common.service.justgetmydata.JustGetMyDataServiceInfo +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.iconSmall @@ -32,7 +34,7 @@ data class JustGetMyDataViewDialogRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.AccountBox, Icons.Outlined.Dataset), - title = translator.translate(Res.strings.uri_action_get_my_data_account_title), + title = Res.string.uri_action_get_my_data_account_title.wrap(), onClick = { val route = JustGetMyDataViewDialogRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewScreen.kt index a03cb3b3..9342aa00 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/justgetdata/directory/JustGetMyDataViewScreen.kt @@ -30,6 +30,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.tfa.directory.FlatLaunchBrowserItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldColumn @@ -43,7 +44,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun JustGetMyDataViewDialogScreen( @@ -85,7 +86,7 @@ fun JustGetMyDataViewDialogScreen( } } Text( - text = stringResource(Res.strings.justgetmydata_title), + text = stringResource(Res.string.justgetmydata_title), style = MaterialTheme.typography.titleSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -112,7 +113,7 @@ fun JustGetMyDataViewDialogScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -212,7 +213,7 @@ fun ColumnScope.Content( }, title = { Text( - text = stringResource(Res.strings.justdeleteme_send_email_title), + text = stringResource(Res.string.justdeleteme_send_email_title), ) }, trailing = { @@ -236,7 +237,7 @@ fun ColumnScope.Content( val websiteUrl = args.model.url if (websiteUrl != null) { FlatLaunchBrowserItem( - title = stringResource(Res.strings.uri_action_launch_website_title), + title = stringResource(Res.string.uri_action_launch_website_title), url = websiteUrl, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupScreen.kt index 8e4f34be..3c716a6c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupScreen.kt @@ -47,6 +47,7 @@ import com.artemchep.keyguard.feature.keyguard.unlock.unlockScreenActionPadding import com.artemchep.keyguard.feature.keyguard.unlock.unlockScreenTitlePadding import com.artemchep.keyguard.platform.isStandalone import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AutofillButton import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItemLayout @@ -58,7 +59,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SetupScreen( @@ -182,7 +183,7 @@ fun ColumnScope.SetupContent( onFill = setupState.password.onChange, ), testTag = "field:password", - label = stringResource(Res.strings.setup_field_app_password_label), + label = stringResource(Res.string.setup_field_app_password_label), value = setupState.password, keyboardOptions = KeyboardOptions( imeAction = when { @@ -217,7 +218,7 @@ fun ColumnScope.SetupContent( }, content = { Text( - text = stringResource(Res.strings.setup_checkbox_biometric_auth), + text = stringResource(Res.string.setup_checkbox_biometric_auth), style = MaterialTheme.typography.bodyMedium, ) }, @@ -240,7 +241,7 @@ fun ColumnScope.SetupContent( }, content = { Text( - text = stringResource(Res.strings.setup_button_send_crash_reports), + text = stringResource(Res.string.setup_button_send_crash_reports), style = MaterialTheme.typography.bodyMedium, ) }, @@ -282,7 +283,7 @@ fun ColumnScope.SetupContent( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.setup_button_create_vault), + text = stringResource(Res.string.setup_button_create_vault), ) } } @@ -300,7 +301,7 @@ private fun ColumnScope.SetupScreenCreateVaultTitle() { Text( modifier = Modifier .fillMaxWidth(), - text = stringResource(Res.strings.setup_header_text), + text = stringResource(Res.string.setup_header_text), style = MaterialTheme.typography.bodyLarge, ) if (isStandalone) { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupStateProducer.kt index 4b33a992..adc31b07 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/setup/SetupStateProducer.kt @@ -21,6 +21,7 @@ import com.artemchep.keyguard.platform.LeCipher import com.artemchep.keyguard.platform.crashlyticsIsEnabled import com.artemchep.keyguard.platform.crashlyticsSetEnabled import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf @@ -142,7 +143,7 @@ private fun createPromptOrNull( ifRight = ::identity, ) BiometricAuthPrompt( - title = TextHolder.Res(Res.strings.setup_biometric_auth_confirm_title), + title = TextHolder.Res(Res.string.setup_biometric_auth_confirm_title), cipher = cipher, requireConfirmation = createVaultWithMasterPasswordAndBiometricFn.requireConfirmation, onComplete = { result -> diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockScreen.kt index d64aa446..20d3c325 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockScreen.kt @@ -39,6 +39,7 @@ import com.artemchep.keyguard.common.model.fold import com.artemchep.keyguard.feature.auth.common.autofill import com.artemchep.keyguard.feature.biometric.BiometricPromptEffect import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.OptionsButton @@ -50,7 +51,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonButton import com.artemchep.keyguard.ui.skeleton.SkeletonTextField import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import org.kodein.di.compose.localDI import org.kodein.di.direct @@ -217,7 +218,7 @@ private fun UnlockScreen( .width(Dimens.buttonIconPadding), ) Text( - text = stringResource(Res.strings.unlock_button_unlock), + text = stringResource(Res.string.unlock_button_unlock), ) } val onBiometricButtonClick by rememberUpdatedState(unlockState.biometric?.onClick) @@ -248,7 +249,7 @@ private fun UnlockScreen( private fun UnlockScreenTheVaultIsLockedTitle() { Text( textAlign = TextAlign.Center, - text = stringResource(Res.strings.unlock_header_text), + text = stringResource(Res.string.unlock_header_text), style = MaterialTheme.typography.bodyLarge, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockStateProducer.kt index dab0566e..b743b200 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/keyguard/unlock/UnlockStateProducer.kt @@ -23,10 +23,12 @@ import com.artemchep.keyguard.feature.auth.common.Validated import com.artemchep.keyguard.feature.auth.common.util.validatedTitle import com.artemchep.keyguard.feature.loading.LoadingTask import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.platform.LeCipher import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.Dispatchers @@ -90,8 +92,8 @@ fun unlockScreenState( val actions = persistentListOf( FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.pref_item_erase_data_title), - text = translate(Res.strings.pref_item_erase_data_text), + title = Res.string.pref_item_erase_data_title.wrap(), + text = Res.string.pref_item_erase_data_text.wrap(), onClick = { clearData() .effectTap { @@ -198,8 +200,8 @@ private fun createPromptOrNull( ifRight = ::identity, ) BiometricAuthPrompt( - title = TextHolder.Res(Res.strings.unlock_biometric_auth_confirm_title), - text = TextHolder.Res(Res.strings.unlock_biometric_auth_confirm_text), + title = TextHolder.Res(Res.string.unlock_biometric_auth_confirm_title), + text = TextHolder.Res(Res.string.unlock_biometric_auth_confirm_text), cipher = cipher, requireConfirmation = fn.requireConfirmation, onComplete = { result -> diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeRoute.kt index 1bded8bb..357e4bb2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeRoute.kt @@ -3,12 +3,14 @@ package com.artemchep.keyguard.feature.largetype import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Lock import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.KeyguardLargeType import com.artemchep.keyguard.ui.icons.icon @@ -44,7 +46,7 @@ data class LargeTypeRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.KeyguardLargeType), - title = translator.translate(Res.strings.largetype_action_show_in_large_type_title), + title = Res.string.largetype_action_show_in_large_type_title.wrap(), onClick = { val route = LargeTypeRoute( args = Args( @@ -83,7 +85,7 @@ data class LargeTypeRoute( navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.KeyguardLargeType, Icons.Filled.Lock), - title = translator.translate(Res.strings.largetype_action_show_in_large_type_and_lock_title), + title = Res.string.largetype_action_show_in_large_type_and_lock_title.wrap(), onClick = { val intent = NavigationIntent.NavigateToLargeType( phrases = if (split) text.split(" ") else listOf(text), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeScreen.kt index eb636995..b02d71c2 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeScreen.kt @@ -37,6 +37,7 @@ import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.KeepScreenOnEffect import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -48,7 +49,7 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.theme.selectedContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun LargeTypeScreen( @@ -70,7 +71,7 @@ private fun LargeTypeDialog( Dialog( icon = icon(Icons.Outlined.KeyguardLargeType), title = { - Text(stringResource(Res.strings.largetype_title)) + Text(stringResource(Res.string.largetype_title)) }, content = { val state = loadableState.getOrNull() @@ -88,7 +89,7 @@ private fun LargeTypeDialog( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeStateProducer.kt index c733fa09..2a792a3b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/largetype/LargeTypeStateProducer.kt @@ -7,6 +7,7 @@ import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.common.util.asCodePointsSequence import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.map @Composable @@ -36,7 +37,7 @@ fun produceLargeTypeScreenState( phrase.any { it.isSurrogate() } } val text = if (hasUnicodeSurrogates) { - translate(Res.strings.largetype_unicode_surrogate_note) + translate(Res.string.largetype_unicode_surrogate_note) } else { null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/license/LicenseScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/license/LicenseScreen.kt index febc07ed..c8166ebd 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/license/LicenseScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/license/LicenseScreen.kt @@ -26,6 +26,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.FlatItemTextContent @@ -37,7 +38,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -53,7 +54,7 @@ fun LicenseScreen() { LargeToolbar( title = { Text( - text = stringResource(Res.strings.settings_open_source_licenses_header_title), + text = stringResource(Res.string.settings_open_source_licenses_header_title), ) }, navigationIcon = { @@ -114,7 +115,7 @@ private fun LicenseItem( title = { Text( text = item.name - ?: stringResource(Res.strings.empty_value), + ?: stringResource(Res.string.empty_value), color = LocalContentColor.current .let { color -> // If the name doesn't exist, then show it with diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/loading/LoadingTask.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/loading/LoadingTask.kt index 91975fa1..e6de0b56 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/loading/LoadingTask.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/loading/LoadingTask.kt @@ -22,7 +22,7 @@ class LoadingTask( * Exception handler that's responsible for parsing the * error messages as user-readable messages. */ - private val exceptionHandler: (Throwable) -> ReadableExceptionMessage = { e -> + private val exceptionHandler: suspend (Throwable) -> ReadableExceptionMessage = { e -> getErrorReadableMessage(e, translator) }, ) { @@ -82,11 +82,11 @@ data class ReadableExceptionMessage( val text: String? = null, ) -fun getErrorReadableMessage(e: Throwable, translator: TranslatorScope) = +suspend fun getErrorReadableMessage(e: Throwable, translator: TranslatorScope) = when (e) { is Readable -> { - val title = e.title.let(translator::translate) - val text = e.text?.let(translator::translate) + val title = e.title.let { translator.translate(it) } + val text = e.text?.let { translator.translate(it) } ReadableExceptionMessage( title = title, text = text, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/TextHolder.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/TextHolder.kt index 810800f3..e3a1ebb6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/TextHolder.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/TextHolder.kt @@ -1,19 +1,23 @@ package com.artemchep.keyguard.feature.localization import androidx.compose.runtime.Composable -import dev.icerock.moko.resources.StringResource -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.stringResource sealed interface TextHolder { - data class Value( + @JvmInline + value class Value( val data: String, ) : TextHolder - data class Res( + @JvmInline + value class Res( val data: StringResource, ) : TextHolder } +fun StringResource.wrap() = TextHolder.Res(this) + @Composable fun textResource(text: TextHolder): String = when (text) { is TextHolder.Value -> text.data diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt index 20e88869..6f7e5b4c 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt @@ -1,23 +1,25 @@ package com.artemchep.keyguard.feature.localization import com.artemchep.keyguard.platform.LeContext -import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.getPluralString +import org.jetbrains.compose.resources.getString -expect fun textResource( +suspend fun textResource( res: StringResource, context: LeContext, -): String +): String = getString(res) -expect fun textResource( +suspend fun textResource( res: StringResource, context: LeContext, vararg args: Any, -): String +): String = getString(res, *args) -expect fun textResource( - res: PluralsResource, +suspend fun textResource( + res: PluralStringResource, context: LeContext, quantity: Int, vararg args: Any, -): String +): String = getPluralString(res, quantity, *args) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScope.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScope.kt index 385a81ef..e8314600 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScope.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScope.kt @@ -6,31 +6,31 @@ import com.artemchep.keyguard.feature.loading.LoadingTask import com.artemchep.keyguard.feature.localization.TextHolder import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.platform.LeContext -import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.shareIn +import org.jetbrains.compose.resources.PluralStringResource interface TranslatorScope { - fun translate( + suspend fun translate( res: StringResource, ): String - fun translate( + suspend fun translate( res: StringResource, vararg args: Any, ): String - fun translate( - res: PluralsResource, + suspend fun translate( + res: PluralStringResource, quantity: Int, vararg args: Any, ): String } -fun TranslatorScope.translate(text: TextHolder) = when (text) { +suspend fun TranslatorScope.translate(text: TextHolder) = when (text) { is TextHolder.Res -> translate(text.data) is TextHolder.Value -> text.data } @@ -90,6 +90,8 @@ interface RememberStateFlowScope : RememberStateFlowScopeSub, CoroutineScope, Tr block: CoroutineScope.() -> Unit, ): () -> Unit + fun action(block: suspend () -> Unit) + // // Helpers // @@ -109,6 +111,10 @@ interface RememberStateFlowScopeZygote : RememberStateFlowScope { val keepAliveFlow: Flow } +fun RememberStateFlowScope.onClick(block: suspend () -> Unit): () -> Unit = { + action(block) +} + fun RememberStateFlowScope.navigatePopSelf() { val intent = NavigationIntent.PopById(screenId, exclusive = false) navigate(intent) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScopeImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScopeImpl.kt index e7d14d10..bbdc4ae5 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScopeImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/navigation/state/RememberStateFlowScopeImpl.kt @@ -24,8 +24,7 @@ import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.platform.contains import com.artemchep.keyguard.platform.get import com.artemchep.keyguard.platform.leBundleOf -import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -39,8 +38,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import kotlinx.coroutines.plus import kotlinx.serialization.json.Json +import org.jetbrains.compose.resources.PluralStringResource class RememberStateFlowScopeImpl( private val key: String, @@ -137,23 +138,25 @@ class RememberStateFlowScopeImpl( override fun message( exception: Throwable, ) { - val parsedMessage = getErrorReadableMessage(exception, this) - val message = ToastMessage( - type = ToastMessage.Type.ERROR, - title = parsedMessage.title, - text = parsedMessage.text, - ) - message(message) + action { + val parsedMessage = getErrorReadableMessage(exception, this) + val message = ToastMessage( + type = ToastMessage.Type.ERROR, + title = parsedMessage.title, + text = parsedMessage.text, + ) + message(message) + } } - override fun translate(res: StringResource): String = + override suspend fun translate(res: StringResource): String = textResource(res, context) - override fun translate(res: StringResource, vararg args: Any): String = + override suspend fun translate(res: StringResource, vararg args: Any): String = textResource(res, context, *args) - override fun translate( - res: PluralsResource, + override suspend fun translate( + res: PluralStringResource, quantity: Int, vararg args: Any, ): String = textResource(res, context, quantity, *args) @@ -212,6 +215,12 @@ class RememberStateFlowScopeImpl( } } + override fun action(block: suspend () -> Unit) { + appScope.launch { + block() + } + } + override suspend fun loadDiskHandle( key: String, global: Boolean, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingItem.kt index a95c984e..71546f9e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingItem.kt @@ -1,7 +1,7 @@ package com.artemchep.keyguard.feature.onboarding import androidx.compose.ui.graphics.vector.ImageVector -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource data class OnboardingItem( val title: StringResource, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingScreen.kt index 65fdd8f5..a0d1bf64 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/onboarding/OnboardingScreen.kt @@ -52,6 +52,7 @@ import com.artemchep.keyguard.common.usecase.PutOnboardingLastVisitInstant import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldColumn @@ -64,27 +65,27 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.horizontalPaddingHalf import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.util.DividerColor -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.GlobalScope import kotlinx.datetime.Clock import org.kodein.di.compose.rememberInstance val onboardingItemsPremium = listOf( OnboardingItem( - title = Res.strings.feat_item_multiple_accounts_title, - text = Res.strings.feat_item_multiple_accounts_text, + title = Res.string.feat_item_multiple_accounts_title, + text = Res.string.feat_item_multiple_accounts_text, premium = true, icon = Icons.Outlined.AccountBox, ), OnboardingItem( - title = Res.strings.feat_item_two_way_sync_title, - text = Res.strings.feat_item_two_way_sync_text, + title = Res.string.feat_item_two_way_sync_title, + text = Res.string.feat_item_two_way_sync_text, premium = true, icon = Icons.Outlined.Sync, ), OnboardingItem( - title = Res.strings.feat_item_offline_editing_title, - text = Res.strings.feat_item_offline_editing_text, + title = Res.string.feat_item_offline_editing_title, + text = Res.string.feat_item_offline_editing_text, premium = true, icon = Icons.Outlined.OfflineBolt, ), @@ -92,78 +93,78 @@ val onboardingItemsPremium = listOf( val onboardingItemsSearch = listOf( OnboardingItem( - title = Res.strings.feat_item_search_by_anything_title, - text = Res.strings.feat_item_search_by_anything_text, + title = Res.string.feat_item_search_by_anything_title, + text = Res.string.feat_item_search_by_anything_text, icon = Icons.Outlined.Search, ), OnboardingItem( - title = Res.strings.feat_item_filter_title, - text = Res.strings.feat_item_filter_text, + title = Res.string.feat_item_filter_title, + text = Res.string.feat_item_filter_text, icon = Icons.Outlined.FilterAlt, ), OnboardingItem( - title = Res.strings.feat_item_multiple_keywords_title, - text = Res.strings.feat_item_multiple_keywords_text, + title = Res.string.feat_item_multiple_keywords_title, + text = Res.string.feat_item_multiple_keywords_text, ), ) val onboardingItemsWatchtower = listOf( OnboardingItem( - title = Res.strings.feat_item_pwned_passwords_title, - text = Res.strings.feat_item_pwned_passwords_text, + title = Res.string.feat_item_pwned_passwords_title, + text = Res.string.feat_item_pwned_passwords_text, icon = Icons.Outlined.DataArray, ), OnboardingItem( - title = Res.strings.feat_item_password_strength_title, - text = Res.strings.feat_item_password_strength_text, + title = Res.string.feat_item_password_strength_title, + text = Res.string.feat_item_password_strength_text, icon = Icons.Outlined.Password, ), OnboardingItem( - title = Res.strings.feat_item_reused_passwords_title, - text = Res.strings.feat_item_reused_passwords_text, + title = Res.string.feat_item_reused_passwords_title, + text = Res.string.feat_item_reused_passwords_text, icon = Icons.Outlined.Recycling, ), OnboardingItem( - title = Res.strings.feat_item_inactive_totp_title, - text = Res.strings.feat_item_inactive_totp_text, + title = Res.string.feat_item_inactive_totp_title, + text = Res.string.feat_item_inactive_totp_text, icon = Icons.Outlined.KeyguardTwoFa, ), OnboardingItem( - title = Res.strings.feat_item_unsecure_websites_title, - text = Res.strings.feat_item_unsecure_websites_text, + title = Res.string.feat_item_unsecure_websites_title, + text = Res.string.feat_item_unsecure_websites_text, icon = Icons.Outlined.KeyguardWebsite, ), OnboardingItem( - title = Res.strings.feat_item_incomplete_items_title, - text = Res.strings.feat_item_incomplete_items_text, + title = Res.string.feat_item_incomplete_items_title, + text = Res.string.feat_item_incomplete_items_text, icon = Icons.Outlined.ShortText, ), OnboardingItem( - title = Res.strings.feat_item_expiring_items_title, - text = Res.strings.feat_item_expiring_items_text, + title = Res.string.feat_item_expiring_items_title, + text = Res.string.feat_item_expiring_items_text, icon = Icons.Outlined.Timer, ), OnboardingItem( - title = Res.strings.feat_item_duplicate_items_title, - text = Res.strings.feat_item_duplicate_items_text, + title = Res.string.feat_item_duplicate_items_title, + text = Res.string.feat_item_duplicate_items_text, icon = Icons.Outlined.CopyAll, ), ) val onboardingItemsOther = listOf( OnboardingItem( - title = Res.strings.feat_item_multi_selection_title, - text = Res.strings.feat_item_multi_selection_text, + title = Res.string.feat_item_multi_selection_title, + text = Res.string.feat_item_multi_selection_text, icon = Icons.Outlined.SelectAll, ), OnboardingItem( - title = Res.strings.feat_item_show_barcode_title, - text = Res.strings.feat_item_show_barcode_text, + title = Res.string.feat_item_show_barcode_title, + text = Res.string.feat_item_show_barcode_text, icon = Icons.Outlined.QrCode, ), OnboardingItem( - title = Res.strings.feat_item_generator_title, - text = Res.strings.feat_item_generator_text, + title = Res.string.feat_item_generator_title, + text = Res.string.feat_item_generator_text, ), ) @@ -184,7 +185,7 @@ fun OnboardingScreen() { topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.feat_header_title)) + Text(stringResource(Res.string.feat_header_title)) }, navigationIcon = { NavigationIcon() @@ -206,7 +207,7 @@ private fun ColumnScope.OnboardingScreenContent() { items = onboardingItemsPremium, ) Section( - text = stringResource(Res.strings.feat_section_search_title), + text = stringResource(Res.string.feat_section_search_title), ) OnboardingContainer( modifier = Modifier @@ -215,7 +216,7 @@ private fun ColumnScope.OnboardingScreenContent() { items = onboardingItemsSearch, ) Section( - text = stringResource(Res.strings.feat_section_watchtower_title), + text = stringResource(Res.string.feat_section_watchtower_title), ) OnboardingContainer( modifier = Modifier @@ -224,7 +225,7 @@ private fun ColumnScope.OnboardingScreenContent() { items = onboardingItemsWatchtower, ) Section( - text = stringResource(Res.strings.feat_section_misc_title), + text = stringResource(Res.string.feat_section_misc_title), ) OnboardingContainer( modifier = Modifier @@ -321,7 +322,7 @@ fun OnboardingCard( tint = MaterialTheme.colorScheme.primary, ) Text( - text = stringResource(Res.strings.feat_keyguard_premium_label), + text = stringResource(Res.string.feat_keyguard_premium_label), color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.labelSmall, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewScreen.kt index 30e3a1a9..1d4ed298 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewScreen.kt @@ -37,6 +37,7 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItemLayout import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -48,7 +49,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonSection import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun PasskeysCredentialViewScreen( @@ -72,7 +73,7 @@ fun PasskeysCredentialViewScreen( icon = icon(Icons.Outlined.Key), title = { Text( - text = stringResource(Res.strings.passkey), + text = stringResource(Res.string.passkey), ) }, content = { @@ -108,7 +109,7 @@ fun PasskeysCredentialViewScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } val onUse = loadableState.getOrNull()?.content?.getOrNull()?.onUse if (onUse != null) { @@ -118,7 +119,7 @@ fun PasskeysCredentialViewScreen( updatedOnUse.invoke() }, ) { - Text(stringResource(Res.strings.passkey_use_short)) + Text(stringResource(Res.string.passkey_use_short)) } } }, @@ -141,14 +142,14 @@ private fun ColumnScope.ContentOk( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.passkey_user_display_name), + text = stringResource(Res.string.passkey_user_display_name), ) }, text = { val userDisplayName = state.model.userDisplayName Text( text = userDisplayName - ?: stringResource(Res.strings.empty_value), + ?: stringResource(Res.string.empty_value), color = if (userDisplayName != null) { LocalContentColor.current } else { @@ -172,14 +173,14 @@ private fun ColumnScope.ContentOk( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.passkey_user_username), + text = stringResource(Res.string.passkey_user_username), ) }, text = { val userName = state.model.userName Text( text = userName - ?: stringResource(Res.strings.empty_value), + ?: stringResource(Res.string.empty_value), color = if (userName != null) { LocalContentColor.current } else { @@ -193,7 +194,7 @@ private fun ColumnScope.ContentOk( enabled = true, ) Section( - text = stringResource(Res.strings.info), + text = stringResource(Res.string.info), ) FlatItemLayout( leading = { @@ -203,7 +204,7 @@ private fun ColumnScope.ContentOk( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.passkey_relying_party), + text = stringResource(Res.string.passkey_relying_party), ) }, text = { @@ -243,14 +244,14 @@ private fun ColumnScope.ContentOk( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.passkey_signature_counter), + text = stringResource(Res.string.passkey_signature_counter), ) }, text = { val counter = state.model.counter?.toString() Text( text = counter - ?: stringResource(Res.strings.empty_value), + ?: stringResource(Res.string.empty_value), color = if (counter != null) { LocalContentColor.current } else { @@ -282,15 +283,15 @@ private fun ColumnScope.ContentOk( FlatItemTextContent2( title = { Text( - text = stringResource(Res.strings.passkey_discoverable), + text = stringResource(Res.string.passkey_discoverable), ) }, text = { val discoverable = state.model.discoverable .let { discoverable -> if (discoverable) { - stringResource(Res.strings.yes) - } else stringResource(Res.strings.no) + stringResource(Res.string.yes) + } else stringResource(Res.string.no) } Text( text = discoverable, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewStateProducer.kt index b08f40c7..55829f6e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/PasskeysCredentialViewStateProducer.kt @@ -13,6 +13,7 @@ import com.artemchep.keyguard.common.usecase.PasskeyTargetCheck import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import org.kodein.di.compose.localDI @@ -83,7 +84,7 @@ fun producePasskeysCredentialViewState( } val createdAt = translate( - Res.strings.vault_view_passkey_created_at_label, + Res.string.vault_view_passkey_created_at_label, dateFormatter.formatDateTime(credential.creationDate), ) val content = PasskeysCredentialViewState.Content( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceListScreen.kt index 46c76bb1..663afef7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceListScreen.kt @@ -37,6 +37,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.navigationNextEntryOrNull import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -48,7 +49,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -131,7 +132,7 @@ fun PasskeysListScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.passkeys_directory_title), + title = stringResource(Res.string.passkeys_directory_title), icon = { NavigationIcon() }, @@ -164,7 +165,7 @@ fun PasskeysListScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.passkeys_directory_search_placeholder), + placeholder = stringResource(Res.string.passkeys_directory_search_placeholder), searchIcon = false, count = count, leading = {}, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceViewScreen.kt index ac580981..6b1616cb 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServiceViewScreen.kt @@ -33,6 +33,7 @@ import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.tfa.directory.FlatLaunchBrowserItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.ScaffoldColumn @@ -44,7 +45,7 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun PasskeysViewDialogScreen( @@ -84,7 +85,7 @@ fun PasskeysViewDialogScreen( } Text( - text = stringResource(Res.strings.passkeys_directory_title), + text = stringResource(Res.string.passkeys_directory_title), style = MaterialTheme.typography.titleSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -112,7 +113,7 @@ fun PasskeysViewDialogScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -200,7 +201,7 @@ fun ColumnScope.Content( val category = state?.model?.category if (category != null) { Section( - text = stringResource(Res.strings.category), + text = stringResource(Res.string.category), ) Text( modifier = Modifier @@ -216,7 +217,7 @@ fun ColumnScope.Content( .height(16.dp), ) FlatLaunchBrowserItem( - title = stringResource(Res.strings.uri_action_launch_docs_title), + title = stringResource(Res.string.uri_action_launch_docs_title), url = documentationUrl, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServicesRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServicesRoute.kt index 0ef12676..3568f4f8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServicesRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passkeys/directory/PasskeysServicesRoute.kt @@ -4,10 +4,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Folder import androidx.compose.material.icons.outlined.Key import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.iconSmall @@ -15,7 +17,7 @@ import com.artemchep.keyguard.ui.icons.iconSmall object PasskeysServicesRoute : Route { const val ROUTER_NAME = "passkeys_services" - fun actionOrNull( + suspend fun actionOrNull( translator: TranslatorScope, navigate: (NavigationIntent) -> Unit, ) = action( @@ -23,13 +25,13 @@ object PasskeysServicesRoute : Route { navigate = navigate, ) - fun action( + suspend fun action( translator: TranslatorScope, navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.Folder, Icons.Outlined.Key), - title = translator.translate(Res.strings.passkeys_directory_title), - text = translator.translate(Res.strings.passkeys_directory_text), + title = Res.string.passkeys_directory_title.wrap(), + text = Res.string.passkeys_directory_text.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakRoute.kt index 39220c4b..1e173481 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakRoute.kt @@ -3,10 +3,12 @@ package com.artemchep.keyguard.feature.passwordleak import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.FactCheck import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.icon @@ -14,7 +16,7 @@ data class PasswordLeakRoute( val args: Args, ) : DialogRoute { companion object { - fun checkBreachesPasswordActionOrNull( + suspend fun checkBreachesPasswordActionOrNull( translator: TranslatorScope, password: String, navigate: (NavigationIntent) -> Unit, @@ -24,13 +26,13 @@ data class PasswordLeakRoute( navigate = navigate, ) - fun checkBreachesPasswordAction( + suspend fun checkBreachesPasswordAction( translator: TranslatorScope, password: String, navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.FactCheck), - title = translator.translate(Res.strings.password_action_check_data_breach_title), + title = Res.string.password_action_check_data_breach_title.wrap(), onClick = { val route = PasswordLeakRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakScreen.kt index e7e10138..8e9f008f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/passwordleak/PasswordLeakScreen.kt @@ -23,6 +23,7 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.common.usecase.NumberFormatter import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -32,7 +33,8 @@ import com.artemchep.keyguard.ui.poweredby.PoweredByHaveibeenpwned import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.pluralStringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance @Composable @@ -45,14 +47,14 @@ fun PasswordLeakScreen( Dialog( icon = icon(Icons.Outlined.FactCheck), title = { - Text(stringResource(Res.strings.passwordleak_title)) + Text(stringResource(Res.string.passwordleak_title)) }, content = { Column { Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.passwordleak_note), + text = stringResource(Res.string.passwordleak_note), style = MaterialTheme.typography.bodySmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -95,7 +97,7 @@ fun PasswordLeakScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -129,7 +131,7 @@ private fun ColumnScope.Content( if (leaks == null) { FlatSimpleNote( type = SimpleNote.Type.WARNING, - text = stringResource(Res.strings.passwordleak_failed_to_load_status_text), + text = stringResource(Res.string.passwordleak_failed_to_load_status_text), ) return } @@ -137,8 +139,8 @@ private fun ColumnScope.Content( if (leaks > 0) { FlatSimpleNote( type = SimpleNote.Type.WARNING, - title = stringResource(Res.strings.passwordleak_occurrences_found_title), - text = stringResource(Res.strings.passwordleak_occurrences_found_text), + title = stringResource(Res.string.passwordleak_occurrences_found_title), + text = stringResource(Res.string.passwordleak_occurrences_found_text), ) Spacer( modifier = Modifier @@ -148,7 +150,7 @@ private fun ColumnScope.Content( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource( + text = pluralStringResource( Res.plurals.passwordleak_occurrences_count_plural, leaks, numberFormatter.formatNumber(leaks), @@ -159,7 +161,7 @@ private fun ColumnScope.Content( } else { FlatSimpleNote( type = SimpleNote.Type.OK, - title = stringResource(Res.strings.passwordleak_occurrences_not_found_title), + title = stringResource(Res.string.passwordleak_occurrences_not_found_title), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterButton.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterButton.kt index 7509d75f..3c2cee95 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterButton.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterButton.kt @@ -8,7 +8,8 @@ import com.artemchep.keyguard.feature.search.component.DropdownButton import com.artemchep.keyguard.feature.search.filter.component.VaultHomeScreenFilterPaneNumberOfItems import com.artemchep.keyguard.feature.search.filter.model.FilterItemModel import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource @Composable fun FilterButton( @@ -21,7 +22,7 @@ fun FilterButton( DropdownButton( modifier = modifier, icon = Icons.Outlined.FilterAlt, - title = stringResource(Res.strings.filter_header_title), + title = stringResource(Res.string.filter_header_title), items = items, onClear = onClear, onSave = onSave, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterItems.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterItems.kt index 7ea03fc6..2c812a9b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterItems.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterItems.kt @@ -16,7 +16,8 @@ import com.artemchep.keyguard.feature.search.filter.component.FilterItemComposab import com.artemchep.keyguard.feature.search.filter.component.FilterSectionComposable import com.artemchep.keyguard.feature.search.filter.model.FilterItemModel import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalLayoutApi::class) @Composable @@ -26,7 +27,7 @@ fun ColumnScope.FilterItems( ) { if (items.isEmpty()) { EmptyItem( - text = stringResource(Res.strings.filter_empty_label), + text = stringResource(Res.string.filter_empty_label), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterScreen.kt index 3ff20b0c..9cfcc9fd 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/FilterScreen.kt @@ -18,12 +18,13 @@ import androidx.compose.ui.unit.dp import com.artemchep.keyguard.feature.search.filter.component.VaultHomeScreenFilterPaneNumberOfItems import com.artemchep.keyguard.feature.search.filter.model.FilterItemModel import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.FabState import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.SmallFab import com.artemchep.keyguard.ui.icons.IconBox -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun FilterScreen( @@ -69,7 +70,7 @@ fun FilterScreen( }, text = { Text( - text = stringResource(Res.strings.reset), + text = stringResource(Res.string.reset), ) }, color = MaterialTheme.colorScheme.secondaryContainer, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/component/VaultHomeScreenFilterPaneNumberOfItems.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/component/VaultHomeScreenFilterPaneNumberOfItems.kt index c6ad12d2..72c769d7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/component/VaultHomeScreenFilterPaneNumberOfItems.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/filter/component/VaultHomeScreenFilterPaneNumberOfItems.kt @@ -7,9 +7,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.animatedNumberText -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun VaultHomeScreenFilterPaneNumberOfItems( @@ -29,7 +30,7 @@ fun VaultHomeScreenFilterPaneNumberOfItems( top = 8.dp, bottom = 8.dp, ), - text = stringResource(Res.strings.items_n, animatedCount), + text = stringResource(Res.string.items_n, animatedCount), style = MaterialTheme.typography.titleSmall, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/sort/SortButton.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/sort/SortButton.kt index e47ab789..b4ea5528 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/sort/SortButton.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/search/sort/SortButton.kt @@ -13,7 +13,8 @@ import com.artemchep.keyguard.feature.search.sort.component.SortItemComposable import com.artemchep.keyguard.feature.search.sort.component.SortSectionComposable import com.artemchep.keyguard.feature.search.sort.model.SortItemModel import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource @Composable fun SortButton( @@ -24,7 +25,7 @@ fun SortButton( DropdownButton( modifier = modifier, icon = Icons.Outlined.SortByAlpha, - title = stringResource(Res.strings.sort_header_title), + title = stringResource(Res.string.sort_header_title), items = items, onClear = onClear, ) { @@ -40,7 +41,7 @@ private fun ColumnScope.SortItems( ) { if (items.isEmpty()) { EmptyItem( - text = stringResource(Res.strings.sort_empty_label), + text = stringResource(Res.string.sort_empty_label), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/SendListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/SendListStateProducer.kt index 37faa373..9ae6dc92 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/SendListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/SendListStateProducer.kt @@ -55,6 +55,7 @@ import com.artemchep.keyguard.feature.home.vault.search.find import com.artemchep.keyguard.feature.home.vault.search.findAlike import com.artemchep.keyguard.feature.home.vault.util.AlphabeticalSortMinItemsSize import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.PersistedStorage import com.artemchep.keyguard.feature.navigation.state.copy @@ -78,6 +79,7 @@ import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.platform.util.isRelease import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -85,7 +87,7 @@ import com.artemchep.keyguard.ui.icons.KeyguardView import com.artemchep.keyguard.ui.icons.SyncIcon import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.selection.selectionHandle -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -103,6 +105,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.serialization.Serializable +import org.jetbrains.compose.resources.getString import org.kodein.di.DirectDI import org.kodein.di.compose.localDI import org.kodein.di.direct @@ -297,7 +300,7 @@ fun sendListScreenState( onCheckedChange = showKeyboardSink::value::set, ) }, - title = translate(Res.strings.vault_action_always_show_keyboard_title), + title = Res.string.vault_action_always_show_keyboard_title.wrap(), onClick = showKeyboardSink::value::set.partially1(!showKeyboard), ) } @@ -309,7 +312,7 @@ fun sendListScreenState( rotating = syncing, ) }, - title = translate(Res.strings.vault_action_sync_vault_title), + title = Res.string.vault_action_sync_vault_title.wrap(), onClick = if (!syncing) { // lambda { @@ -325,7 +328,7 @@ fun sendListScreenState( leading = { Icon(Icons.Outlined.Lock, null) }, - title = translate(Res.strings.vault_action_lock_vault_title), + title = Res.string.vault_action_lock_vault_title.wrap(), onClick = { clearVaultSession() .launchIn(appScope) @@ -470,7 +473,7 @@ fun sendListScreenState( item = createComparatorAction( id = "title", icon = Icons.Outlined.SortByAlpha, - title = Res.strings.sortby_title_title, + title = Res.string.sortby_title_title, config = ComparatorHolder( comparator = AlphabeticalSendSort, favourites = true, @@ -479,7 +482,7 @@ fun sendListScreenState( subItems = listOf( createComparatorAction( id = "title_normal", - title = Res.strings.sortby_title_normal_mode, + title = Res.string.sortby_title_normal_mode, config = ComparatorHolder( comparator = AlphabeticalSendSort, favourites = true, @@ -487,7 +490,7 @@ fun sendListScreenState( ), createComparatorAction( id = "title_rev", - title = Res.strings.sortby_title_reverse_mode, + title = Res.string.sortby_title_reverse_mode, config = ComparatorHolder( comparator = AlphabeticalSendSort, reversed = true, @@ -500,7 +503,7 @@ fun sendListScreenState( item = createComparatorAction( id = "access_count", icon = Icons.Outlined.KeyguardView, - title = Res.strings.sortby_access_count_title, + title = Res.string.sortby_access_count_title, config = ComparatorHolder( comparator = AccessCountSendSort, ), @@ -508,14 +511,14 @@ fun sendListScreenState( subItems = listOf( createComparatorAction( id = "access_count_normal", - title = Res.strings.sortby_access_count_normal_mode, + title = Res.string.sortby_access_count_normal_mode, config = ComparatorHolder( comparator = AccessCountSendSort, ), ), createComparatorAction( id = "access_count_rev", - title = Res.strings.sortby_access_count_reverse_mode, + title = Res.string.sortby_access_count_reverse_mode, config = ComparatorHolder( comparator = AccessCountSendSort, reversed = true, @@ -527,7 +530,7 @@ fun sendListScreenState( item = createComparatorAction( id = "modify_date", icon = Icons.Outlined.CalendarMonth, - title = Res.strings.sortby_modification_date_title, + title = Res.string.sortby_modification_date_title, config = ComparatorHolder( comparator = LastModifiedSendSort, ), @@ -535,14 +538,14 @@ fun sendListScreenState( subItems = listOf( createComparatorAction( id = "modify_date_normal", - title = Res.strings.sortby_modification_date_normal_mode, + title = Res.string.sortby_modification_date_normal_mode, config = ComparatorHolder( comparator = LastModifiedSendSort, ), ), createComparatorAction( id = "modify_date_rev", - title = Res.strings.sortby_modification_date_reverse_mode, + title = Res.string.sortby_modification_date_reverse_mode, config = ComparatorHolder( comparator = LastModifiedSendSort, reversed = true, @@ -554,7 +557,7 @@ fun sendListScreenState( item = createComparatorAction( id = "expiration_date", icon = Icons.Outlined.CalendarMonth, - title = Res.strings.sortby_expiration_date_title, + title = Res.string.sortby_expiration_date_title, config = ComparatorHolder( comparator = LastExpiredSendSort, ), @@ -562,14 +565,14 @@ fun sendListScreenState( subItems = listOf( createComparatorAction( id = "expiration_date_normal", - title = Res.strings.sortby_expiration_date_normal_mode, + title = Res.string.sortby_expiration_date_normal_mode, config = ComparatorHolder( comparator = LastExpiredSendSort, ), ), createComparatorAction( id = "expiration_date_rev", - title = Res.strings.sortby_expiration_date_reverse_mode, + title = Res.string.sortby_expiration_date_reverse_mode, config = ComparatorHolder( comparator = LastExpiredSendSort, reversed = true, @@ -581,7 +584,7 @@ fun sendListScreenState( item = createComparatorAction( id = "deletion_date", icon = Icons.Outlined.CalendarMonth, - title = Res.strings.sortby_deletion_date_title, + title = Res.string.sortby_deletion_date_title, config = ComparatorHolder( comparator = LastDeletedSendSort, ), @@ -589,14 +592,14 @@ fun sendListScreenState( subItems = listOf( createComparatorAction( id = "deletion_date_normal", - title = Res.strings.sortby_deletion_date_normal_mode, + title = Res.string.sortby_deletion_date_normal_mode, config = ComparatorHolder( comparator = LastDeletedSendSort, ), ), createComparatorAction( id = "deletion_date_rev", - title = Res.strings.sortby_deletion_date_reverse_mode, + title = Res.string.sortby_deletion_date_reverse_mode, config = ComparatorHolder( comparator = LastDeletedSendSort, reversed = true, @@ -625,7 +628,7 @@ fun sendListScreenState( if (subItems.isNotEmpty()) { out += SendSortItem.Section( id = "sub_items_section", - text = TextHolder.Res(Res.strings.options), + text = TextHolder.Res(Res.string.options), ) out += subItems } @@ -688,11 +691,11 @@ fun sendListScreenState( ) .stateIn(this, SharingStarted.WhileSubscribed(), OurFilterResult()) - fun createTypeAction( + suspend fun createTypeAction( type: DSend.Type, ) = FlatItemAction( leading = icon(type.iconImageVector()), - title = translate(type.titleH()), + title = type.titleH().wrap(), onClick = { val route = SendAddRoute( args = SendAddRoute.Args( @@ -1094,31 +1097,30 @@ private fun hahah( else -> ItemDecoratorNone } - val items = sequence { - state.preferredList.forEach { item -> - yield(item) - } - if ( - state.preferredList.isNotEmpty() && - state.list.isNotEmpty() - ) { - val section = SendItem.Section( - id = "preferred.end", - text = "All items", - ) - yield(section) - } - state.list.forEach { item -> - val section = decorator.getOrNull(item) - if (section != null) yield(section) + val out = mutableListOf() + state.preferredList.forEach { item -> + out += item + } + if ( + state.preferredList.isNotEmpty() && + state.list.isNotEmpty() + ) { + val section = SendItem.Section( + id = "preferred.end", + text = "All items", + ) + out += section + } + state.list.forEach { item -> + val section = decorator.getOrNull(item) + if (section != null) out += section - yield(item) - } - }.toList() + out += item + } FilteredBoo( count = state.list.size, - list = items, - preferredList = items, + list = out, + preferredList = out, orderConfig = state.orderConfig, filterConfig = state.filterConfig, queryConfig = state.queryConfig, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/action/showInLargeTypeActionOrNull.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/action/showInLargeTypeActionOrNull.kt index c5b73e1d..5a820306 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/action/showInLargeTypeActionOrNull.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/action/showInLargeTypeActionOrNull.kt @@ -4,15 +4,17 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.Send import androidx.compose.material.icons.outlined.Share import com.artemchep.keyguard.common.model.DSend +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.feature.send.add.SendAddRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.icon -fun createSendActionOrNull( +suspend fun createSendActionOrNull( translator: TranslatorScope, name: String = "", text: String, @@ -24,14 +26,14 @@ fun createSendActionOrNull( navigate = navigate, ) -fun createSendAction( +suspend fun createSendAction( translator: TranslatorScope, name: String, text: String, navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.AutoMirrored.Outlined.Send), - title = translator.translate(Res.strings.text_action_send_title), + title = Res.string.text_action_send_title.wrap(), onClick = { val args = SendAddRoute.Args( type = DSend.Type.Text, @@ -44,7 +46,7 @@ fun createSendAction( }, ) -fun createShareAction( +suspend fun createShareAction( translator: TranslatorScope, text: String, navigate: (NavigationIntent) -> Unit, @@ -53,7 +55,7 @@ fun createShareAction( trailing = { ChevronIcon() }, - title = translator.translate(Res.strings.text_action_share_with_title), + title = Res.string.text_action_share_with_title.wrap(), onClick = { val intent = NavigationIntent.NavigateToShare( text = text, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddScreen.kt index 1dc0080a..093a85da 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.home.vault.add.AddState import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.FabState @@ -48,7 +49,7 @@ import com.artemchep.keyguard.ui.button.FavouriteToggleButton import com.artemchep.keyguard.ui.shimmer.shimmer import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SendAddScreen( @@ -127,7 +128,7 @@ fun SendAddScreen( }, text = { Text( - text = stringResource(Res.strings.save), + text = stringResource(Res.string.save), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddStateProducer.kt index f617f048..7b465551 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/add/SendAddStateProducer.kt @@ -63,14 +63,18 @@ import com.artemchep.keyguard.feature.auth.common.util.validatedTitle import com.artemchep.keyguard.feature.confirmation.organization.OrganizationConfirmationResult import com.artemchep.keyguard.feature.confirmation.organization.OrganizationConfirmationRoute import com.artemchep.keyguard.feature.home.vault.add.createItem +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.send.view.SendViewRoute import com.artemchep.keyguard.platform.parcelize.LeParcelable import com.artemchep.keyguard.platform.parcelize.LeParcelize import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.SimpleNote import com.artemchep.keyguard.ui.buildContextItems @@ -174,9 +178,9 @@ fun produceSendAddScreenState( val markdown = getMarkdown().first() val title = if (args.ownershipRo) { - translate(Res.strings.addsend_header_edit_title) + translate(Res.string.addsend_header_edit_title) } else { - translate(Res.strings.addsend_header_new_title) + translate(Res.string.addsend_header_new_title) } val ownershipFlow = produceOwnershipFlow( @@ -254,8 +258,8 @@ fun produceSendAddScreenState( val deactivate = AddStateItem.Switch( id = "deactivate", - title = translate(Res.strings.sends_action_disable_title), - text = translate(Res.strings.sends_action_disable_text), + title = translate(Res.string.sends_action_disable_title), + text = translate(Res.string.sends_action_disable_text), state = LocalStateItem( flow = kotlin.run { val sink = mutablePersistedFlow("deactivate") { @@ -288,8 +292,8 @@ fun produceSendAddScreenState( .map { model -> FlatItemAction( id = item.id, - title = item.title, - text = item.text, + title = TextHolder.Value(item.title), + text = item.text?.let(TextHolder::Value), trailing = { Switch( checked = model.checked, @@ -477,16 +481,16 @@ private suspend fun RememberStateFlowScope.produceOwnershipFlow( account = account.element, onClick = if (!readOnly) { // lambda - { + onClick { val route = registerRouteResultReceiver( route = OrganizationConfirmationRoute( args = OrganizationConfirmationRoute.Args( decor = OrganizationConfirmationRoute.Args.Decor( - title = translate(Res.strings.save_to), + title = translate(Res.string.save_to), icon = Icons.Outlined.AccountBox, note = if (requiresPremium) { SimpleNote( - text = translate(Res.strings.bitwarden_premium_required), + text = translate(Res.string.bitwarden_premium_required), type = SimpleNote.Type.INFO, ) } else { @@ -548,7 +552,7 @@ private suspend fun RememberStateFlowScope.produceTextState( val txt = args.initialValue?.text val text = createItem( key = "text", - label = translate(Res.strings.text), + label = translate(Res.string.text), initialValue = args.text ?: txt?.text, lens = CreateSendRequest.text.text, ) @@ -564,7 +568,7 @@ private suspend fun RememberStateFlowScope.produceTextState( factory = { id, state -> AddStateItem.Switch( id = id, - title = translate(Res.strings.addsend_text_hide_by_default_title), + title = translate(Res.string.addsend_text_hide_by_default_title), state = state, ) }, @@ -615,7 +619,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( onChange = state::value::set, ) AddStateItem.Text.State( - label = translate(Res.strings.max_access_count), + label = translate(Res.string.max_access_count), keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number, ), @@ -635,7 +639,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( AddStateItem.Text( id = id, leading = icon(Icons.Outlined.Visibility), - note = translate(Res.strings.addsend_max_access_count_note), + note = translate(Res.string.addsend_max_access_count_note), state = state, ) } @@ -644,7 +648,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( val label = kotlin.run { val hasPassword = args.initialValue?.hasPassword == true if (hasPassword) { - translate(Res.strings.new_password) + translate(Res.string.new_password) } else null } val state = LocalStateItem( @@ -687,17 +691,19 @@ private suspend fun RememberStateFlowScope.produceOptionsState( .takeIf { args.initialValue?.deletedDate == null } } val dropdown = buildContextItems { + val durationItems = opts.map { duration -> + val durationFormatted = duration.format(context) + FlatItemAction( + title = TextHolder.Value(durationFormatted), + onClick = sink::value::set.partially1(duration), + ) + } section { - opts.forEach { duration -> - this += FlatItemAction( - title = duration.format(context), - onClick = sink::value::set.partially1(duration), - ) - } + this += durationItems } section { this += FlatItemAction( - title = translate(Res.strings.deletion_date_custom), + title = Res.string.deletion_date_custom.wrap(), onClick = sink::value::set.partially1(null), ) } @@ -706,7 +712,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( flow = sink .map { duration -> val value = duration?.format(context) - ?: translate(Res.strings.deletion_date_custom) + ?: translate(Res.string.deletion_date_custom) AddStateItem.Enum.State( data = duration, value = value, @@ -722,7 +728,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( AddStateItem.Enum( id = id, leading = icon(Icons.Outlined.AutoDelete), - label = translate(Res.strings.deletion_date), + label = translate(Res.string.deletion_date), state = state, ) } @@ -736,11 +742,11 @@ private suspend fun RememberStateFlowScope.produceOptionsState( date = now.date.plus(deletionDateUpperLimitDays, DateTimeUnit.DAY), time = now.time, ) - val deletionDateWarning by lazy { + val deletionDateWarning = run { TextFieldModel2.Vl( type = TextFieldModel2.Vl.Type.ERROR, text = translate( - res = Res.strings.error_must_be_less_than_days, + res = Res.string.error_must_be_less_than_days, deletionDateUpperLimitDays, ), ) @@ -779,22 +785,27 @@ private suspend fun RememberStateFlowScope.produceOptionsState( .takeIf { args.initialValue?.expirationDate == null } } val dropdown = buildContextItems { - section { - opts.forEach { duration -> - this += FlatItemAction( - title = duration.format(context), - onClick = sink::value::set.partially1(duration), - ) - } + val durationItems = opts.map { duration -> + val durationFormatted = duration.format(context) + FlatItemAction( + title = TextHolder.Value(durationFormatted), + onClick = sink::value::set.partially1(duration), + ) + } + val durationInfinite = run { val duration = with(Duration) { INFINITE } - this += FlatItemAction( - title = duration.format(context), + FlatItemAction( + title = TextHolder.Value(duration.format(context)), onClick = sink::value::set.partially1(duration), ) } + section { + this += durationItems + this += durationInfinite + } section { this += FlatItemAction( - title = translate(Res.strings.expiration_date_custom), + title = Res.string.expiration_date_custom.wrap(), onClick = sink::value::set.partially1(null), ) } @@ -803,7 +814,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( flow = sink .map { duration -> val value = duration?.format(context) - ?: translate(Res.strings.expiration_date_custom) + ?: translate(Res.string.expiration_date_custom) AddStateItem.Enum.State( data = duration, value = value, @@ -819,7 +830,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( AddStateItem.Enum( id = id, leading = icon(Icons.Outlined.AccessTime), - label = translate(Res.strings.expiration_date), + label = translate(Res.string.expiration_date), state = state, ) } @@ -854,7 +865,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( factory = { id, state -> AddStateItem.Switch( id = id, - title = translate(Res.strings.addsend_hide_email_title), + title = translate(Res.string.addsend_hide_email_title), state = state, ) }, @@ -873,7 +884,7 @@ private suspend fun RememberStateFlowScope.produceOptionsState( val model = TextFieldModel2( state = state, text = value, - hint = translate(Res.strings.additem_note_placeholder), + hint = translate(Res.string.additem_note_placeholder), onChange = state::value::set, ) model diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/list/SendListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/list/SendListScreen.kt index b7ab52c9..31721f2f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/list/SendListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/list/SendListScreen.kt @@ -77,6 +77,7 @@ import com.artemchep.keyguard.feature.send.view.SendViewRoute import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBadgeIcon import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.CollectedEffect @@ -107,7 +108,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomSearchbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SendListScreen( @@ -192,9 +193,9 @@ fun SendListScreen( searchFieldModifier = Modifier .focusRequester2(focusRequester), searchFieldModel = state.query, - searchFieldPlaceholder = stringResource(Res.strings.send_main_search_placeholder), + searchFieldPlaceholder = stringResource(Res.string.send_main_search_placeholder), title = args.appBar?.title - ?: stringResource(Res.strings.send_main_header_title), + ?: stringResource(Res.string.send_main_header_title), subtitle = args.appBar?.subtitle, icon = { NavigationIcon() @@ -265,9 +266,9 @@ private fun SendScreenContent( searchFieldModifier = Modifier .focusRequester2(focusRequester), searchFieldModel = state.query, - searchFieldPlaceholder = stringResource(Res.strings.send_main_search_placeholder), + searchFieldPlaceholder = stringResource(Res.string.send_main_search_placeholder), title = title - ?: stringResource(Res.strings.send_main_header_title), + ?: stringResource(Res.string.send_main_header_title), subtitle = subtitle, icon = { NavigationIcon() @@ -345,7 +346,7 @@ private fun SendScreenContent( }, text = { Text( - text = stringResource(Res.strings.send_main_new_item_button), + text = stringResource(Res.string.send_main_new_item_button), ) }, ) @@ -525,7 +526,7 @@ fun VaultSendItemText( ) } else { Text( - text = stringResource(Res.strings.empty_value), + text = stringResource(Res.string.empty_value), color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha), overflow = TextOverflow.Ellipsis, @@ -649,12 +650,12 @@ fun VaultSendItemText( ) { if (item.source.disabled) { SmallInfoBadge( - text = stringResource(Res.strings.deactivated), + text = stringResource(Res.string.deactivated), ) } if (expiredState.value) { SmallInfoBadge( - text = stringResource(Res.strings.expired), + text = stringResource(Res.string.expired), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/search/SendListFilter.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/search/SendListFilter.kt index 29127dda..1bf009a1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/search/SendListFilter.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/search/SendListFilter.kt @@ -24,6 +24,7 @@ import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.send.search.filter.FilterSendHolder import com.artemchep.keyguard.feature.send.search.filter.SendFilterItem import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.AccentColors import com.artemchep.keyguard.ui.icons.IconBox import com.artemchep.keyguard.ui.icons.generateAccentColorsByAccountId @@ -290,7 +291,7 @@ suspend fun < icon = icon, ) - fun createTypeFilterAction( + suspend fun createTypeFilterAction( type: DSend.Type, ) = createFilterAction( sectionId = typeSectionId, @@ -328,7 +329,7 @@ suspend fun < } .aaa( sectionId = accountSectionId, - sectionTitle = translate(Res.strings.account), + sectionTitle = translate(Res.string.account), ) .filterSection(params.section.account) @@ -349,7 +350,7 @@ suspend fun < } .aaa( sectionId = typeSectionId, - sectionTitle = translate(Res.strings.type), + sectionTitle = translate(Res.string.type), ) .filterSection(params.section.type) @@ -362,7 +363,7 @@ suspend fun < } .aaa( sectionId = miscSectionId, - sectionTitle = translate(Res.strings.misc), + sectionTitle = translate(Res.string.misc), collapse = false, ) .filterSection(params.section.misc) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/util/SendUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/util/SendUtil.kt index 776d89a2..56753f2b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/util/SendUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/util/SendUtil.kt @@ -20,11 +20,15 @@ import com.artemchep.keyguard.common.usecase.SendToolbox import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase import com.artemchep.keyguard.feature.confirmation.ConfirmationResult import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope +import com.artemchep.keyguard.feature.navigation.state.onClick +import com.artemchep.keyguard.feature.navigation.state.translate import com.artemchep.keyguard.platform.util.isRelease import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -55,14 +59,14 @@ object SendUtil { val icon = icon(Icons.Outlined.Edit) val title = if (sends.size > 1) { - translate(Res.strings.sends_action_change_names_title) + Res.string.sends_action_change_names_title.wrap() } else { - translate(Res.strings.sends_action_change_name_title) + Res.string.sends_action_change_name_title.wrap() } FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = sends @@ -80,7 +84,7 @@ object SendUtil { route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon, - title = title, + title = translate(title), items = items, ), ), @@ -127,14 +131,14 @@ object SendUtil { val icon = iconSmall(Icons.Outlined.Attachment, Icons.Outlined.Edit) val title = if (sends.size > 1) { - translate(Res.strings.sends_action_change_filenames_title) + Res.string.sends_action_change_filenames_title } else { - translate(Res.strings.sends_action_change_filename_title) - } + Res.string.sends_action_change_filename_title + }.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = sends @@ -152,7 +156,7 @@ object SendUtil { route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon, - title = title, + title = translate(title), items = items, ), ), @@ -178,7 +182,7 @@ object SendUtil { } context(RememberStateFlowScope) - fun changePasswordActionOrNull( + suspend fun changePasswordActionOrNull( patchSendById: PatchSendById, sends: List, canEdit: Boolean, @@ -194,21 +198,21 @@ object SendUtil { val icon = iconSmall(Icons.Outlined.Password) val title = if (hasPasswords) { if (sends.size > 1) { - translate(Res.strings.sends_action_change_passwords_title) + Res.string.sends_action_change_passwords_title } else { - translate(Res.strings.sends_action_change_password_title) + Res.string.sends_action_change_password_title } } else { if (sends.size > 1) { - translate(Res.strings.sends_action_set_passwords_title) + Res.string.sends_action_set_passwords_title } else { - translate(Res.strings.sends_action_set_password_title) + Res.string.sends_action_set_password_title } - } + }.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val items = sends @@ -226,11 +230,11 @@ object SendUtil { route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon, - title = title, + title = translate(title), message = if (hasPasswords) { null } else { - translate(Res.strings.sends_action_set_password_confirmation_message) + translate(Res.string.sends_action_set_password_confirmation_message) }, items = items, ), @@ -276,14 +280,14 @@ object SendUtil { val icon = iconSmall(Icons.Outlined.Password, Icons.Outlined.Remove) val title = if (sends.size > 1) { - translate(Res.strings.sends_action_remove_passwords_title) + Res.string.sends_action_remove_passwords_title } else { - translate(Res.strings.sends_action_remove_password_title) - } + Res.string.sends_action_remove_password_title + }.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val route = registerRouteResultReceiver( @@ -291,11 +295,11 @@ object SendUtil { args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.Password, Icons.Outlined.Remove), title = if (sends.size > 1) { - translate(Res.strings.sends_action_remove_passwords_confirmation_title) + translate(Res.string.sends_action_remove_passwords_confirmation_title) } else { - translate(Res.strings.sends_action_remove_password_confirmation_title) + translate(Res.string.sends_action_remove_password_confirmation_title) }, - message = translate(Res.strings.sends_action_remove_password_confirmation_message), + message = translate(Res.string.sends_action_remove_password_confirmation_message), ), ), ) { result -> @@ -349,7 +353,7 @@ object SendUtil { after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = iconSmall(Icons.Outlined.Email, Icons.Outlined.Visibility) - val title = translate(Res.strings.sends_action_show_email_title) + val title = Res.string.sends_action_show_email_title.wrap() FlatItemAction( leading = icon, title = title, @@ -398,7 +402,7 @@ object SendUtil { after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = iconSmall(Icons.Outlined.Email, Icons.Outlined.VisibilityOff) - val title = translate(Res.strings.sends_action_hide_email_title) + val title = Res.string.sends_action_hide_email_title.wrap() FlatItemAction( leading = icon, title = title, @@ -447,19 +451,19 @@ object SendUtil { after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Stub) - val title = translate(Res.strings.sends_action_enable_title) - val text = translate(Res.strings.sends_action_enable_text) + val title = Res.string.sends_action_enable_title.wrap() + val text = Res.string.sends_action_enable_text.wrap() FlatItemAction( leading = icon, title = title, text = text, - onClick = { + onClick = onClick { before?.invoke() val route = registerRouteResultReceiver( route = ConfirmationRoute( args = ConfirmationRoute.Args( - title = translate(Res.strings.sends_action_enable_confirmation_title), + title = translate(Res.string.sends_action_enable_confirmation_title), ), ), ) { result -> @@ -513,19 +517,19 @@ object SendUtil { after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Stub) - val title = translate(Res.strings.sends_action_disable_title) - val text = translate(Res.strings.sends_action_disable_text) + val title = Res.string.sends_action_disable_title.wrap() + val text = Res.string.sends_action_disable_text.wrap() FlatItemAction( leading = icon, title = title, text = text, - onClick = { + onClick = onClick { before?.invoke() val route = registerRouteResultReceiver( route = ConfirmationRoute( args = ConfirmationRoute.Args( - title = translate(Res.strings.sends_action_disable_confirmation_title), + title = translate(Res.string.sends_action_disable_confirmation_title), ), ), ) { result -> @@ -575,18 +579,18 @@ object SendUtil { after: ((Boolean) -> Unit)? = null, ) = kotlin.run { val icon = icon(Icons.Outlined.DeleteForever) - val title = translate(Res.strings.sends_action_delete_title) + val title = Res.string.sends_action_delete_title.wrap() FlatItemAction( leading = icon, title = title, - onClick = { + onClick = onClick { before?.invoke() val route = registerRouteResultReceiver( route = ConfirmationRoute( args = ConfirmationRoute.Args( icon = icon(Icons.Outlined.DeleteForever), - title = translate(Res.strings.sends_action_delete_confirmation_title), + title = translate(Res.string.sends_action_delete_confirmation_title), ), ), ) { result -> @@ -638,7 +642,7 @@ object SendUtil { } context(RememberStateFlowScope) - fun actions( + suspend fun actions( toolbox: SendToolbox, sends: List, canEdit: Boolean, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewScreen.kt index ebf5ba66..5a1147de 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewScreen.kt @@ -46,6 +46,7 @@ import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevati import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Avatar import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DisabledEmphasisAlpha @@ -63,7 +64,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonText import com.artemchep.keyguard.ui.text.AutoSizeText import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SendViewScreen( @@ -146,7 +147,7 @@ fun SendViewScreen( }, text = { Text( - text = stringResource(Res.strings.copy_send), + text = stringResource(Res.string.copy_send), ) }, ) @@ -326,7 +327,7 @@ private fun VaultViewTitle( ) } else { Text( - text = stringResource(Res.strings.empty_value), + text = stringResource(Res.string.empty_value), color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha), maxLines = 1, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewStateProducer.kt index 598f7fab..c7d75d5f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/send/view/SendViewStateProducer.kt @@ -74,6 +74,8 @@ import com.artemchep.keyguard.feature.favicon.FaviconUrl import com.artemchep.keyguard.feature.filepicker.humanReadableByteCountSI import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem import com.artemchep.keyguard.feature.largetype.LargeTypeRoute +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope import com.artemchep.keyguard.feature.navigation.state.copy @@ -84,6 +86,7 @@ import com.artemchep.keyguard.feature.send.add.SendAddRoute import com.artemchep.keyguard.feature.send.toVaultItemIcon import com.artemchep.keyguard.feature.send.util.SendUtil import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.autoclose.launchAutoPopSelfHandler import com.artemchep.keyguard.ui.buildContextItems @@ -357,8 +360,8 @@ private fun RememberStateFlowScope.oh( if (send.disabled) { val model = VaultViewItem.Info( id = "disabled", - name = translate(Res.strings.deactivated), - message = translate(Res.strings.sends_action_disabled_note), + name = translate(Res.string.deactivated), + message = translate(Res.string.sends_action_disabled_note), ) emit(model) } @@ -368,7 +371,7 @@ private fun RememberStateFlowScope.oh( val model = create( copy = copy, id = "text.text", - title = translate(Res.strings.text), + title = translate(Res.string.text), send = send.name, value = text.text.orEmpty(), elevated = true, @@ -400,7 +403,7 @@ private fun RememberStateFlowScope.oh( if (url != null) { val section = VaultViewItem.Section( id = "url", - text = translate(Res.strings.public_url), + text = translate(Res.string.public_url), ) emit(section) emit(url) @@ -409,7 +412,7 @@ private fun RememberStateFlowScope.oh( val w = VaultViewItem.Label( id = "url.password", text = AnnotatedString( - text = translate(Res.strings.send_password_is_required_to_access_label), + text = translate(Res.string.send_password_is_required_to_access_label), ), ) emit(w) @@ -418,14 +421,14 @@ private fun RememberStateFlowScope.oh( val section = VaultViewItem.Section( id = "iiinfo", - text = translate(Res.strings.info), + text = translate(Res.string.info), ) emit(section) val accessCount = send.accessCount val w = VaultViewItem.Value( id = "info", - title = translate(Res.strings.access_count), + title = translate(Res.string.access_count), value = "$accessCount" + send.maxAccessCount?.let { " / $it" }.orEmpty(), leading = { IconBox(Icons.Outlined.KeyguardView) @@ -435,11 +438,11 @@ private fun RememberStateFlowScope.oh( val w22 = VaultViewItem.Value( id = "info.email", - title = translate(Res.strings.email_visibility), + title = translate(Res.string.email_visibility), value = if (send.hideEmail) { - translate(Res.strings.hidden) + translate(Res.string.hidden) } else { - translate(Res.strings.visible) + translate(Res.string.visible) }, leading = { IconBox(Icons.Outlined.Email) @@ -450,7 +453,7 @@ private fun RememberStateFlowScope.oh( if (send.notes.isNotEmpty()) { val section = VaultViewItem.Section( id = "note", - text = translate(Res.strings.notes), + text = translate(Res.string.notes), ) emit(section) val content = VaultViewItem.Note.Content.of( @@ -473,7 +476,7 @@ private fun RememberStateFlowScope.oh( val x = VaultViewItem.Label( id = "account", text = annotate( - Res.strings.vault_view_saved_to_label, + Res.string.vault_view_saved_to_label, account.username to SpanStyle( color = contentColor, ), @@ -489,7 +492,7 @@ private fun RememberStateFlowScope.oh( id = "created", text = AnnotatedString( translate( - Res.strings.vault_view_created_at_label, + Res.string.vault_view_created_at_label, dateFormatter.formatDateTime(createdDate), ), ), @@ -501,7 +504,7 @@ private fun RememberStateFlowScope.oh( id = "revision", text = AnnotatedString( translate( - Res.strings.vault_view_revision_label, + Res.string.vault_view_revision_label, dateFormatter.formatDateTime(send.revisionDate), ), ), @@ -513,7 +516,7 @@ private fun RememberStateFlowScope.oh( id = "expiration", text = AnnotatedString( translate( - Res.strings.vault_view_expiration_scheduled_at_label, + Res.string.vault_view_expiration_scheduled_at_label, dateFormatter.formatDateTime(expirationDate), ), ), @@ -526,7 +529,7 @@ private fun RememberStateFlowScope.oh( id = "deleted", text = AnnotatedString( translate( - Res.strings.vault_view_deletion_scheduled_at_label, + Res.string.vault_view_deletion_scheduled_at_label, dateFormatter.formatDateTime(deletedDate), ), ), @@ -535,7 +538,7 @@ private fun RememberStateFlowScope.oh( } } -fun RememberStateFlowScope.create( +suspend fun RememberStateFlowScope.create( copy: CopyText, id: String, title: String?, @@ -553,7 +556,7 @@ fun RememberStateFlowScope.create( buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy), + title = Res.string.copy.wrap(), value = value, hidden = private, ) @@ -625,15 +628,15 @@ private suspend fun RememberStateFlowScope.aaaa( val dropdown = buildContextItems { section { this += copy.FlatItemAction( - title = translate(Res.strings.copy_url), + title = Res.string.copy_url.wrap(), value = url, ) } section { this += FlatItemAction( icon = Icons.Outlined.Launch, - title = translate(Res.strings.uri_action_launch_browser_title), - text = url, + title = Res.string.uri_action_launch_browser_title.wrap(), + text = TextHolder.Value(url), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncScreen.kt index d40362a2..6b3258b4 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncScreen.kt @@ -31,8 +31,10 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.unit.dp import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.common.model.fold +import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Ah import com.artemchep.keyguard.ui.AhContainer import com.artemchep.keyguard.ui.FlatItem @@ -49,7 +51,7 @@ import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.ok import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun SyncScreen() { @@ -83,7 +85,7 @@ private fun SyncContent( LargeToolbar( title = { Text( - text = stringResource(Res.strings.syncstatus_header_title), + text = stringResource(Res.string.syncstatus_header_title), ) }, navigationIcon = { @@ -209,7 +211,9 @@ private fun TestK( ChevronIcon() }, title = { - Text(action.title) + Text( + text = textResource(action.title), + ) }, elevation = 1.dp, onClick = action.onClick, @@ -234,7 +238,7 @@ private fun BadgeStatusUpToDate( Ah( modifier = modifier, score = 1f, - text = stringResource(Res.strings.syncstatus_status_up_to_date), + text = stringResource(Res.string.syncstatus_status_up_to_date), ) } @@ -300,6 +304,6 @@ private fun BadgeStatusFailed( Ah( modifier = modifier, score = 0f, - text = stringResource(Res.strings.syncstatus_status_failed), + text = stringResource(Res.string.syncstatus_status_failed), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncStateProducer.kt index b7358912..912e2a5a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/sync/SyncStateProducer.kt @@ -19,9 +19,12 @@ import com.artemchep.keyguard.feature.auth.AccountViewRoute import com.artemchep.keyguard.feature.home.vault.VaultRoute import com.artemchep.keyguard.feature.home.vault.folders.FoldersRoute import com.artemchep.keyguard.feature.home.vault.screen.VaultListRoute +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.buildContextItems import kotlinx.coroutines.flow.combine @@ -135,7 +138,7 @@ fun produceSyncState( val timestamp = c.meta?.lastSyncTimestamp if (timestamp != null) { val date = dateFormatter.formatDateTime(timestamp) - translate(Res.strings.account_last_synced_at, date) + translate(Res.string.account_last_synced_at, date) } else { null } @@ -160,8 +163,8 @@ fun produceSyncState( val items = buildContextItems { if (c.failedCiphersCount > 0) { this += FlatItemAction( - title = translate(Res.strings.items), - onClick = { + title = Res.string.items.wrap(), + onClick = onClick { val filter = DFilter.And( listOf( DFilter.ById( @@ -176,8 +179,8 @@ fun produceSyncState( val route = VaultListRoute( args = VaultRoute.Args( appBar = VaultRoute.Args.AppBar( - title = translate(Res.strings.items), - subtitle = translate(Res.strings.syncstatus_header_title), + title = translate(Res.string.items), + subtitle = translate(Res.string.syncstatus_header_title), ), filter = filter, trash = null, @@ -192,7 +195,7 @@ fun produceSyncState( } if (c.failedFoldersCount > 0) { this += FlatItemAction( - title = translate(Res.strings.folders), + title = Res.string.folders.wrap(), onClick = { val filter = DFilter.And( listOf( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/team/AboutTeamScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/team/AboutTeamScreen.kt index ff78db75..afe01876 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/team/AboutTeamScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/team/AboutTeamScreen.kt @@ -29,6 +29,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Avatar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -41,9 +42,9 @@ import com.artemchep.keyguard.ui.toolbar.LargeToolbar import compose.icons.FeatherIcons import compose.icons.feathericons.Github import compose.icons.feathericons.Instagram -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.toPersistentList +import org.jetbrains.compose.resources.painterResource private data class SocialNetwork( val title: String, @@ -81,7 +82,7 @@ fun AboutTeamScreen() { modifier = Modifier .size(24.dp) .padding(1.dp), - painter = painterResource(Res.images.ic_mastodon), + painter = painterResource(Res.drawable.ic_mastodon), contentDescription = null, ) }, @@ -134,7 +135,7 @@ fun AboutTeamScreen() { LargeToolbar( title = { Text( - text = stringResource(Res.strings.team_header_title), + text = stringResource(Res.string.team_header_title), ) }, navigationIcon = { @@ -155,10 +156,10 @@ fun AboutTeamScreen() { Text( modifier = Modifier .padding(horizontal = 16.dp), - text = stringResource(Res.strings.team_artem_whoami_text), + text = stringResource(Res.string.team_artem_whoami_text), ) Section( - text = stringResource(Res.strings.team_follow_me_section), + text = stringResource(Res.string.team_follow_me_section), ) socialNetworks.forEach { item -> FlatItem( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceListScreen.kt index 5eb31188..fad7e0a3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceListScreen.kt @@ -37,6 +37,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.navigationNextEntryOrNull import com.artemchep.keyguard.feature.twopane.LocalHasDetailPane import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultProgressBar import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.ScaffoldLazyColumn @@ -48,7 +49,7 @@ import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.toolbar.CustomToolbar import com.artemchep.keyguard.ui.toolbar.content.CustomToolbarContent -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filter @@ -131,7 +132,7 @@ fun TwoFaServiceListScreen( ) { Column { CustomToolbarContent( - title = stringResource(Res.strings.tfa_directory_title), + title = stringResource(Res.string.tfa_directory_title), icon = { NavigationIcon() }, @@ -164,7 +165,7 @@ fun TwoFaServiceListScreen( modifier = Modifier .focusRequester2(focusRequester), text = queryText, - placeholder = stringResource(Res.strings.tfa_directory_search_placeholder), + placeholder = stringResource(Res.string.tfa_directory_search_placeholder), searchIcon = false, count = count, leading = {}, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceViewScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceViewScreen.kt index c8e853f7..dcdc7558 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceViewScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServiceViewScreen.kt @@ -35,6 +35,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.MediumEmphasisAlpha @@ -49,7 +50,7 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.monoFontFamily import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun TwoFaServiceViewDialogScreen( @@ -90,7 +91,7 @@ fun TwoFaServiceViewDialogScreen( } Text( - text = stringResource(Res.strings.tfa_directory_title), + text = stringResource(Res.string.tfa_directory_title), style = MaterialTheme.typography.titleSmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -118,7 +119,7 @@ fun TwoFaServiceViewDialogScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -211,7 +212,7 @@ fun ColumnScope.Content( val websiteUrl = state?.model?.url if (websiteUrl != null) { FlatLaunchBrowserItem( - title = stringResource(Res.strings.uri_action_launch_website_title), + title = stringResource(Res.string.uri_action_launch_website_title), url = websiteUrl, ) } @@ -219,7 +220,7 @@ fun ColumnScope.Content( val documentationUrl = state?.model?.documentation if (documentationUrl != null) { FlatLaunchBrowserItem( - title = stringResource(Res.strings.uri_action_launch_docs_title), + title = stringResource(Res.string.uri_action_launch_docs_title), url = documentationUrl, ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServicesRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServicesRoute.kt index dca8326f..b90b290f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServicesRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/tfa/directory/TwoFaServicesRoute.kt @@ -3,10 +3,12 @@ package com.artemchep.keyguard.feature.tfa.directory import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Folder import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.Route import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.ChevronIcon import com.artemchep.keyguard.ui.icons.KeyguardTwoFa @@ -15,7 +17,7 @@ import com.artemchep.keyguard.ui.icons.iconSmall object TwoFaServicesRoute : Route { const val ROUTER_NAME = "twofa_services" - fun actionOrNull( + suspend fun actionOrNull( translator: TranslatorScope, navigate: (NavigationIntent) -> Unit, ) = action( @@ -23,13 +25,13 @@ object TwoFaServicesRoute : Route { navigate = navigate, ) - fun action( + suspend fun action( translator: TranslatorScope, navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = iconSmall(Icons.Outlined.Folder, Icons.Outlined.KeyguardTwoFa), - title = translator.translate(Res.strings.tfa_directory_title), - text = translator.translate(Res.strings.tfa_directory_text), + title = Res.string.tfa_directory_title.wrap(), + text = Res.string.tfa_directory_text.wrap(), trailing = { ChevronIcon() }, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/timepicker/TimePickerScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/timepicker/TimePickerScreen.kt index 2b8c7720..c3ab85ce 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/timepicker/TimePickerScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/timepicker/TimePickerScreen.kt @@ -19,8 +19,9 @@ import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.Dimens -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.datetime.LocalTime @@ -57,7 +58,7 @@ fun TimePickerScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } TextButton( enabled = updatedOnOk != null, @@ -65,7 +66,7 @@ fun TimePickerScreen( updatedOnOk?.invoke() }, ) { - Text(stringResource(Res.strings.ok)) + Text(stringResource(Res.string.ok)) } }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListScreen.kt index 3b4b61e7..8b554eb9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListScreen.kt @@ -48,6 +48,7 @@ import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.AvatarBuilder import com.artemchep.keyguard.ui.DefaultFab import com.artemchep.keyguard.ui.DefaultSelection @@ -59,7 +60,7 @@ import com.artemchep.keyguard.ui.ScaffoldLazyColumn import com.artemchep.keyguard.ui.icons.IconBox import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.withIndex @@ -111,7 +112,7 @@ fun EmailRelayListScreen( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.urloverride_list_header_title)) + Text(stringResource(Res.string.urloverride_list_header_title)) }, navigationIcon = { NavigationIcon() @@ -158,7 +159,7 @@ fun EmailRelayListScreen( }, text = { Text( - text = stringResource(Res.strings.add), + text = stringResource(Res.string.add), ) }, ) @@ -221,7 +222,7 @@ private fun NoItemsPlaceholder( modifier = modifier, text = { Text( - text = stringResource(Res.strings.urloverride_empty_label), + text = stringResource(Res.string.urloverride_empty_label), ) }, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListStateProducer.kt index d786b5aa..4298fed9 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/urloverride/UrlOverrideListStateProducer.kt @@ -25,10 +25,13 @@ import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogInten import com.artemchep.keyguard.feature.crashlytics.crashlyticsAttempt import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon import com.artemchep.keyguard.feature.home.vault.model.short +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.Selection import com.artemchep.keyguard.ui.buildContextItems @@ -77,12 +80,12 @@ fun produceUrlOverrideListState( ) { val selectionHandle = selectionHandle("selection") - fun onEdit(entity: DGlobalUrlOverride?) { + suspend fun onEdit(entity: DGlobalUrlOverride?) { val nameKey = "name" val nameItem = ConfirmationRoute.Args.Item.StringItem( key = nameKey, value = entity?.name.orEmpty(), - title = translate(Res.strings.generic_name), + title = translate(Res.string.generic_name), type = ConfirmationRoute.Args.Item.StringItem.Type.Text, canBeEmpty = false, ) @@ -91,18 +94,18 @@ fun produceUrlOverrideListState( val enabledItem = ConfirmationRoute.Args.Item.BooleanItem( key = enabledKey, value = entity?.enabled ?: true, - title = translate(Res.strings.enabled), + title = translate(Res.string.enabled), ) val regexKey = "regex" val regexItem = ConfirmationRoute.Args.Item.StringItem( key = regexKey, value = entity?.regex?.toString().orEmpty(), - title = translate(Res.strings.regex), + title = translate(Res.string.regex), // A hint explains how would a user write a regex that // matches both HTTPS and HTTP schemes. hint = "^https?://.*", - description = translate(Res.strings.urloverride_regex_note), + description = translate(Res.string.urloverride_regex_note), type = ConfirmationRoute.Args.Item.StringItem.Type.Regex, canBeEmpty = false, ) @@ -111,7 +114,7 @@ fun produceUrlOverrideListState( val commandItem = ConfirmationRoute.Args.Item.StringItem( key = commandKey, value = entity?.command.orEmpty(), - title = translate(Res.strings.command), + title = translate(Res.string.command), // A hint explains how would a user write a command that // converts all links to use the HTTPS scheme. hint = "https://{url:rmvscm}", @@ -136,7 +139,7 @@ fun produceUrlOverrideListState( Icons.Outlined.Add }, ), - title = translate(Res.strings.urloverride_header_title), + title = translate(Res.string.urloverride_header_title), items = items2, ), ), @@ -167,9 +170,9 @@ fun produceUrlOverrideListState( navigate(intent) } - fun onNew() = onEdit(null) + suspend fun onNew() = onEdit(null) - fun onDuplicate(entity: DGlobalUrlOverride) { + suspend fun onDuplicate(entity: DGlobalUrlOverride) { val createdAt = Clock.System.now() val model = entity.copy( id = null, @@ -179,13 +182,13 @@ fun produceUrlOverrideListState( .launchIn(appScope) } - fun onDeleteByItems( + suspend fun onDeleteByItems( items: List, ) { val title = if (items.size > 1) { - translate(Res.strings.urloverride_delete_many_confirmation_title) + translate(Res.string.urloverride_delete_many_confirmation_title) } else { - translate(Res.strings.urloverride_delete_one_confirmation_title) + translate(Res.string.urloverride_delete_one_confirmation_title) } val message = items .joinToString(separator = "\n") { it.name } @@ -238,9 +241,12 @@ fun produceUrlOverrideListState( section { this += FlatItemAction( leading = icon(Icons.Outlined.Delete), - title = translate(Res.strings.delete), - onClick = ::onDeleteByItems - .partially1(selectedItems), + title = Res.string.delete.wrap(), + onClick = onClick { + onDeleteByItems( + items = selectedItems, + ) + }, ) } } @@ -268,21 +274,30 @@ fun produceUrlOverrideListState( section { this += FlatItemAction( icon = Icons.Outlined.Edit, - title = translate(Res.strings.edit), - onClick = ::onEdit - .partially1(it), + title = Res.string.edit.wrap(), + onClick = onClick { + onEdit( + entity = it, + ) + }, ) this += FlatItemAction( icon = Icons.Outlined.CopyAll, - title = translate(Res.strings.duplicate), - onClick = ::onDuplicate - .partially1(it), + title = Res.string.duplicate.wrap(), + onClick = onClick { + onDuplicate( + entity = it, + ) + }, ) this += FlatItemAction( icon = Icons.Outlined.Delete, - title = translate(Res.strings.delete), - onClick = ::onDeleteByItems - .partially1(listOf(it)), + title = Res.string.delete.wrap(), + onClick = onClick { + onDeleteByItems( + items = listOf(it), + ) + }, ) } } @@ -358,7 +373,9 @@ fun produceUrlOverrideListState( revision = 0, items = items, selection = selection, - primaryAction = ::onNew, + primaryAction = onClick { + onNew() + }, ) } Loadable.Ok(contentOrException) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerScreen.kt index 9eebbb94..0eb3d579 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerScreen.kt @@ -89,6 +89,7 @@ import com.artemchep.keyguard.feature.search.filter.FilterButton import com.artemchep.keyguard.feature.search.filter.FilterScreen import com.artemchep.keyguard.feature.twopane.TwoPaneScreen import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.Ah import com.artemchep.keyguard.ui.DefaultEmphasisAlpha import com.artemchep.keyguard.ui.DisabledEmphasisAlpha @@ -124,7 +125,7 @@ import com.artemchep.keyguard.ui.theme.ok import com.artemchep.keyguard.ui.theme.warning import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.toolbar.SmallToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlin.math.roundToInt @@ -155,7 +156,7 @@ fun WatchtowerScreen( containerColor = Color.Transparent, title = { Text( - text = stringResource(Res.strings.watchtower_header_title), + text = stringResource(Res.string.watchtower_header_title), ) }, navigationIcon = { @@ -242,7 +243,7 @@ fun WatchtowerScreen2( LargeToolbar( title = { Text( - text = stringResource(Res.strings.watchtower_header_title), + text = stringResource(Res.string.watchtower_header_title), ) }, navigationIcon = { @@ -474,7 +475,7 @@ private fun ColumnScope.DashboardContentData( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPaddingHalf), - text = stringResource(Res.strings.watchtower_section_password_strength_label), + text = stringResource(Res.string.watchtower_section_password_strength_label), ) } Spacer( @@ -706,10 +707,10 @@ private fun CardPwnedPassword( ContentCardsContentTitle( icon = WatchtowerStatusIcon.ERROR.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_pwned_passwords_title), + title = stringResource(Res.string.watchtower_item_pwned_passwords_title), ) }, - text = stringResource(Res.strings.watchtower_item_pwned_passwords_text), + text = stringResource(Res.string.watchtower_item_pwned_passwords_text), imageVector = Icons.Outlined.KeyguardPwnedPassword, onClick = state.onClick, content = { @@ -732,10 +733,10 @@ private fun CardReusedPassword( ContentCardsContentTitle( icon = WatchtowerStatusIcon.ERROR.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_reused_passwords_title), + title = stringResource(Res.string.watchtower_item_reused_passwords_title), ) }, - text = stringResource(Res.strings.watchtower_item_reused_passwords_text), + text = stringResource(Res.string.watchtower_item_reused_passwords_text), imageVector = Icons.Outlined.KeyguardReusedPassword, onClick = state.onClick, ) @@ -751,10 +752,10 @@ private fun CardVulnerableAccounts( ContentCardsContentTitle( icon = WatchtowerStatusIcon.ERROR.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_vulnerable_accounts_title), + title = stringResource(Res.string.watchtower_item_vulnerable_accounts_title), ) }, - text = stringResource(Res.strings.watchtower_item_vulnerable_accounts_text), + text = stringResource(Res.string.watchtower_item_vulnerable_accounts_text), imageVector = Icons.Outlined.KeyguardPwnedWebsites, onClick = state.onClick, content = { @@ -777,10 +778,10 @@ private fun CardUnsecureWebsites( ContentCardsContentTitle( icon = WatchtowerStatusIcon.WARNING.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_unsecure_websites_title), + title = stringResource(Res.string.watchtower_item_unsecure_websites_title), ) }, - text = stringResource(Res.strings.watchtower_item_unsecure_websites_text), + text = stringResource(Res.string.watchtower_item_unsecure_websites_text), imageVector = Icons.Outlined.KeyguardUnsecureWebsites, onClick = state.onClick, ) @@ -796,10 +797,10 @@ private fun CardCompromisedAccount( ContentCardsContentTitle( icon = WatchtowerStatusIcon.WARNING.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_compromised_accounts_title), + title = stringResource(Res.string.watchtower_item_compromised_accounts_title), ) }, - text = stringResource(Res.strings.watchtower_item_compromised_accounts_text), + text = stringResource(Res.string.watchtower_item_compromised_accounts_text), imageVector = Icons.Outlined.AccountTree, onClick = state.onClick, content = { @@ -822,10 +823,10 @@ private fun CardInactiveTwoFactorAuth( ContentCardsContentTitle( icon = WatchtowerStatusIcon.WARNING.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_inactive_2fa_title), + title = stringResource(Res.string.watchtower_item_inactive_2fa_title), ) }, - text = stringResource(Res.strings.watchtower_item_inactive_2fa_text), + text = stringResource(Res.string.watchtower_item_inactive_2fa_text), imageVector = Icons.Outlined.KeyguardTwoFa, onClick = state.onClick, content = { @@ -848,10 +849,10 @@ private fun CardInactivePasskey( ContentCardsContentTitle( icon = WatchtowerStatusIcon.INFO.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_inactive_passkey_title), + title = stringResource(Res.string.watchtower_item_inactive_passkey_title), ) }, - text = stringResource(Res.strings.watchtower_item_inactive_passkey_text), + text = stringResource(Res.string.watchtower_item_inactive_passkey_text), imageVector = Icons.Outlined.KeyguardPasskey, onClick = state.onClick, content = { @@ -874,10 +875,10 @@ private fun CardIncompleteItems( ContentCardsContentTitle( icon = WatchtowerStatusIcon.INFO.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_incomplete_items_title), + title = stringResource(Res.string.watchtower_item_incomplete_items_title), ) }, - text = stringResource(Res.strings.watchtower_item_incomplete_items_text), + text = stringResource(Res.string.watchtower_item_incomplete_items_text), imageVector = Icons.Outlined.KeyguardIncompleteItems, onClick = state.onClick, ) @@ -893,10 +894,10 @@ private fun CardExpiringItems( ContentCardsContentTitle( icon = WatchtowerStatusIcon.INFO.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_expiring_items_title), + title = stringResource(Res.string.watchtower_item_expiring_items_title), ) }, - text = stringResource(Res.strings.watchtower_item_expiring_items_text), + text = stringResource(Res.string.watchtower_item_expiring_items_text), imageVector = Icons.Outlined.KeyguardExpiringItems, onClick = state.onClick, ) @@ -912,10 +913,10 @@ private fun CardDuplicateWebsites( ContentCardsContentTitle( icon = WatchtowerStatusIcon.INFO.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_duplicate_websites_title), + title = stringResource(Res.string.watchtower_item_duplicate_websites_title), ) }, - text = stringResource(Res.strings.watchtower_item_duplicate_websites_text), + text = stringResource(Res.string.watchtower_item_duplicate_websites_text), imageVector = Icons.Outlined.KeyguardDuplicateWebsites, onClick = state.onClick, ) @@ -939,10 +940,10 @@ private fun CardTrashedItems( } ContentCardsContentTitle( icon = icon, - title = stringResource(Res.strings.watchtower_item_trashed_items_title), + title = stringResource(Res.string.watchtower_item_trashed_items_title), ) }, - text = stringResource(Res.strings.watchtower_item_trashed_items_text), + text = stringResource(Res.string.watchtower_item_trashed_items_text), imageVector = Icons.Outlined.KeyguardTrashedItems, onClick = state.onClick, ) @@ -963,10 +964,10 @@ private fun CardEmptyItems( } ContentCardsContentTitle( icon = icon, - title = stringResource(Res.strings.watchtower_item_empty_folders_title), + title = stringResource(Res.string.watchtower_item_empty_folders_title), ) }, - text = stringResource(Res.strings.watchtower_item_empty_folders_text), + text = stringResource(Res.string.watchtower_item_empty_folders_text), imageVector = Icons.Outlined.FolderOff, onClick = state.onClick, ) @@ -982,10 +983,10 @@ private fun CardDuplicateItems( ContentCardsContentTitle( icon = WatchtowerStatusIcon.INFO.takeIf { state.count > 0 } ?: WatchtowerStatusIcon.OK, - title = stringResource(Res.strings.watchtower_item_duplicate_items_title), + title = stringResource(Res.string.watchtower_item_duplicate_items_title), ) }, - text = stringResource(Res.strings.watchtower_item_duplicate_items_text), + text = stringResource(Res.string.watchtower_item_duplicate_items_text), imageVector = Icons.Outlined.KeyguardDuplicateItems, onClick = state.onClick, ) @@ -1096,7 +1097,7 @@ private fun ContentLayout( dashboardContent() } Section( - text = stringResource(Res.strings.watchtower_section_security_label), + text = stringResource(Res.string.watchtower_section_security_label), ) GridLayout( modifier = Modifier @@ -1108,7 +1109,7 @@ private fun ContentLayout( cardsContent() } Section( - text = stringResource(Res.strings.watchtower_section_maintenance_label), + text = stringResource(Res.string.watchtower_section_maintenance_label), ) GridLayout( modifier = Modifier diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerStateProducer.kt index 0a841f87..70b2ed3b 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/watchtower/WatchtowerStateProducer.kt @@ -36,10 +36,12 @@ import com.artemchep.keyguard.feature.justdeleteme.directory.JustDeleteMeService import com.artemchep.keyguard.feature.justgetdata.directory.JustGetMyDataServicesRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.PersistedStorage +import com.artemchep.keyguard.feature.navigation.state.onClick import com.artemchep.keyguard.feature.navigation.state.produceScreenState import com.artemchep.keyguard.feature.passkeys.directory.PasskeysServicesRoute import com.artemchep.keyguard.feature.tfa.directory.TwoFaServicesRoute import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.buildContextItems import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted @@ -343,14 +345,14 @@ fun produceWatchtowerState( // Password strength // - fun onClickPasswordStrength( + suspend fun onClickPasswordStrength( filter: DFilter, score: PasswordStrength.Score, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( title = translate(score.formatH2()), - subtitle = translate(Res.strings.watchtower_header_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByPasswordStrength(score), @@ -385,9 +387,12 @@ fun produceWatchtowerState( val onClick = if (it.value > 0) { val filter = holder.filterConfig?.filter ?: DFilter.All - ::onClickPasswordStrength - .partially1(filter) - .partially1(it.key) + onClick { + onClickPasswordStrength( + filter = filter, + score = it.key, + ) + } } else { null } @@ -421,13 +426,13 @@ fun produceWatchtowerState( // Security // - fun onClickPasswordPwned( + suspend fun onClickPasswordPwned( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_pwned_passwords_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_pwned_passwords_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByPasswordPwned, @@ -452,8 +457,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickPasswordPwned - .partially1(filter) + onClick { + onClickPasswordPwned( + filter = filter, + ) + } } else { null } @@ -465,13 +473,13 @@ fun produceWatchtowerState( }, ) - fun onClickUnsecureWebsites( + suspend fun onClickUnsecureWebsites( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_unsecure_websites_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_unsecure_websites_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByUnsecureWebsites, @@ -495,8 +503,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickUnsecureWebsites - .partially1(filter) + onClick { + onClickUnsecureWebsites( + filter = filter, + ) + } } else { null } @@ -508,13 +519,13 @@ fun produceWatchtowerState( }, ) - fun onClickDuplicateWebsites( + suspend fun onClickDuplicateWebsites( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_duplicate_websites_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_duplicate_websites_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByDuplicateWebsites, @@ -538,8 +549,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickDuplicateWebsites - .partially1(filter) + onClick { + onClickDuplicateWebsites( + filter = filter, + ) + } } else { null } @@ -551,13 +565,13 @@ fun produceWatchtowerState( }, ) - fun onClickTfaWebsites( + suspend fun onClickTfaWebsites( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_inactive_2fa_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_inactive_2fa_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByTfaWebsites, @@ -582,8 +596,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickTfaWebsites - .partially1(filter) + onClick { + onClickTfaWebsites( + filter = filter, + ) + } } else { null } @@ -595,13 +612,13 @@ fun produceWatchtowerState( }, ) - fun onClickPasskeyWebsites( + suspend fun onClickPasskeyWebsites( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_inactive_passkey_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_inactive_passkey_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByPasskeyWebsites, @@ -626,8 +643,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickPasskeyWebsites - .partially1(filter) + onClick { + onClickPasskeyWebsites( + filter = filter, + ) + } } else { null } @@ -639,13 +659,13 @@ fun produceWatchtowerState( }, ) - fun onClickPasswordReused( + suspend fun onClickPasswordReused( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_reused_passwords_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_reused_passwords_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByPasswordDuplicates, @@ -670,8 +690,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickPasswordReused - .partially1(filter) + onClick { + onClickPasswordReused( + filter = filter, + ) + } } else { null } @@ -683,13 +706,13 @@ fun produceWatchtowerState( }, ) - fun onClickWebsitePwned( + suspend fun onClickWebsitePwned( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_vulnerable_accounts_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_vulnerable_accounts_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByWebsitePwned, @@ -714,8 +737,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickWebsitePwned - .partially1(filter) + onClick { + onClickWebsitePwned( + filter = filter, + ) + } } else { null } @@ -737,8 +763,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickWebsitePwned - .partially1(filter) + onClick { + onClickWebsitePwned( + filter = filter, + ) + } } else { null } @@ -793,13 +822,13 @@ fun produceWatchtowerState( }, ) - fun onClickIncomplete( + suspend fun onClickIncomplete( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_incomplete_items_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_incomplete_items_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByIncomplete, @@ -823,8 +852,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickIncomplete - .partially1(filter) + onClick { + onClickIncomplete( + filter = filter, + ) + } } else { null } @@ -836,13 +868,13 @@ fun produceWatchtowerState( }, ) - fun onClickExpiring( + suspend fun onClickExpiring( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_expiring_items_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_expiring_items_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( DFilter.ByExpiring, @@ -866,8 +898,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickExpiring - .partially1(filter) + onClick { + onClickExpiring( + filter = filter, + ) + } } else { null } @@ -879,13 +914,13 @@ fun produceWatchtowerState( }, ) - fun onClickTrash( + suspend fun onClickTrash( filter: DFilter, ) { val intent = NavigationIntent.NavigateToRoute( VaultRoute.watchtower( - title = translate(Res.strings.watchtower_item_trashed_items_title), - subtitle = translate(Res.strings.watchtower_header_title), + title = translate(Res.string.watchtower_item_trashed_items_title), + subtitle = translate(Res.string.watchtower_header_title), filter = DFilter.And( filters = listOfNotNull( filter, @@ -909,8 +944,11 @@ fun produceWatchtowerState( val onClick = if (count > 0) { val filter = holder?.filterConfig?.filter ?: DFilter.All - ::onClickTrash - .partially1(filter) + onClick { + onClickTrash( + filter = filter, + ) + } } else { null } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakRoute.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakRoute.kt index 00d6c858..b3f69586 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakRoute.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakRoute.kt @@ -3,10 +3,12 @@ package com.artemchep.keyguard.feature.websiteleak import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.FactCheck import androidx.compose.runtime.Composable +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.feature.navigation.DialogRoute import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.state.TranslatorScope import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItemAction import com.artemchep.keyguard.ui.icons.icon @@ -14,7 +16,7 @@ data class WebsiteLeakRoute( val args: Args, ) : DialogRoute { companion object { - fun checkBreachesWebsiteActionOrNull( + suspend fun checkBreachesWebsiteActionOrNull( translator: TranslatorScope, host: String, navigate: (NavigationIntent) -> Unit, @@ -24,13 +26,13 @@ data class WebsiteLeakRoute( navigate = navigate, ) - fun checkBreachesWebsiteAction( + suspend fun checkBreachesWebsiteAction( translator: TranslatorScope, host: String, navigate: (NavigationIntent) -> Unit, ) = FlatItemAction( leading = icon(Icons.Outlined.FactCheck), - title = translator.translate(Res.strings.website_action_check_data_breach_title), + title = Res.string.website_action_check_data_breach_title.wrap(), onClick = { val route = WebsiteLeakRoute( args = Args( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakScreen.kt index 4453a1cb..09b44cbe 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/websiteleak/WebsiteLeakScreen.kt @@ -36,6 +36,7 @@ import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.favicon.FaviconImage import com.artemchep.keyguard.feature.home.vault.component.Section import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatItem import com.artemchep.keyguard.ui.FlatSimpleNote import com.artemchep.keyguard.ui.FlatTextFieldBadge @@ -49,7 +50,8 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.infoContainer import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.pluralStringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance @Composable @@ -62,14 +64,14 @@ fun WebsiteLeakScreen( Dialog( icon = icon(Icons.Outlined.FactCheck), title = { - Text(stringResource(Res.strings.emailleak_title)) + Text(stringResource(Res.string.emailleak_title)) }, content = { Column { Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.emailleak_note), + text = stringResource(Res.string.emailleak_note), style = MaterialTheme.typography.bodySmall, color = LocalContentColor.current .combineAlpha(MediumEmphasisAlpha), @@ -112,7 +114,7 @@ fun WebsiteLeakScreen( updatedOnClose?.invoke() }, ) { - Text(stringResource(Res.strings.close)) + Text(stringResource(Res.string.close)) } }, ) @@ -146,15 +148,15 @@ private fun ColumnScope.Content( if (leaks.isNotEmpty()) { FlatSimpleNote( type = SimpleNote.Type.WARNING, - title = stringResource(Res.strings.emailleak_breach_found_title), + title = stringResource(Res.string.emailleak_breach_found_title), ) Section( - text = stringResource(Res.strings.emailleak_breach_section), + text = stringResource(Res.string.emailleak_breach_section), ) } else { FlatSimpleNote( type = SimpleNote.Type.OK, - title = stringResource(Res.strings.emailleak_breach_not_found_title), + title = stringResource(Res.string.emailleak_breach_not_found_title), ) } leaks.forEachIndexed { index, item -> @@ -231,7 +233,7 @@ private fun BreachItem( if (item.count != null) { val numberFormatter: NumberFormatter by rememberInstance() Text( - text = stringResource( + text = pluralStringResource( Res.plurals.emailleak_breach_accounts_count_plural, item.count, numberFormatter.formatNumber(item.count.toInt()), @@ -243,7 +245,7 @@ private fun BreachItem( if (item.occurredAt != null) { Text( text = stringResource( - Res.strings.emailleak_breach_occurred_at, + Res.string.emailleak_breach_occurred_at, item.occurredAt, ), style = MaterialTheme.typography.labelSmall, @@ -254,7 +256,7 @@ private fun BreachItem( if (item.reportedAt != null) { Text( text = stringResource( - Res.strings.emailleak_breach_reported_at, + Res.string.emailleak_breach_reported_at, item.reportedAt, ), style = MaterialTheme.typography.labelSmall, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiKey.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiKey.kt index 19d95f58..98b08922 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiKey.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiKey.kt @@ -36,12 +36,13 @@ import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.common.model.map import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DefaultEmphasisAlpha import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.ExpandedIfNotEmpty import com.artemchep.keyguard.ui.MediumEmphasisAlpha import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource typealias OnYubiKeyListener = (Either) -> Unit @@ -80,7 +81,7 @@ fun YubiKeyUsbCard( Text( modifier = Modifier .weight(1f), - text = stringResource(Res.strings.yubikey_usb_title), + text = stringResource(Res.string.yubikey_usb_title), ) Spacer( modifier = Modifier @@ -101,7 +102,7 @@ fun YubiKeyUsbCard( .width(8.dp), ) }, - text = stringResource(Res.strings.yubikey_usb_text), + text = stringResource(Res.string.yubikey_usb_text), content = { val isCapturing by remember(state) { derivedStateOf { @@ -120,7 +121,7 @@ fun YubiKeyUsbCard( Text( modifier = Modifier .weight(1f), - text = stringResource(Res.strings.yubikey_usb_touch_the_gold_sensor_note), + text = stringResource(Res.string.yubikey_usb_touch_the_gold_sensor_note), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.primary, ) @@ -169,7 +170,7 @@ fun YubiKeyNfcCard( Text( modifier = Modifier .weight(1f), - text = stringResource(Res.strings.yubikey_nfc_title), + text = stringResource(Res.string.yubikey_nfc_title), ) Spacer( modifier = Modifier @@ -186,7 +187,7 @@ fun YubiKeyNfcCard( .width(8.dp), ) }, - text = stringResource(Res.strings.yubikey_nfc_text), + text = stringResource(Res.string.yubikey_nfc_text), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiScreen.kt index bd2c2e9c..2672a0d6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/yubikey/YubiScreen.kt @@ -25,6 +25,7 @@ import com.artemchep.keyguard.common.usecase.ShowMessage import com.artemchep.keyguard.feature.auth.common.TextFieldModel2 import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.FlatTextField import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.grid.SimpleGridLayout @@ -32,7 +33,7 @@ import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.theme.horizontalPaddingHalf import com.artemchep.keyguard.ui.toolbar.LargeToolbar import com.artemchep.keyguard.ui.util.HorizontalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance @OptIn(ExperimentalMaterial3Api::class) @@ -130,7 +131,7 @@ fun YubiKeyManual( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.addaccount2fa_yubikey_manual_text), + text = stringResource(Res.string.addaccount2fa_yubikey_manual_text), style = MaterialTheme.typography.bodyMedium, ) Spacer( @@ -140,7 +141,7 @@ fun YubiKeyManual( FlatTextField( modifier = Modifier .padding(horizontal = 16.dp), - label = stringResource(Res.strings.verification_code), + label = stringResource(Res.string.verification_code), value = fieldState.value, keyboardOptions = KeyboardOptions( autoCorrect = true, @@ -165,7 +166,7 @@ fun YubiKeyManual( updatedOnSend(textState.value) }, ) { - Text(stringResource(Res.strings.send)) + Text(stringResource(Res.string.send)) } } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt index 77ced9e1..b78b680a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt @@ -2,4 +2,4 @@ package com.artemchep.keyguard.platform.parcelize @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY) -expect annotation class LeParcelize() +annotation class LeParcelize() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/ServerEnv.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/ServerEnv.kt index 3866aa99..9fd031ed 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/ServerEnv.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/ServerEnv.kt @@ -2,7 +2,8 @@ package com.artemchep.keyguard.provider.bitwarden import arrow.optics.optics import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource @optics data class ServerEnv( @@ -21,8 +22,8 @@ data class ServerEnv( val title: StringResource, val text: String, ) { - US(Res.strings.addaccount_region_us_type, "bitwarden.com"), - EU(Res.strings.addaccount_region_eu_type, "bitwarden.eu"), + US(Res.string.addaccount_region_us_type, "bitwarden.com"), + EU(Res.string.addaccount_region_eu_type, "bitwarden.eu"), ; companion object { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/model/TwoFactorProvider.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/model/TwoFactorProvider.kt index 25185c3a..b5123dac 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/model/TwoFactorProvider.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/provider/bitwarden/model/TwoFactorProvider.kt @@ -3,7 +3,8 @@ package com.artemchep.keyguard.provider.bitwarden.model import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource data class TwoFactorProvider( val type: TwoFactorProviderType, @@ -15,37 +16,37 @@ data class TwoFactorProvider( val state = mapOf( TwoFactorProviderType.Authenticator to TwoFactorProvider( type = TwoFactorProviderType.Authenticator, - name = Res.strings.provider_2fa_authenticator, + name = Res.string.provider_2fa_authenticator, priority = 10, supported = true, ), TwoFactorProviderType.YubiKey to TwoFactorProvider( type = TwoFactorProviderType.YubiKey, - name = Res.strings.provider_2fa_yubikey, + name = Res.string.provider_2fa_yubikey, priority = 30, supported = true, ), TwoFactorProviderType.Duo to TwoFactorProvider( type = TwoFactorProviderType.Duo, - name = Res.strings.provider_2fa_duo, + name = Res.string.provider_2fa_duo, priority = 20, supported = CurrentPlatform is Platform.Mobile, ), TwoFactorProviderType.OrganizationDuo to TwoFactorProvider( type = TwoFactorProviderType.OrganizationDuo, - name = Res.strings.provider_2fa_duo_organization, + name = Res.string.provider_2fa_duo_organization, priority = 21, supported = CurrentPlatform is Platform.Mobile, ), TwoFactorProviderType.Fido2WebAuthn to TwoFactorProvider( type = TwoFactorProviderType.Fido2WebAuthn, - name = Res.strings.provider_2fa_fido2_webauthn, + name = Res.string.provider_2fa_fido2_webauthn, priority = 50, supported = CurrentPlatform is Platform.Mobile, ), TwoFactorProviderType.Email to TwoFactorProvider( type = TwoFactorProviderType.Email, - name = Res.strings.provider_2fa_email, + name = Res.string.provider_2fa_email, priority = 0, supported = true, ), @@ -53,7 +54,7 @@ data class TwoFactorProvider( // provider. Therefore most likely this is never going to be implemented. TwoFactorProviderType.U2f to TwoFactorProvider( type = TwoFactorProviderType.U2f, - name = Res.strings.provider_2fa_fido_u2f, + name = Res.string.provider_2fa_fido_u2f, priority = 40, supported = false, ), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/AutofillWindow.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/AutofillWindow.kt index 8323b53a..eda5d119 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/AutofillWindow.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/AutofillWindow.kt @@ -48,11 +48,13 @@ import com.artemchep.keyguard.feature.generator.GeneratorState import com.artemchep.keyguard.feature.generator.GeneratorType import com.artemchep.keyguard.feature.generator.produceGeneratorState import com.artemchep.keyguard.feature.home.vault.component.Section +import com.artemchep.keyguard.feature.localization.wrap import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.icons.icon import com.artemchep.keyguard.ui.skeleton.SkeletonItem import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.flow.StateFlow @Composable @@ -147,10 +149,10 @@ fun ColumnScope.AutofillWindow( }, ifOk = { state -> val text = when { - username && password -> stringResource(Res.strings.generator_header_title) - username -> stringResource(Res.strings.generator_header_username_title) - password -> stringResource(Res.strings.generator_header_password_title) - else -> stringResource(Res.strings.generator_header_title) + username && password -> stringResource(Res.string.generator_header_title) + username -> stringResource(Res.string.generator_header_username_title) + password -> stringResource(Res.string.generator_header_password_title) + else -> stringResource(Res.string.generator_header_title) } Text( modifier = Modifier @@ -206,7 +208,7 @@ fun ColumnScope.AutofillWindowContent( Unit.takeIf { showSection }, ) { Section( - text = stringResource(Res.strings.filter_header_title), + text = stringResource(Res.string.filter_header_title), ) } @@ -245,8 +247,6 @@ private fun ColumnScope.GeneratorValue2( ) { value -> val updatedOnRefresh by rememberUpdatedState(value.onRefresh) - val generateTitle = stringResource(Res.strings.generator_generate_button) - val regenerateTitle = stringResource(Res.strings.generator_regenerate_button) val actions by remember(valueState) { derivedStateOf { val valueExists = !valueState.value?.password.isNullOrEmpty() @@ -254,7 +254,7 @@ private fun ColumnScope.GeneratorValue2( listOf( FlatItemAction( leading = icon(Icons.Outlined.Refresh), - title = regenerateTitle, + title = Res.string.generator_regenerate_button.wrap(), onClick = { updatedOnRefresh?.invoke() }, @@ -264,7 +264,7 @@ private fun ColumnScope.GeneratorValue2( listOf( FlatItemAction( leading = icon(Icons.Outlined.Refresh), - title = generateTitle, + title = Res.string.generator_generate_button.wrap(), onClick = { updatedOnRefresh?.invoke() }, @@ -288,7 +288,7 @@ private fun ColumnScope.GeneratorValue2( text = if (password.isEmpty()) { val color = LocalContentColor.current .combineAlpha(DisabledEmphasisAlpha) - val text = stringResource(Res.strings.empty_value) + val text = stringResource(Res.string.empty_value) buildAnnotatedString { withStyle( style = SpanStyle(color = color), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Duration.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Duration.kt index 1760e786..6217aa64 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Duration.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Duration.kt @@ -3,14 +3,17 @@ package com.artemchep.keyguard.ui import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.toList import kotlin.time.Duration -fun Duration.format(context: LeContext): String { +suspend fun Duration.format(context: LeContext): String { if (this == Duration.INFINITE) { - return textResource(Res.strings.expiration_date_never, context) + return textResource(Res.string.expiration_date_never, context) } - return sequence { + return flow { val days = inWholeDays if (days > 0) { val daysFormatted = textResource( @@ -19,7 +22,7 @@ fun Duration.format(context: LeContext): String { quantity = days.toInt(), days.toString(), ) - yield(daysFormatted) + emit(daysFormatted) } val hours = inWholeHours - daysToHours(days) if (hours > 0) { @@ -29,7 +32,7 @@ fun Duration.format(context: LeContext): String { quantity = hours.toInt(), hours.toString(), ) - yield(hoursFormatted) + emit(hoursFormatted) } val minutes = inWholeMinutes - hoursToMinutes(daysToHours(days) + hours) if (minutes > 0) { @@ -39,7 +42,7 @@ fun Duration.format(context: LeContext): String { quantity = minutes.toInt(), minutes.toString(), ) - yield(minutesFormatted) + emit(minutesFormatted) } val seconds = inWholeSeconds - minutesToSeconds(hoursToMinutes(daysToHours(days) + hours) + minutes) @@ -50,9 +53,10 @@ fun Duration.format(context: LeContext): String { quantity = seconds.toInt(), seconds.toString(), ) - yield(secondsFormatted) + emit(secondsFormatted) } } + .toList() .joinToString(separator = " ") .takeIf { it.isNotEmpty() } ?: toString() diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordFilterItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordFilterItem.kt index 69ae05b5..8be82500 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordFilterItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordFilterItem.kt @@ -67,6 +67,8 @@ import com.artemchep.keyguard.feature.home.vault.component.VaultItemIcon2 import com.artemchep.keyguard.feature.home.vault.component.localSurfaceColorAtElevation import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevationSemi import com.artemchep.keyguard.feature.home.vault.model.VaultItemIcon +import com.artemchep.keyguard.feature.localization.TextHolder +import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.surface.ProvideSurfaceColor import com.artemchep.keyguard.ui.theme.combineAlpha @@ -104,8 +106,8 @@ data class FlatItemAction( val icon: ImageVector? = null, val leading: (@Composable () -> Unit)? = null, val trailing: (@Composable () -> Unit)? = null, - val title: String, - val text: String? = null, + val title: TextHolder, + val text: TextHolder? = null, val type: Type? = null, val onClick: (() -> Unit)? = {}, ) : ContextItem { @@ -143,7 +145,7 @@ class ContextItemBuilder( out } - fun section( + inline fun section( title: String? = null, block: ContextItemBuilder.() -> Unit, ) { @@ -152,8 +154,8 @@ class ContextItemBuilder( return } - items += ContextItem.Section(title = title) - items += sectionItems + this += ContextItem.Section(title = title) + this += sectionItems } operator fun plusAssign(item: ContextItem?) { @@ -161,6 +163,10 @@ class ContextItemBuilder( ?: return } + operator fun plusAssign(item: Collection) { + items += item + } + fun build(): PersistentList = sequence { items.forEachIndexed { index, item -> // Skip a first item if it has no title. @@ -180,7 +186,7 @@ class ContextItemBuilder( @JvmName("FlatItemActionNullable") fun CopyText.FlatItemAction( - title: String, + title: TextHolder, value: String?, hidden: Boolean = false, type: CopyText.Type = CopyText.Type.VALUE, @@ -195,7 +201,7 @@ fun CopyText.FlatItemAction( fun CopyText.FlatItemAction( leading: (@Composable () -> Unit)? = null, - title: String, + title: TextHolder, value: String, hidden: Boolean = false, type: CopyText.Type = CopyText.Type.VALUE, @@ -203,7 +209,8 @@ fun CopyText.FlatItemAction( leading = leading, icon = Icons.Outlined.ContentCopy, title = title, - text = value.takeUnless { hidden }, + text = value.takeUnless { hidden } + ?.let(TextHolder::Value), type = FlatItemAction.Type.COPY, onClick = { copy( @@ -627,7 +634,7 @@ fun RowScope.FlatItemActionContent( FlatItemTextContent( title = { Text( - text = action.title, + text = textResource(action.title), maxLines = 2, overflow = TextOverflow.Ellipsis, ) @@ -636,7 +643,7 @@ fun RowScope.FlatItemActionContent( // composable { Text( - text = action.text, + text = textResource(action.text), maxLines = 2, overflow = TextOverflow.Ellipsis, fontSize = 13.sp, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordPwnedBadge.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordPwnedBadge.kt index 132ca424..6746f50e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordPwnedBadge.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/PasswordPwnedBadge.kt @@ -18,7 +18,7 @@ import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.common.usecase.CheckPasswordLeak import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart +import org.jetbrains.compose.resources.stringResource import org.kodein.di.compose.rememberInstance private data class PasswordPwnedBadgeState( @@ -62,7 +63,7 @@ fun PasswordPwnedBadge( Text( modifier = Modifier .padding(horizontal = 4.dp), - text = stringResource(Res.strings.password_pwned_label), + text = stringResource(Res.string.password_pwned_label), ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Placeholder.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Placeholder.kt index acc4ec4c..baa58eed 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Placeholder.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Placeholder.kt @@ -19,9 +19,10 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import compose.icons.FeatherIcons import compose.icons.feathericons.Package -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun Placeholder( @@ -47,7 +48,7 @@ fun Placeholder( Placeholder( modifier = modifier, icon = FeatherIcons.Package, - title = stringResource(Res.strings.coming_soon), + title = stringResource(Res.string.coming_soon), ) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Scaffold.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Scaffold.kt index e212c97d..06745c8e 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Scaffold.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/Scaffold.kt @@ -64,12 +64,13 @@ import com.artemchep.keyguard.platform.leDisplayCutout import com.artemchep.keyguard.platform.leIme import com.artemchep.keyguard.platform.leSystemBars import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.scrollbar.ColumnScrollbar import com.artemchep.keyguard.ui.scrollbar.LazyColumnScrollbar import com.artemchep.keyguard.ui.selection.SelectionBar import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList import kotlin.math.log10 @@ -384,7 +385,7 @@ fun DefaultSelection( ) { selection -> SelectionBar( title = { - val text = stringResource(Res.strings.selection_n_selected, selection.count) + val text = stringResource(Res.string.selection_n_selected, selection.count) Text( text = text, maxLines = 2, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/TextItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/TextItem.kt index 67c60a66..d6293248 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/TextItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/TextItem.kt @@ -90,6 +90,7 @@ import com.artemchep.keyguard.feature.auth.common.TextFieldModel2 import com.artemchep.keyguard.feature.auth.common.VisibilityState import com.artemchep.keyguard.feature.auth.common.VisibilityToggle import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.focus.FocusRequester2 import com.artemchep.keyguard.ui.focus.bringIntoView import com.artemchep.keyguard.ui.focus.focusRequester2 @@ -103,7 +104,7 @@ import com.artemchep.keyguard.ui.theme.warningContainer import com.artemchep.keyguard.ui.util.DividerColor import com.artemchep.keyguard.ui.util.HorizontalDivider import com.artemchep.keyguard.ui.util.VerticalDivider -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -140,7 +141,7 @@ fun UrlFlatTextField( modifier = modifier, testTag = testTag, label = label - ?: stringResource(Res.strings.url), + ?: stringResource(Res.string.url), placeholder = placeholder, value = value, keyboardOptions = keyboardOptions.copy( @@ -183,7 +184,7 @@ fun EmailFlatTextField( boxModifier = boxModifier, testTag = testTag, label = label - ?: stringResource(Res.strings.email), + ?: stringResource(Res.string.email), placeholder = placeholder, value = value, keyboardOptions = keyboardOptions.copy( @@ -226,7 +227,7 @@ fun PasswordFlatTextField( boxModifier = boxModifier, testTag = testTag, label = label - ?: stringResource(Res.strings.password), + ?: stringResource(Res.string.password), placeholder = placeholder, value = value, keyboardOptions = keyboardOptions.copy( diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/ToastComposable.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/ToastComposable.kt index 21c5d13f..c031c056 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/ToastComposable.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/ToastComposable.kt @@ -40,11 +40,12 @@ import com.artemchep.keyguard.common.service.clipboard.ClipboardService import com.artemchep.keyguard.common.usecase.MessageHub import com.artemchep.keyguard.feature.navigation.navigationNodeStack import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.combineAlpha import com.artemchep.keyguard.ui.theme.ok import com.artemchep.keyguard.ui.theme.okContainer import com.artemchep.keyguard.ui.theme.onOkContainer -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -295,7 +296,7 @@ private fun ToastMessage(model: ToastMessage) { ) { Icon( imageVector = Icons.Outlined.ContentCopy, - contentDescription = stringResource(Res.strings.copy), + contentDescription = stringResource(Res.string.copy), ) } } else { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/markdown/Markdown.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/markdown/Markdown.kt index 39e22b6c..0e0a1512 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/markdown/Markdown.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/markdown/Markdown.kt @@ -12,6 +12,7 @@ import com.artemchep.keyguard.common.usecase.ShowMessage import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LocalLeContext import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.halilibo.richtext.commonmark.Markdown import com.halilibo.richtext.markdown.BasicMarkdown import com.halilibo.richtext.markdown.node.AstNode @@ -20,6 +21,8 @@ import com.halilibo.richtext.ui.RichTextStyle import com.halilibo.richtext.ui.material3.RichText import com.halilibo.richtext.ui.resolveDefaults import com.halilibo.richtext.ui.string.RichTextStringStyle +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import org.kodein.di.compose.rememberInstance @Composable @@ -63,13 +66,15 @@ private fun rememberGracefulLinkClickHandler(): LinkClickHandler { try { updatedUriHandler.openUri(uri) } catch (e: Exception) { - val title = textResource(Res.strings.error_failed_open_uri, updatedContext) - val msg = ToastMessage( - title = title, - text = e.message, - type = ToastMessage.Type.ERROR, - ) - showMessage.copy(msg) + GlobalScope.launch { + val title = textResource(Res.string.error_failed_open_uri, updatedContext) + val msg = ToastMessage( + title = title, + text = e.message, + type = ToastMessage.Type.ERROR, + ) + showMessage.copy(msg) + } } } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/poweredby/PoweredBy.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/poweredby/PoweredBy.kt index a6a41c5e..40ffa963 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/poweredby/PoweredBy.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/poweredby/PoweredBy.kt @@ -22,9 +22,10 @@ import com.artemchep.keyguard.URL_PASSKEYS import com.artemchep.keyguard.feature.navigation.LocalNavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun PoweredByJustDeleteMe( @@ -106,7 +107,7 @@ fun PoweredByLabel( modifier = Modifier .weight(1f, fill = fill) .padding(top = 4.dp), - text = stringResource(Res.strings.powered_by), + text = stringResource(Res.string.powered_by), maxLines = 2, style = MaterialTheme.typography.labelSmall, color = LocalContentColor.current diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/pulltosearch/PullToSearch.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/pulltosearch/PullToSearch.kt index edb0d0a8..a932f858 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/pulltosearch/PullToSearch.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/pulltosearch/PullToSearch.kt @@ -22,9 +22,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.theme.combineAlpha -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlin.math.log10 @Composable @@ -76,7 +77,7 @@ fun PullToSearch( tint = tint, ) Text( - text = stringResource(Res.strings.pull_to_search), + text = stringResource(Res.string.pull_to_search), color = tint, style = MaterialTheme.typography.bodySmall, ) diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/ColumnScrollbar.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/ColumnScrollbar.kt index 6030e899..4052339a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/ColumnScrollbar.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/ColumnScrollbar.kt @@ -212,8 +212,8 @@ fun InternalColumnScrollbar( }, ) { indicatorContent( - normalizedOffset = offsetCorrectionInverse(normalizedOffsetPosition), - isThumbSelected = isSelected, + offsetCorrectionInverse(normalizedOffsetPosition), + isSelected, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/LazyColumnScrollbar.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/LazyColumnScrollbar.kt index 85ba52c2..119231ee 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/LazyColumnScrollbar.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/scrollbar/LazyColumnScrollbar.kt @@ -269,8 +269,8 @@ fun InternalLazyColumnScrollbar( ), ) { indicatorContent( - index = firstVisibleItemIndex.value, - isThumbSelected = isSelected, + firstVisibleItemIndex.value, + isSelected, ) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/CallsTabs.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/CallsTabs.kt index 3ecafe03..8b31d7ab 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/CallsTabs.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/CallsTabs.kt @@ -1,16 +1,17 @@ package com.artemchep.keyguard.ui.tabs import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.StringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.StringResource enum class CallsTabs( override val title: StringResource, ) : TabItem { RECENTS( - title = Res.strings.ciphers_recently_opened, + title = Res.string.ciphers_recently_opened, ), FAVORITES( - title = Res.strings.ciphers_often_opened, + title = Res.string.ciphers_often_opened, ); companion object { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/SegmentedTabs.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/SegmentedTabs.kt index 5feb07ac..c41db13f 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/SegmentedTabs.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/SegmentedTabs.kt @@ -42,7 +42,7 @@ import androidx.compose.ui.unit.dp import com.artemchep.keyguard.ui.DisabledEmphasisAlpha import com.artemchep.keyguard.ui.theme.selectedContainer import com.artemchep.keyguard.ui.util.DividerColor -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource import kotlinx.collections.immutable.ImmutableList @Composable diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/TabItem.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/TabItem.kt index b731e800..8124f66a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/TabItem.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/tabs/TabItem.kt @@ -1,6 +1,6 @@ package com.artemchep.keyguard.ui.tabs -import dev.icerock.moko.resources.StringResource +import org.jetbrains.compose.resources.StringResource interface TabItem { val title: StringResource diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/text/AnnotatedResource.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/text/AnnotatedResource.kt index eeff24e5..66a80441 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/text/AnnotatedResource.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/text/AnnotatedResource.kt @@ -7,8 +7,8 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import com.artemchep.keyguard.feature.navigation.state.TranslatorScope -import dev.icerock.moko.resources.StringResource -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.stringResource import java.util.UUID @Composable @@ -32,7 +32,7 @@ fun annotatedResource( } } -fun TranslatorScope.annotate( +suspend fun TranslatorScope.annotate( resource: StringResource, vararg args: Pair, ): AnnotatedString { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt index 43b06d91..a41ce7b6 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/theme/Theme.kt @@ -23,11 +23,12 @@ import com.artemchep.keyguard.common.usecase.GetFont import com.artemchep.keyguard.common.usecase.GetTheme import com.artemchep.keyguard.common.usecase.GetThemeUseAmoledDark import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.theme.monet.ColorSchemeFactory import com.artemchep.keyguard.ui.theme.monet.darkMonetCompatScheme import com.artemchep.keyguard.ui.theme.monet.lightMonetCompatScheme -import dev.icerock.moko.resources.compose.fontFamilyResource import dev.kdrag0n.colorkt.rgb.LinearSrgb +import org.jetbrains.compose.resources.Font import org.kodein.di.compose.rememberInstance val ColorScheme.selectedContainer @@ -237,7 +238,7 @@ val sansFontFamily: FontFamily val robotoMonoFontFamily: FontFamily @Composable - get() = fontFamilyResource(Res.fonts.RobotoMono.robotoMono) + get() = FontFamily(Font(Res.font.RobotoMono)) val robotoSansFontFamily: FontFamily @Composable @@ -247,12 +248,12 @@ val robotoSansFontFamily: FontFamily getFont() }.collectAsState(null) val res = when (font.value) { - AppFont.ROBOTO -> Res.fonts.Roboto.regular - AppFont.NOTO -> Res.fonts.NotoSans.regular - AppFont.ATKINSON_HYPERLEGIBLE -> Res.fonts.AtkinsonHyperlegible.regular - null -> Res.fonts.Roboto.regular + AppFont.ROBOTO -> Res.font.Roboto_Regular + AppFont.NOTO -> Res.font.NotoSans_Regular + AppFont.ATKINSON_HYPERLEGIBLE -> Res.font.AtkinsonHyperlegible_Regular + null -> Res.font.Roboto_Regular } - return fontFamilyResource(res) + return FontFamily(Font(res)) } @Composable diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/content/ContentSearchbar.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/content/ContentSearchbar.kt index c88718aa..c9953fb3 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/content/ContentSearchbar.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/content/ContentSearchbar.kt @@ -6,7 +6,8 @@ import androidx.compose.ui.Modifier import com.artemchep.keyguard.feature.auth.common.TextFieldModel2 import com.artemchep.keyguard.feature.home.vault.component.SearchTextField import com.artemchep.keyguard.res.Res -import dev.icerock.moko.resources.compose.stringResource +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.stringResource @Composable fun CustomSearchbarContent( diff --git a/common/src/commonMain/resources/MR/images/ic_card_amex.svg b/common/src/commonMain/resources/MR/images/ic_card_amex.svg deleted file mode 100644 index 1a928e5d..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_amex.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_diners.svg b/common/src/commonMain/resources/MR/images/ic_card_diners.svg deleted file mode 100644 index 5f6e4b0a..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_diners.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_discover.svg b/common/src/commonMain/resources/MR/images/ic_card_discover.svg deleted file mode 100644 index 160daa61..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_discover.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_elo.svg b/common/src/commonMain/resources/MR/images/ic_card_elo.svg deleted file mode 100644 index 0b4e06ef..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_elo.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_jcb.svg b/common/src/commonMain/resources/MR/images/ic_card_jcb.svg deleted file mode 100644 index bf45dc82..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_jcb.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_maestro.svg b/common/src/commonMain/resources/MR/images/ic_card_maestro.svg deleted file mode 100644 index e21a6b16..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_maestro.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_mastercard.svg b/common/src/commonMain/resources/MR/images/ic_card_mastercard.svg deleted file mode 100644 index a15ae8e9..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_mastercard.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_mir.svg b/common/src/commonMain/resources/MR/images/ic_card_mir.svg deleted file mode 100644 index 3f0587e4..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_mir.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_unionpay.svg b/common/src/commonMain/resources/MR/images/ic_card_unionpay.svg deleted file mode 100644 index 035a99e4..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_unionpay.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_card_visa.svg b/common/src/commonMain/resources/MR/images/ic_card_visa.svg deleted file mode 100644 index 6a0b6f5c..00000000 --- a/common/src/commonMain/resources/MR/images/ic_card_visa.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/common/src/commonMain/resources/MR/images/ic_mastodon.svg b/common/src/commonMain/resources/MR/images/ic_mastodon.svg deleted file mode 100644 index 425d57b0..00000000 --- a/common/src/commonMain/resources/MR/images/ic_mastodon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/copy/TextServiceJvm.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/copy/TextServiceJvm.kt index f20e4e6f..7d95c0aa 100644 --- a/common/src/desktopMain/kotlin/com/artemchep/keyguard/copy/TextServiceJvm.kt +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/copy/TextServiceJvm.kt @@ -1,7 +1,10 @@ package com.artemchep.keyguard.copy +import com.artemchep.keyguard.common.model.FileResource import com.artemchep.keyguard.common.service.text.TextService -import dev.icerock.moko.resources.FileResource +import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* +import org.jetbrains.compose.resources.ExperimentalResourceApi import org.kodein.di.DirectDI import java.io.File import java.io.InputStream @@ -12,12 +15,11 @@ class TextServiceJvm() : TextService { directDI: DirectDI, ) : this() - override fun readFromResources( + @OptIn(ExperimentalResourceApi::class) + override suspend fun readFromResources( fileResource: FileResource, - ): InputStream = fileResource.inputStream() - - private fun FileResource.inputStream() = resourcesClassLoader - .getResourceAsStream(filePath)!! + ): InputStream = Res.readBytes(fileResource.name) + .inputStream() override fun readFromFile(uri: String): InputStream { val parsedUri = URI.create(uri) diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt index e243b8fc..bc1aae1d 100644 --- a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filepicker/FilePickerEffect.kt @@ -10,6 +10,7 @@ import com.artemchep.keyguard.feature.localization.textResource import com.artemchep.keyguard.platform.LocalLeContext import com.artemchep.keyguard.platform.leParseUri import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.CollectedEffect import com.artemchep.keyguard.ui.LocalComposeWindow import kotlinx.coroutines.flow.Flow @@ -47,7 +48,7 @@ actual fun FilePickerEffect( } } val filters = if (extensions.isNotEmpty()) { - val title = textResource(Res.strings.select_file, context) + val title = textResource(Res.string.select_file, context) listOf( FileDialog.Filter( title = title, diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt index 7606e64a..c2c7a09a 100644 --- a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/localization/textResource.kt @@ -1,25 +1,21 @@ package com.artemchep.keyguard.feature.localization import com.artemchep.keyguard.platform.LeContext -import dev.icerock.moko.resources.PluralsResource -import dev.icerock.moko.resources.StringResource -import dev.icerock.moko.resources.desc.PluralFormatted -import dev.icerock.moko.resources.desc.Resource -import dev.icerock.moko.resources.desc.ResourceFormatted -import dev.icerock.moko.resources.desc.StringDesc +import org.jetbrains.compose.resources.PluralStringResource +import org.jetbrains.compose.resources.StringResource -actual fun textResource(res: StringResource, context: LeContext): String = - StringDesc.Resource(res).localized() - -actual fun textResource( - res: StringResource, - context: LeContext, - vararg args: Any, -): String = StringDesc.ResourceFormatted(res, *args).localized() - -actual fun textResource( - res: PluralsResource, - context: LeContext, - quantity: Int, - vararg args: Any, -): String = StringDesc.PluralFormatted(res, quantity, *args).localized() +//actual suspend fun textResource(res: StringResource, context: LeContext): String = +// "StringDesc.Resource(res).localized()" +// +//actual suspend fun textResource( +// res: StringResource, +// context: LeContext, +// vararg args: Any, +//): String = "StringDesc.ResourceFormatted(res, *args).localized()" +// +//actual suspend fun textResource( +// res: PluralStringResource, +// context: LeContext, +// quantity: Int, +// vararg args: Any, +//): String = "StringDesc.PluralFormatted(res, quantity, *args).localized()" diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt index 5a1cf6c8..c48dffa7 100644 --- a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/qr/ScanQrScreen.kt @@ -15,11 +15,12 @@ import com.artemchep.keyguard.feature.filepicker.FilePickerEffect import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.RouteResultTransmitter import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.CollectedEffect import com.artemchep.keyguard.ui.ScaffoldColumn import com.artemchep.keyguard.ui.theme.Dimens import com.artemchep.keyguard.ui.toolbar.LargeToolbar -import dev.icerock.moko.resources.compose.stringResource +import org.jetbrains.compose.resources.stringResource @Composable fun ScanQrScreen( @@ -53,7 +54,7 @@ fun ScanQrScreen( topBar = { LargeToolbar( title = { - Text(stringResource(Res.strings.scanqr_title)) + Text(stringResource(Res.string.scanqr_title)) }, navigationIcon = { NavigationIcon() @@ -69,7 +70,7 @@ fun ScanQrScreen( Text( modifier = Modifier .padding(horizontal = Dimens.horizontalPadding), - text = stringResource(Res.strings.scanqr_load_from_image_note), + text = stringResource(Res.string.scanqr_load_from_image_note), ) Spacer( modifier = Modifier @@ -83,7 +84,7 @@ fun ScanQrScreen( }, ) { Text( - text = stringResource(Res.strings.select_file), + text = stringResource(Res.string.select_file), ) } } diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt deleted file mode 100644 index 24168e8f..00000000 --- a/common/src/desktopMain/kotlin/com/artemchep/keyguard/platform/parcelize/LeParcelize.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.artemchep.keyguard.platform.parcelize - -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.BINARY) -actual annotation class LeParcelize actual constructor() diff --git a/common/src/jvmMain/kotlin/com/artemchep/keyguard/copy/DateFormatterAndroid.kt b/common/src/jvmMain/kotlin/com/artemchep/keyguard/copy/DateFormatterAndroid.kt index 9a8f1a3f..0189e502 100644 --- a/common/src/jvmMain/kotlin/com/artemchep/keyguard/copy/DateFormatterAndroid.kt +++ b/common/src/jvmMain/kotlin/com/artemchep/keyguard/copy/DateFormatterAndroid.kt @@ -54,13 +54,13 @@ class DateFormatterAndroid( return formatterDate.format(date) } - override fun formatDateShort(instant: Instant): String { + override suspend fun formatDateShort(instant: Instant): String { val tz = TimeZone.currentSystemDefault() val dt = instant.toLocalDateTime(tz) return formatDateShort(dt.date) } - override fun formatDateShort(date: LocalDate): String { + override suspend fun formatDateShort(date: LocalDate): String { // Manually format the date. Using the "MMMM yyyy" format // doesn't work correctly for some locales. val year = date.year.toString() diff --git a/crowdin.yml b/crowdin.yml index d4c10b29..71d163af 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -21,13 +21,13 @@ files: [ # Source files filter # e.g. "/resources/en/*.json" # - "source" : "/common/src/commonMain/resources/MR/base/*.xml", + "source" : "/common/src/commonMain/composeResources/values/*.xml", # # Where translations will be placed # e.g. "/resources/%two_letters_code%/%original_file_name%" # - "translation" : "/common/src/commonMain/resources/MR/%android_code%/%original_file_name%", + "translation" : "/common/src/commonMain/composeResources/values-%android_code%/%original_file_name%", # # File type diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index 5aba25cf..8f52de15 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -2,8 +2,9 @@ import org.apache.tools.ant.taskdefs.condition.Os import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { - alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.compose) + alias(libs.plugins.kotlin.plugin.compose) + alias(libs.plugins.kotlin.multiplatform) } kotlin { @@ -19,6 +20,7 @@ kotlin { implementation(compose.material3) implementation(compose.materialIconsExtended) implementation(compose.desktop.currentOs) + implementation(compose.components.resources) implementation(project(":common")) } } diff --git a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt index 59b0b797..f3b86756 100644 --- a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt @@ -47,13 +47,11 @@ import com.artemchep.keyguard.platform.CurrentPlatform import com.artemchep.keyguard.platform.Platform import com.artemchep.keyguard.platform.lifecycle.LeLifecycleState import com.artemchep.keyguard.res.Res +import com.artemchep.keyguard.res.* import com.artemchep.keyguard.ui.LocalComposeWindow import com.artemchep.keyguard.ui.surface.LocalBackgroundManager import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.theme.KeyguardTheme -import dev.icerock.moko.resources.compose.painterResource -import dev.icerock.moko.resources.compose.stringResource -import dev.icerock.moko.resources.desc.StringDesc import io.kamel.core.config.KamelConfig import io.kamel.core.config.takeFrom import io.kamel.core.mapper.Mapper @@ -71,6 +69,8 @@ import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.datetime.Clock +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource import org.kodein.di.DI import org.kodein.di.bindSingleton import org.kodein.di.compose.rememberInstance @@ -130,10 +130,6 @@ fun main() { } } Locale.setDefault(newLocale) - StringDesc.localeType = when (locale) { - null -> StringDesc.LocaleType.System - else -> StringDesc.LocaleType.Custom(locale) - } } .launchIn(GlobalScope) @@ -229,18 +225,18 @@ fun main() { val trayState = rememberTrayState() Tray( icon = when (CurrentPlatform) { - is Platform.Desktop.MacOS -> painterResource(Res.images.ic_tray_macos) - else -> painterResource(Res.images.ic_keyguard) + is Platform.Desktop.MacOS -> painterResource(Res.drawable.ic_tray_macos) + else -> painterResource(Res.drawable.ic_keyguard) }, state = trayState, onAction = onWindowOpen, menu = { Item( - stringResource(Res.strings.show_keyguard), + stringResource(Res.string.show_keyguard), onClick = onWindowOpen, ) Item( - stringResource(Res.strings.quit), + stringResource(Res.string.quit), onClick = ::exitApplication, ) }, @@ -271,7 +267,7 @@ private fun ApplicationScope.KeyguardWindow( val windowState = rememberWindowState() Window( onCloseRequest = onCloseRequest, - icon = painterResource(Res.images.ic_keyguard), + icon = painterResource(Res.drawable.ic_keyguard), state = windowState, title = "Keyguard", ) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5b62e0ea..c503a13a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,21 +17,21 @@ androidBillingClient = "6.2.1" # https://mvnrepository.com/artifact/com.android.tools/desugar_jdk_libs androidDesugar = "2.0.4" # https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google -androidPlugin = "8.3.2" +androidPlugin = "8.4.1" androidxActivity = "1.9.0" -androidxAppCompat = "1.7.0-beta01" +androidxAppCompat = "1.7.0-rc01" androidxAutofill = "1.3.0-alpha01" androidxBaselineProfile = "1.2.4" androidxBenchmarkMacroJUnit4 = "1.2.4" androidxBiometricKtx = "1.2.0-alpha05" androidxBrowser = "1.8.0" -androidxCamera = "1.4.0-alpha05" +androidxCamera = "1.4.0-beta01" androidxCoreKtx = "1.13.1" androidxCoreSplash = "1.2.0-alpha01" androidxCoreShortcuts = "1.1.0" androidxCredentials = "1.2.2" androidxDatastore = "1.1.1" -androidxLifecycle = "2.7.0" +androidxLifecycle = "2.8.0" androidxProfileInstaller = "1.3.1" androidxRoom = "2.6.1" androidxSecurityCryptoKtx = "1.1.0-alpha06" @@ -52,10 +52,10 @@ commonsCodec = "1.17.0" # https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 commonsLang3 = "3.14.0" # https://github.com/JetBrains/compose-multiplatform -composeMultiplatform = "1.6.2" +composeMultiplatform = "1.6.10" # https://github.com/DevSrSouza/compose-icons composeOpenIcons = "1.1.0" -crashlyticsPlugin = "2.9.9" +crashlyticsPlugin = "3.0.1" firebase = "33.0.0" # https://github.com/tfcporciuncula/flow-preferences flowPreferences = "1.9.1" @@ -69,20 +69,20 @@ kamel = "0.9.4" # https://github.com/kdrag0n/colorkt kdrag0nColorKt = "1.0.5" # https://github.com/Kodein-Framework/Kodein-DI -kodeinDi = "7.21.1" +kodeinDi = "7.21.2" # https://github.com/JetBrains/kotlin -kotlin = "1.9.23" +kotlin = "2.0.0" # https://github.com/Kotlin/kotlinx.collections.immutable kotlinCollections = "0.3.7" # https://github.com/Kotlin/kotlinx.coroutines -kotlinCoroutines = "1.8.0" +kotlinCoroutines = "1.8.1" # https://github.com/Kotlin/kotlinx-datetime -kotlinDatetime = "0.5.0" +kotlinDatetime = "0.6.0" kotlinDsl = "4.3.0" # https://github.com/Kotlin/kotlinx.serialization kotlinSerialization = "1.6.3" # https://github.com/google/ksp/releases -kspPlugin = "1.9.23-1.0.20" +kspPlugin = "2.0.0-1.0.21" # https://github.com/pinterest/ktlint/releases # @keep ktlint = "0.50.0" @@ -99,8 +99,6 @@ licenseCheckPlugin = "1.11.0" logback = "3.0.0" # https://developers.google.com/android/guides/setup mlkitBarcodeScanning = "18.3.0" -# https://github.com/icerockdev/moko-resources -moko = "0.23.0" # https://github.com/WonderzGmbH/nativefiledialog-java nfd = "1.0.3" # https://square.github.io/okhttp/changelogs/changelog/ @@ -112,13 +110,13 @@ playServicesBase = "18.4.0" # https://github.com/halilozercan/compose-richtext/releases richtext = "1.0.0-alpha01" # https://mvnrepository.com/artifact/com.microsoft.signalr/signalr -signalr = "8.0.3" +signalr = "8.0.5" # https://mvnrepository.com/artifact/org.slf4j/slf4j-api slf4j = "2.0.13" # https://github.com/bcgit/bc-java bouncycastle = "1.78.1" # https://github.com/sqlcipher/sqlcipher-android -sqlcipherAndroid = "4.5.7" +sqlcipherAndroid = "4.6.0" # https://github.com/cashapp/sqldelight sqldelight = "2.0.2" # https://github.com/Willena/sqlite-jdbc-crypt @@ -236,9 +234,6 @@ microsoft-signalr = { module = "com.microsoft.signalr:signalr", version.ref = "s microsoft-signalr-messagepack = { module = "com.microsoft.signalr.messagepack:signalr-messagepack", version.ref = "signalr" } mm2d-touchicon = { module = "net.mm2d.touchicon:touchicon", version.ref = "touchIcon" } mm2d-touchicon-http-okhttp = { module = "net.mm2d.touchicon:touchicon-http-okhttp", version.ref = "touchIcon" } -moko-resources = { module = "dev.icerock.moko:resources", version.ref = "moko" } -moko-resources-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "moko" } -moko-resources-test = { module = "dev.icerock.moko:resources-test", version.ref = "moko" } lingala-zip4j = { module = "net.lingala.zip4j:zip4j", version.ref = "zip4j" } nulabinc-zxcvbn = { module = "com.nulab-inc:zxcvbn", version.ref = "zxcvbn4j" } ricecode-string-similarity = { module = "net.ricecode:string-similarity", version.ref = "stringSimilarity" } @@ -264,12 +259,12 @@ kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +kotlin-plugin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlin-plugin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-plugin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "kspPlugin" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlintPlugin" } license-check = { id = "app.cash.licensee", version.ref = "licenseCheckPlugin" } -moko = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogPlugin" } versions = { id = "com.github.ben-manes.versions", version.ref = "versionsPlugin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1a66888..6ffd0835 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Jul 31 15:58:03 EEST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME