diff --git a/app/src/main/java/org/searchmob/MainActivity.kt b/app/src/main/java/org/searchmob/MainActivity.kt index 3797535..c979aef 100644 --- a/app/src/main/java/org/searchmob/MainActivity.kt +++ b/app/src/main/java/org/searchmob/MainActivity.kt @@ -34,6 +34,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -347,22 +348,21 @@ private fun UpdateBanner( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - val context = LocalContext.current Text( text = if (inProgress) { - context.getString(R.string.update_banner_downloading, version) + stringResource(R.string.update_banner_downloading, version) } else { - context.getString(R.string.update_banner_available, version) + stringResource(R.string.update_banner_available, version) }, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.weight(1f), ) Button(onClick = onUpdate, enabled = !inProgress) { - Text(context.getString(R.string.update_banner_action)) + Text(stringResource(R.string.update_banner_action)) } TextButton(onClick = onDismiss, enabled = !inProgress) { - Text(context.getString(R.string.update_banner_dismiss)) + Text(stringResource(R.string.update_banner_dismiss)) } } } diff --git a/app/src/main/java/org/searchmob/ui/about/AboutScreen.kt b/app/src/main/java/org/searchmob/ui/about/AboutScreen.kt index 3701bb0..39d1445 100644 --- a/app/src/main/java/org/searchmob/ui/about/AboutScreen.kt +++ b/app/src/main/java/org/searchmob/ui/about/AboutScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp @@ -267,10 +268,10 @@ private fun Footer( } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) @Composable private fun str( id: Int, vararg formatArgs: Any, -): String = LocalContext.current.getString(id, *formatArgs) +): String = stringResource(id, *formatArgs) diff --git a/app/src/main/java/org/searchmob/ui/history/HistoryScreen.kt b/app/src/main/java/org/searchmob/ui/history/HistoryScreen.kt index 403f6da..eeb0221 100644 --- a/app/src/main/java/org/searchmob/ui/history/HistoryScreen.kt +++ b/app/src/main/java/org/searchmob/ui/history/HistoryScreen.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -46,6 +47,10 @@ fun HistoryScreen( ) { val state by viewModel.state.collectAsStateWithLifecycle() val context = LocalContext.current + // The import toast fires in an event-time callback, where composable reads are not allowed, so + // the localized pattern is read here in composition and formatted with the count on completion + // (String.format applies the same positional %1$d substitution getString would). + val importedTemplate = stringResource(R.string.history_imported) val scope = androidx.compose.runtime.rememberCoroutineScope() val exportLauncher = @@ -76,7 +81,7 @@ fun HistoryScreen( viewModel.import(text) { count -> Toast.makeText( context, - context.getString(R.string.history_imported, count), + importedTemplate.format(count), Toast.LENGTH_SHORT, ).show() } @@ -178,4 +183,4 @@ private fun CenteredText(text: String) { } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) diff --git a/app/src/main/java/org/searchmob/ui/home/HomeScreen.kt b/app/src/main/java/org/searchmob/ui/home/HomeScreen.kt index 72a0963..b575013 100644 --- a/app/src/main/java/org/searchmob/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/searchmob/ui/home/HomeScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.searchmob.R @@ -160,4 +161,4 @@ private fun OemGuidanceCard() { } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) diff --git a/app/src/main/java/org/searchmob/ui/onboarding/OnboardingWizard.kt b/app/src/main/java/org/searchmob/ui/onboarding/OnboardingWizard.kt index 5c3e5fb..14dd185 100644 --- a/app/src/main/java/org/searchmob/ui/onboarding/OnboardingWizard.kt +++ b/app/src/main/java/org/searchmob/ui/onboarding/OnboardingWizard.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat @@ -311,4 +312,4 @@ private fun hasNotificationsPermission(context: android.content.Context): Boolea } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) diff --git a/app/src/main/java/org/searchmob/ui/search/SearchScreen.kt b/app/src/main/java/org/searchmob/ui/search/SearchScreen.kt index cedfe86..b88920a 100644 --- a/app/src/main/java/org/searchmob/ui/search/SearchScreen.kt +++ b/app/src/main/java/org/searchmob/ui/search/SearchScreen.kt @@ -51,6 +51,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics @@ -400,7 +401,6 @@ private fun MediaActionsRow( */ @Composable private fun EngineStatusRow(engineStatus: List) { - val context = LocalContext.current var expanded by remember(engineStatus) { mutableStateOf(false) } val responded = engineStatus.count { it.status != EngineStatus.FAILED } Column( @@ -412,7 +412,7 @@ private fun EngineStatusRow(engineStatus: List) { .padding(vertical = 4.dp), ) { Text( - text = context.getString(R.string.search_engines_responded, responded, engineStatus.size), + text = stringResource(R.string.search_engines_responded, responded, engineStatus.size), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -421,7 +421,7 @@ private fun EngineStatusRow(engineStatus: List) { val detail = when (outcome.status) { EngineStatus.CONTRIBUTED -> - context.getString(R.string.search_engine_result_count, outcome.count) + stringResource(R.string.search_engine_result_count, outcome.count) EngineStatus.EMPTY -> stringResource(R.string.engine_status_no_results) EngineStatus.FAILED -> stringResource(R.string.engine_status_failed) } @@ -648,6 +648,3 @@ private fun RankMenu(onSelect: (RankRule) -> Unit) { } } } - -@Composable -private fun stringResource(id: Int): String = LocalContext.current.getString(id) diff --git a/app/src/main/java/org/searchmob/ui/settings/SettingsScreen.kt b/app/src/main/java/org/searchmob/ui/settings/SettingsScreen.kt index ab6c8a6..ce706a9 100644 --- a/app/src/main/java/org/searchmob/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/org/searchmob/ui/settings/SettingsScreen.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics @@ -1000,10 +1001,10 @@ private fun PasteTextDialog( } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) @Composable private fun str( id: Int, vararg formatArgs: Any, -): String = LocalContext.current.getString(id, *formatArgs) +): String = stringResource(id, *formatArgs) diff --git a/app/src/main/java/org/searchmob/ui/setup/BrowserSetupScreen.kt b/app/src/main/java/org/searchmob/ui/setup/BrowserSetupScreen.kt index f833bdd..404da84 100644 --- a/app/src/main/java/org/searchmob/ui/setup/BrowserSetupScreen.kt +++ b/app/src/main/java/org/searchmob/ui/setup/BrowserSetupScreen.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.platform.ClipboardManager import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -279,4 +280,4 @@ private fun InstructionCard( } @Composable -private fun str(id: Int): String = LocalContext.current.getString(id) +private fun str(id: Int): String = stringResource(id) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2110e34..61a128d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,16 +3,16 @@ agp = "9.2.1" kotlin = "2.4.0" coreKtx = "1.19.0" activityCompose = "1.13.0" -lifecycleRuntimeKtx = "2.10.0" +lifecycleRuntimeKtx = "2.11.0" composeBom = "2024.12.01" navigationCompose = "2.9.8" -lifecycleViewmodelCompose = "2.10.0" +lifecycleViewmodelCompose = "2.11.0" junit = "4.13.2" junitExt = "1.3.0" espressoCore = "3.7.0" ktlintPlugin = "12.3.0" coroutines = "1.11.0" -ktor = "3.5.0" +ktor = "3.5.1" okhttp = "4.12.0" jsoup = "1.22.2" coil = "2.7.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 65d8749..dbe66e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=bbaeb2fef8710818cf0e261201dab964c572f92b942812df0c3620d62a529a01 -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionSha256Sum=9c0f7faeeb306cb14e4279a3e084ca6b596894089a0638e68a07c945a32c9e14 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500