refactor(commons): migrate from Moko to Compose Multiplatform Resources

Remove Moko Resources dependency that blocks AGP 9.0 migration.
Migrate to built-in Compose Multiplatform Resources which is compatible
with the new KMP Android plugin.

- Remove moko-resources plugin and libraries from commons module
- Move strings.xml from moko-resources/ to composeResources/values/
- Update imports from SharedRes.strings.* to Res.string.*
- Add compose.components.resources dependency to desktopApp
- Configure resource package as com.vitorpamplona.amethyst.commons.resources

Closes #1675

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-01-25 13:29:55 +02:00
parent 8ebba994e8
commit 71e68dc35b
10 changed files with 68 additions and 47 deletions
+1
View File
@@ -25,6 +25,7 @@ dependencies {
implementation(compose.desktop.currentOs)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation(compose.components.resources)
// Quartz Nostr library (will use JVM target)
implementation(project(":quartz"))
@@ -37,14 +37,16 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.SharedRes
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.login_subtitle_desktop
import com.vitorpamplona.amethyst.commons.resources.login_title
import com.vitorpamplona.amethyst.desktop.account.AccountManager
import com.vitorpamplona.amethyst.desktop.account.AccountState
import com.vitorpamplona.amethyst.desktop.ui.auth.LoginCard
import com.vitorpamplona.amethyst.desktop.ui.auth.NewKeyWarningCard
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.stringResource
@Composable
fun LoginScreen(
@@ -61,7 +63,7 @@ fun LoginScreen(
verticalArrangement = Arrangement.Center,
) {
Text(
stringResource(SharedRes.strings.login_title),
stringResource(Res.string.login_title),
style = MaterialTheme.typography.headlineLarge,
color = MaterialTheme.colorScheme.onBackground,
)
@@ -69,7 +71,7 @@ fun LoginScreen(
Spacer(Modifier.height(8.dp))
Text(
stringResource(SharedRes.strings.login_subtitle_desktop),
stringResource(Res.string.login_subtitle_desktop),
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
@@ -42,8 +42,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.SharedRes
import dev.icerock.moko.resources.compose.stringResource
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.login_hide_key
import com.vitorpamplona.amethyst.commons.resources.login_key_label
import com.vitorpamplona.amethyst.commons.resources.login_key_placeholder
import com.vitorpamplona.amethyst.commons.resources.login_show_key
import org.jetbrains.compose.resources.stringResource
/**
* Text field for entering Nostr keys (nsec or npub) with visibility toggle.
@@ -53,8 +57,8 @@ fun KeyInputField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
label: String = stringResource(SharedRes.strings.login_key_label),
placeholder: String = stringResource(SharedRes.strings.login_key_placeholder),
label: String = stringResource(Res.string.login_key_label),
placeholder: String = stringResource(Res.string.login_key_placeholder),
errorMessage: String? = null,
) {
var showKey by remember { mutableStateOf(false) }
@@ -76,7 +80,7 @@ fun KeyInputField(
IconButton(onClick = { showKey = !showKey }) {
Icon(
if (showKey) Icons.Default.VisibilityOff else Icons.Default.Visibility,
contentDescription = if (showKey) stringResource(SharedRes.strings.login_hide_key) else stringResource(SharedRes.strings.login_show_key),
contentDescription = if (showKey) stringResource(Res.string.login_hide_key) else stringResource(Res.string.login_show_key),
)
}
},
@@ -44,8 +44,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.SharedRes
import dev.icerock.moko.resources.compose.stringResource
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.login_button
import com.vitorpamplona.amethyst.commons.resources.login_card_subtitle
import com.vitorpamplona.amethyst.commons.resources.login_card_title
import com.vitorpamplona.amethyst.commons.resources.login_generate_button
import org.jetbrains.compose.resources.stringResource
/**
* Login card with Nostr key input field and action buttons.
@@ -63,8 +67,8 @@ fun LoginCard(
onGenerateNew: () -> Unit,
modifier: Modifier = Modifier,
cardWidth: Dp = 400.dp,
title: String = stringResource(SharedRes.strings.login_card_title),
subtitle: String = stringResource(SharedRes.strings.login_card_subtitle),
title: String = stringResource(Res.string.login_card_title),
subtitle: String = stringResource(Res.string.login_card_subtitle),
) {
var keyInput by remember { mutableStateOf("") }
var errorMessage by remember { mutableStateOf<String?>(null) }
@@ -121,14 +125,14 @@ fun LoginCard(
modifier = Modifier.weight(1f),
enabled = keyInput.isNotBlank(),
) {
Text(stringResource(SharedRes.strings.login_button))
Text(stringResource(Res.string.login_button))
}
OutlinedButton(
onClick = onGenerateNew,
modifier = Modifier.weight(1f),
) {
Text(stringResource(SharedRes.strings.login_generate_button))
Text(stringResource(Res.string.login_generate_button))
}
}
}
@@ -37,8 +37,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.SharedRes
import dev.icerock.moko.resources.compose.stringResource
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.new_key_continue_button
import com.vitorpamplona.amethyst.commons.resources.new_key_public_label
import com.vitorpamplona.amethyst.commons.resources.new_key_secret_label
import com.vitorpamplona.amethyst.commons.resources.new_key_warning_message
import com.vitorpamplona.amethyst.commons.resources.new_key_warning_title
import org.jetbrains.compose.resources.stringResource
/**
* Warning card displayed after generating a new Nostr key pair.
@@ -69,7 +74,7 @@ fun NewKeyWarningCard(
modifier = Modifier.padding(24.dp),
) {
Text(
stringResource(SharedRes.strings.new_key_warning_title),
stringResource(Res.string.new_key_warning_title),
style = MaterialTheme.typography.titleMedium,
color = Color.Red,
)
@@ -77,7 +82,7 @@ fun NewKeyWarningCard(
Spacer(Modifier.height(16.dp))
Text(
stringResource(SharedRes.strings.new_key_warning_message),
stringResource(Res.string.new_key_warning_message),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface,
)
@@ -85,7 +90,7 @@ fun NewKeyWarningCard(
Spacer(Modifier.height(16.dp))
Text(
stringResource(SharedRes.strings.new_key_public_label),
stringResource(Res.string.new_key_public_label),
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
@@ -95,7 +100,7 @@ fun NewKeyWarningCard(
nsec?.let { secretKey ->
Text(
stringResource(SharedRes.strings.new_key_secret_label),
stringResource(Res.string.new_key_secret_label),
style = MaterialTheme.typography.labelMedium,
color = Color.Red,
)
@@ -108,7 +113,7 @@ fun NewKeyWarningCard(
onClick = onContinue,
modifier = Modifier.fillMaxWidth(),
) {
Text(stringResource(SharedRes.strings.new_key_continue_button))
Text(stringResource(Res.string.new_key_continue_button))
}
}
}