feat(i18n): bulk-migrate 2,565 mechanically-safe string keys to commons

Every key whose usages are all composable stringRes/stringResource
calls, with no XML references, no bare %s/%d, only %N$s/%N$d args and
no inline markup, moves from the app's res/ to commons Compose
resources (~105,800 locale entries across 57 locales, translations
preserved byte-for-byte for Crowdin). 568 app files repointed to
Res.string via the stringRes bridge overloads.

The app keeps 1,866 keys that are genuinely Android-bound: ctx-based
call sites, Int-typed id storage (maps/whens), @string/ XML references,
and non-positional format args.

Tool fix folded in: Crowdin emits some entries with attributes before
name= (xmlns:ns0=... name="key") - the extraction regex now matches
any attribute order; the six entries the old pattern missed (zh,
nl-rBE, es x account_backup_tips{2,3}_md) are relocated, and 11 in-file
duplicates from keys that already existed in commons are removed.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011S1vbFWVVAMFDT8PTgdibV
This commit is contained in:
Claude
2026-09-01 03:31:48 +00:00
parent 8128507c12
commit 7c6a18ee52
683 changed files with 113853 additions and 110487 deletions
@@ -54,9 +54,19 @@ import com.halilibo.richtext.markdown.BasicMarkdown
import com.halilibo.richtext.ui.RichTextStyle import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.material3.RichText import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.resolveDefaults import com.halilibo.richtext.ui.resolveDefaults
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_dialog_button_ok
import com.vitorpamplona.amethyst.commons.resources.push_server_explainer
import com.vitorpamplona.amethyst.commons.resources.push_server_install_app
import com.vitorpamplona.amethyst.commons.resources.push_server_install_app_description
import com.vitorpamplona.amethyst.commons.resources.push_server_none
import com.vitorpamplona.amethyst.commons.resources.push_server_none_explainer
import com.vitorpamplona.amethyst.commons.resources.push_server_title
import com.vitorpamplona.amethyst.commons.resources.push_server_uses_app_explainer
import com.vitorpamplona.amethyst.commons.resources.quick_action_dont_show_again_button
import com.vitorpamplona.amethyst.commons.resources.select_push_server
import com.vitorpamplona.amethyst.model.UiSettingsFlow import com.vitorpamplona.amethyst.model.UiSettingsFlow
import com.vitorpamplona.amethyst.service.notifications.PushDistributorHandler import com.vitorpamplona.amethyst.service.notifications.PushDistributorHandler
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsBlockTile import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsBlockTile
@@ -100,7 +110,7 @@ fun SelectNotificationProvider(sharedPrefs: UiSettingsFlow) {
LoadDistributors { currentDistributor, list, readableListWithExplainer -> LoadDistributors { currentDistributor, list, readableListWithExplainer ->
if (readableListWithExplainer.size > 1) { if (readableListWithExplainer.size > 1) {
SpinnerSelectionDialog( SpinnerSelectionDialog(
title = stringRes(id = R.string.select_push_server), title = stringRes(id = Res.string.select_push_server),
options = readableListWithExplainer, options = readableListWithExplainer,
onSelect = { index -> onSelect = { index ->
if (list[index] == "None") { if (list[index] == "None") {
@@ -122,9 +132,9 @@ fun SelectNotificationProvider(sharedPrefs: UiSettingsFlow) {
} else { } else {
AlertDialog( AlertDialog(
onDismissRequest = { distributorPresent = true }, onDismissRequest = { distributorPresent = true },
title = { Text(stringRes(R.string.push_server_install_app)) }, title = { Text(stringRes(Res.string.push_server_install_app)) },
text = { text = {
val content = stringRes(R.string.push_server_install_app_description) val content = stringRes(Res.string.push_server_install_app_description)
val astNode = val astNode =
remember { remember {
@@ -149,7 +159,7 @@ fun SelectNotificationProvider(sharedPrefs: UiSettingsFlow) {
sharedPrefs.dontShowPushNotificationSelector() sharedPrefs.dontShowPushNotificationSelector()
}, },
) { ) {
Text(stringRes(R.string.quick_action_dont_show_again_button)) Text(stringRes(Res.string.quick_action_dont_show_again_button))
} }
Button( Button(
onClick = { distributorPresent = true }, onClick = { distributorPresent = true },
@@ -163,7 +173,7 @@ fun SelectNotificationProvider(sharedPrefs: UiSettingsFlow) {
contentDescription = null, contentDescription = null,
) )
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(8.dp))
Text(stringRes(R.string.error_dialog_button_ok)) Text(stringRes(Res.string.error_dialog_button_ok))
} }
} }
} }
@@ -191,12 +201,12 @@ fun LoadDistributors(onInner: @Composable (String, ImmutableList<String>, Immuta
.mapIndexed { index, name -> .mapIndexed { index, name ->
TitleExplainer( TitleExplainer(
name, name,
stringRes(id = R.string.push_server_uses_app_explainer, list[index]), stringRes(id = Res.string.push_server_uses_app_explainer, list[index]),
) )
}.plus( }.plus(
TitleExplainer( TitleExplainer(
stringRes(id = R.string.push_server_none), stringRes(id = Res.string.push_server_none),
stringRes(id = R.string.push_server_none_explainer), stringRes(id = Res.string.push_server_none_explainer),
), ),
).toImmutableList() ).toImmutableList()
@@ -217,8 +227,8 @@ fun PushNotificationProviderTile(sharedPrefs: UiSettingsFlow) {
val selectedIndex = list.indexOf(currentDistributor).coerceAtLeast(0) val selectedIndex = list.indexOf(currentDistributor).coerceAtLeast(0)
SettingsBlockTile( SettingsBlockTile(
icon = MaterialSymbols.CloudSync, icon = MaterialSymbols.CloudSync,
title = stringRes(R.string.push_server_title), title = stringRes(Res.string.push_server_title),
description = stringRes(R.string.push_server_explainer), description = stringRes(Res.string.push_server_explainer),
) { ) {
TextSpinner( TextSpinner(
label = null, label = null,
@@ -65,6 +65,19 @@ import com.vitorpamplona.amethyst.commons.favorites.FavoriteAppIcon
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.napplet_connect_block
import com.vitorpamplona.amethyst.commons.resources.napplet_connect_button
import com.vitorpamplona.amethyst.commons.resources.napplet_connect_how_handle
import com.vitorpamplona.amethyst.commons.resources.napplet_connect_subtitle
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_full_trust
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_full_trust_desc
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_paranoid
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_paranoid_desc
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_reasonable
import com.vitorpamplona.amethyst.commons.resources.napplet_policy_reasonable_desc
import com.vitorpamplona.amethyst.commons.resources.nip46_connect_requests_title
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.AmethystTheme import com.vitorpamplona.amethyst.ui.theme.AmethystTheme
class SignerConnectActivity : ComponentActivity() { class SignerConnectActivity : ComponentActivity() {
@@ -164,7 +177,7 @@ private fun SignerConnectScreen(
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
Text( Text(
stringResource(R.string.napplet_connect_subtitle), stringRes(Res.string.napplet_connect_subtitle),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@@ -193,7 +206,7 @@ private fun SignerConnectScreen(
) { ) {
Column(modifier = Modifier.padding(14.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { Column(modifier = Modifier.padding(14.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
Text( Text(
stringResource(R.string.nip46_connect_requests_title), stringRes(Res.string.nip46_connect_requests_title),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
) )
info.requestedPermissions.forEach { perm -> info.requestedPermissions.forEach { perm ->
@@ -216,7 +229,7 @@ private fun SignerConnectScreen(
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
Text( Text(
stringResource(R.string.napplet_connect_how_handle), stringRes(Res.string.napplet_connect_how_handle),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) )
@@ -230,22 +243,22 @@ private fun SignerConnectScreen(
PolicyOption( PolicyOption(
selected = selected == AppSignerPolicy.FULL_TRUST, selected = selected == AppSignerPolicy.FULL_TRUST,
symbol = MaterialSymbols.LockOpen, symbol = MaterialSymbols.LockOpen,
label = stringResource(R.string.napplet_policy_full_trust), label = stringRes(Res.string.napplet_policy_full_trust),
description = stringResource(R.string.napplet_policy_full_trust_desc), description = stringRes(Res.string.napplet_policy_full_trust_desc),
onClick = { selected = AppSignerPolicy.FULL_TRUST }, onClick = { selected = AppSignerPolicy.FULL_TRUST },
) )
PolicyOption( PolicyOption(
selected = selected == AppSignerPolicy.REASONABLE, selected = selected == AppSignerPolicy.REASONABLE,
symbol = MaterialSymbols.Shield, symbol = MaterialSymbols.Shield,
label = stringResource(R.string.napplet_policy_reasonable), label = stringRes(Res.string.napplet_policy_reasonable),
description = stringResource(R.string.napplet_policy_reasonable_desc), description = stringRes(Res.string.napplet_policy_reasonable_desc),
onClick = { selected = AppSignerPolicy.REASONABLE }, onClick = { selected = AppSignerPolicy.REASONABLE },
) )
PolicyOption( PolicyOption(
selected = selected == AppSignerPolicy.PARANOID, selected = selected == AppSignerPolicy.PARANOID,
symbol = MaterialSymbols.Lock, symbol = MaterialSymbols.Lock,
label = stringResource(R.string.napplet_policy_paranoid), label = stringRes(Res.string.napplet_policy_paranoid),
description = stringResource(R.string.napplet_policy_paranoid_desc), description = stringRes(Res.string.napplet_policy_paranoid_desc),
onClick = { selected = AppSignerPolicy.PARANOID }, onClick = { selected = AppSignerPolicy.PARANOID },
) )
} }
@@ -262,7 +275,7 @@ private fun SignerConnectScreen(
Text(stringResource(R.string.cancel)) Text(stringResource(R.string.cancel))
} }
Button(onClick = { onConnect(selected) }, modifier = Modifier.weight(1f)) { Button(onClick = { onConnect(selected) }, modifier = Modifier.weight(1f)) {
Text(stringResource(R.string.napplet_connect_button)) Text(stringRes(Res.string.napplet_connect_button))
} }
} }
@@ -272,7 +285,7 @@ private fun SignerConnectScreen(
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { ) {
Text( Text(
stringResource(R.string.napplet_connect_block, info.domain), stringRes(Res.string.napplet_connect_block, info.domain),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
} }
@@ -75,11 +75,31 @@ import com.vitorpamplona.amethyst.commons.favorites.FavoriteApp
import com.vitorpamplona.amethyst.commons.favorites.FavoriteAppIcon import com.vitorpamplona.amethyst.commons.favorites.FavoriteAppIcon
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_allow_always
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_fewer_options
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_hide_event
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_more_options
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_show_event
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_wants_to
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_allow_24h
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_allow_30d
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_allow_all
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_allow_once
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_allow_session
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_deny_once
import com.vitorpamplona.amethyst.commons.resources.napplet_signer_deny_op
import com.vitorpamplona.amethyst.commons.resources.nip46_signer_batch_allow
import com.vitorpamplona.amethyst.commons.resources.nip46_signer_batch_deny
import com.vitorpamplona.amethyst.commons.resources.nip46_signer_batch_remember
import com.vitorpamplona.amethyst.commons.resources.nip46_signer_batch_signing_as
import com.vitorpamplona.amethyst.commons.resources.nip46_signer_messages_with
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.call.CallSessionBridge import com.vitorpamplona.amethyst.service.call.CallSessionBridge
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.note.NoteCompose import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.AmethystTheme import com.vitorpamplona.amethyst.ui.theme.AmethystTheme
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorAssembler import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorAssembler
@@ -184,7 +204,7 @@ private fun SignerConsentDialog(
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
Text( Text(
stringResource(R.string.napplet_consent_wants_to, info.operationSummary), stringRes(Res.string.napplet_consent_wants_to, info.operationSummary),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@@ -197,7 +217,7 @@ private fun SignerConsentDialog(
// that person as an avatar + name, never as nothing. // that person as an avatar + name, never as nothing.
if (info.counterpartyName != null) { if (info.counterpartyName != null) {
Text( Text(
stringResource(R.string.nip46_signer_messages_with), stringRes(Res.string.nip46_signer_messages_with),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -230,14 +250,14 @@ private fun SignerConsentDialog(
onClick = { onGrant(SignerOpGrant.AllowForOp(info.op)) }, onClick = { onGrant(SignerOpGrant.AllowForOp(info.op)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_consent_allow_always)) Text(stringRes(Res.string.napplet_consent_allow_always))
} }
} else { } else {
Button( Button(
onClick = { onGrant(SignerOpGrant.AllowForOp(info.op)) }, onClick = { onGrant(SignerOpGrant.AllowForOp(info.op)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_consent_allow_always)) Text(stringRes(Res.string.napplet_consent_allow_always))
} }
} }
@@ -246,7 +266,7 @@ private fun SignerConsentDialog(
onClick = { onGrant(SignerOpGrant.AllowOnce) }, onClick = { onGrant(SignerOpGrant.AllowOnce) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_signer_allow_once)) Text(stringRes(Res.string.napplet_signer_allow_once))
} }
// "More options" toggle: session and time-bound grants // "More options" toggle: session and time-bound grants
@@ -261,9 +281,9 @@ private fun SignerConsentDialog(
) { ) {
Text( Text(
if (showMoreOptions) { if (showMoreOptions) {
stringResource(R.string.napplet_consent_fewer_options) stringRes(Res.string.napplet_consent_fewer_options)
} else { } else {
stringResource(R.string.napplet_consent_more_options) stringRes(Res.string.napplet_consent_more_options)
}, },
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
@@ -280,25 +300,25 @@ private fun SignerConsentDialog(
onClick = { onGrant(SignerOpGrant.AllowForSession(info.op)) }, onClick = { onGrant(SignerOpGrant.AllowForSession(info.op)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_signer_allow_session)) Text(stringRes(Res.string.napplet_signer_allow_session))
} }
OutlinedButton( OutlinedButton(
onClick = { onGrant(SignerOpGrant.AllowUntil(info.op, TimeUtils.now() + 86_400L)) }, onClick = { onGrant(SignerOpGrant.AllowUntil(info.op, TimeUtils.now() + 86_400L)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_signer_allow_24h)) Text(stringRes(Res.string.napplet_signer_allow_24h))
} }
OutlinedButton( OutlinedButton(
onClick = { onGrant(SignerOpGrant.AllowUntil(info.op, TimeUtils.now() + 30L * 86_400L)) }, onClick = { onGrant(SignerOpGrant.AllowUntil(info.op, TimeUtils.now() + 30L * 86_400L)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_signer_allow_30d)) Text(stringRes(Res.string.napplet_signer_allow_30d))
} }
OutlinedButton( OutlinedButton(
onClick = { onGrant(SignerOpGrant.AllowAll) }, onClick = { onGrant(SignerOpGrant.AllowAll) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_signer_allow_all)) Text(stringRes(Res.string.napplet_signer_allow_all))
} }
} }
@@ -311,14 +331,14 @@ private fun SignerConsentDialog(
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { ) {
Text(stringResource(R.string.napplet_signer_deny_once)) Text(stringRes(Res.string.napplet_signer_deny_once))
} }
OutlinedButton( OutlinedButton(
onClick = { onGrant(SignerOpGrant.DenyForOp(info.op)) }, onClick = { onGrant(SignerOpGrant.DenyForOp(info.op)) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { ) {
Text(stringResource(R.string.napplet_signer_deny_op, info.operationSummary)) Text(stringRes(Res.string.napplet_signer_deny_op, info.operationSummary))
} }
} }
} }
@@ -390,9 +410,9 @@ private fun SignerConsentPreview(info: SignerConsentInfo) {
) { ) {
Text( Text(
if (showRawData) { if (showRawData) {
stringResource(R.string.napplet_consent_hide_event) stringRes(Res.string.napplet_consent_hide_event)
} else { } else {
stringResource(R.string.napplet_consent_show_event) stringRes(Res.string.napplet_consent_show_event)
}, },
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
) )
@@ -468,7 +488,7 @@ private fun BatchedConsentDialog(
) )
account.accountName?.let { name -> account.accountName?.let { name ->
Text( Text(
stringResource(R.string.nip46_signer_batch_signing_as, name), stringRes(Res.string.nip46_signer_batch_signing_as, name),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1, maxLines = 1,
@@ -553,7 +573,7 @@ private fun BatchedConsentDialog(
) { ) {
Switch(checked = rememberChoice, onCheckedChange = { rememberChoice = it }) Switch(checked = rememberChoice, onCheckedChange = { rememberChoice = it })
Text( Text(
stringResource(R.string.nip46_signer_batch_remember), stringRes(Res.string.nip46_signer_batch_remember),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
} }
@@ -575,7 +595,7 @@ private fun BatchedConsentDialog(
enabled = selected.isNotEmpty(), enabled = selected.isNotEmpty(),
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.nip46_signer_batch_allow, selected.size)) Text(stringRes(Res.string.nip46_signer_batch_allow, selected.size))
} }
OutlinedButton( OutlinedButton(
onClick = { onResolve(pending.filter { it.token in selected }.map { it.token }, SignerOpGrant.DenyOnce) }, onClick = { onResolve(pending.filter { it.token in selected }.map { it.token }, SignerOpGrant.DenyOnce) },
@@ -583,7 +603,7 @@ private fun BatchedConsentDialog(
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { ) {
Text(stringResource(R.string.nip46_signer_batch_deny, selected.size)) Text(stringRes(Res.string.nip46_signer_batch_deny, selected.size))
} }
} }
} }
@@ -55,17 +55,23 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.favorites.FavoriteApp import com.vitorpamplona.amethyst.commons.favorites.FavoriteApp
import com.vitorpamplona.amethyst.commons.favorites.FavoriteAppIcon import com.vitorpamplona.amethyst.commons.favorites.FavoriteAppIcon
import com.vitorpamplona.amethyst.commons.napplet.permissions.GrantState import com.vitorpamplona.amethyst.commons.napplet.permissions.GrantState
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_allow_always
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_allow_once
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_deny_always
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_hide_event
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_not_now
import com.vitorpamplona.amethyst.commons.resources.napplet_consent_show_event
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.AmethystTheme import com.vitorpamplona.amethyst.ui.theme.AmethystTheme
/** /**
@@ -240,9 +246,9 @@ private fun NappletConsentDialog(
TextButton(onClick = { showRawData = !showRawData }) { TextButton(onClick = { showRawData = !showRawData }) {
Text( Text(
if (showRawData) { if (showRawData) {
stringResource(R.string.napplet_consent_hide_event) stringRes(Res.string.napplet_consent_hide_event)
} else { } else {
stringResource(R.string.napplet_consent_show_event) stringRes(Res.string.napplet_consent_show_event)
}, },
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
) )
@@ -261,20 +267,20 @@ private fun NappletConsentDialog(
onClick = { onDecision(GrantState.ALLOW_ALWAYS) }, onClick = { onDecision(GrantState.ALLOW_ALWAYS) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_consent_allow_always)) Text(stringRes(Res.string.napplet_consent_allow_always))
} }
OutlinedButton( OutlinedButton(
onClick = { onDecision(GrantState.ALLOW_ONCE) }, onClick = { onDecision(GrantState.ALLOW_ONCE) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_consent_allow_once)) Text(stringRes(Res.string.napplet_consent_allow_once))
} }
} else { } else {
Button( Button(
onClick = { onDecision(GrantState.ALLOW_ONCE) }, onClick = { onDecision(GrantState.ALLOW_ONCE) },
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text(stringResource(R.string.napplet_consent_allow_once)) Text(stringRes(Res.string.napplet_consent_allow_once))
} }
} }
@@ -287,7 +293,7 @@ private fun NappletConsentDialog(
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
) { ) {
Text( Text(
stringResource(R.string.napplet_consent_not_now), stringRes(Res.string.napplet_consent_not_now),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
} }
@@ -297,7 +303,7 @@ private fun NappletConsentDialog(
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { ) {
Text( Text(
stringResource(R.string.napplet_consent_deny_always), stringRes(Res.string.napplet_consent_deny_always),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
} }
@@ -33,11 +33,14 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.res.stringResource
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.crashreport_found
import com.vitorpamplona.amethyst.commons.resources.crashreport_found_send
import com.vitorpamplona.amethyst.commons.resources.would_you_like_to_send_the_recent_crash_report_to_amethyst_in_a_dm_no_personal_information_will_be_shared
import com.vitorpamplona.amethyst.commons.service.crashreports.DEV_REPORT_PUBKEY import com.vitorpamplona.amethyst.commons.service.crashreports.DEV_REPORT_PUBKEY
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -65,10 +68,10 @@ fun DisplayCrashMessages(
stackTrace.value?.let { stack -> stackTrace.value?.let { stack ->
AlertDialog( AlertDialog(
onDismissRequest = { stackTrace.value = null }, onDismissRequest = { stackTrace.value = null },
title = { Text(stringResource(R.string.crashreport_found)) }, title = { Text(stringRes(Res.string.crashreport_found)) },
text = { text = {
SelectionContainer { SelectionContainer {
Text(stringResource(R.string.would_you_like_to_send_the_recent_crash_report_to_amethyst_in_a_dm_no_personal_information_will_be_shared)) Text(stringRes(Res.string.would_you_like_to_send_the_recent_crash_report_to_amethyst_in_a_dm_no_personal_information_will_be_shared))
} }
}, },
dismissButton = { dismissButton = {
@@ -96,10 +99,10 @@ fun DisplayCrashMessages(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Done, symbol = MaterialSymbols.Done,
contentDescription = stringRes(R.string.crashreport_found_send), contentDescription = stringRes(Res.string.crashreport_found_send),
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.crashreport_found_send)) Text(stringRes(Res.string.crashreport_found_send))
} }
} }
}, },
@@ -37,9 +37,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.enter_picture_in_picture
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
@@ -86,7 +87,7 @@ fun FullScreenButton(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.ZoomOutMap, symbol = MaterialSymbols.ZoomOutMap,
contentDescription = stringRes(id = R.string.enter_picture_in_picture), contentDescription = stringRes(id = Res.string.enter_picture_in_picture),
modifier = modifier, modifier = modifier,
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
@@ -41,6 +41,11 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_settings_video_quality
import com.vitorpamplona.amethyst.commons.resources.picture_in_picture
import com.vitorpamplona.amethyst.commons.resources.playback_actions_dialog_title
import com.vitorpamplona.amethyst.commons.resources.video_player_settings_action_fullscreen
import com.vitorpamplona.amethyst.model.VideoPlayerAction import com.vitorpamplona.amethyst.model.VideoPlayerAction
import com.vitorpamplona.amethyst.ui.components.M3ActionDialog import com.vitorpamplona.amethyst.ui.components.M3ActionDialog
import com.vitorpamplona.amethyst.ui.components.M3ActionRow import com.vitorpamplona.amethyst.ui.components.M3ActionRow
@@ -157,7 +162,7 @@ fun OverflowMenuButton(
if (menuExpanded.value) { if (menuExpanded.value) {
M3ActionDialog( M3ActionDialog(
title = stringRes(R.string.playback_actions_dialog_title), title = stringRes(Res.string.playback_actions_dialog_title),
onDismiss = { menuExpanded.value = false }, onDismiss = { menuExpanded.value = false },
) { ) {
M3ActionSection { M3ActionSection {
@@ -167,7 +172,7 @@ fun OverflowMenuButton(
onFullscreenClick?.let { zoom -> onFullscreenClick?.let { zoom ->
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.ZoomOutMap, icon = MaterialSymbols.ZoomOutMap,
text = stringRes(R.string.video_player_settings_action_fullscreen), text = stringRes(Res.string.video_player_settings_action_fullscreen),
) { ) {
menuExpanded.value = false menuExpanded.value = false
zoom() zoom()
@@ -188,7 +193,7 @@ fun OverflowMenuButton(
VideoPlayerAction.Quality -> { VideoPlayerAction.Quality -> {
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.Settings, icon = MaterialSymbols.Settings,
text = stringRes(R.string.call_settings_video_quality), text = stringRes(Res.string.call_settings_video_quality),
) { ) {
menuExpanded.value = false menuExpanded.value = false
onQualityClick() onQualityClick()
@@ -218,7 +223,7 @@ fun OverflowMenuButton(
VideoPlayerAction.PictureInPicture -> { VideoPlayerAction.PictureInPicture -> {
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.PictureInPicture, icon = MaterialSymbols.PictureInPicture,
text = stringRes(R.string.picture_in_picture), text = stringRes(Res.string.picture_in_picture),
) { ) {
menuExpanded.value = false menuExpanded.value = false
onPipClick() onPipClick()
@@ -55,6 +55,8 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.picture_in_picture
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
import com.vitorpamplona.amethyst.model.VideoButtonLocation import com.vitorpamplona.amethyst.model.VideoButtonLocation
import com.vitorpamplona.amethyst.model.VideoPlayerAction import com.vitorpamplona.amethyst.model.VideoPlayerAction
@@ -362,7 +364,7 @@ fun RenderTopButtons(
AnimatedTopBarIconButton( AnimatedTopBarIconButton(
controllerVisible = controllerVisible, controllerVisible = controllerVisible,
symbol = MaterialSymbols.PictureInPicture, symbol = MaterialSymbols.PictureInPicture,
contentDescription = stringRes(R.string.picture_in_picture), contentDescription = stringRes(Res.string.picture_in_picture),
onClick = onPictureInPictureClick, onClick = onPictureInPictureClick,
) )
} }
@@ -52,9 +52,11 @@ import androidx.media3.common.Player
import androidx.media3.common.Tracks import androidx.media3.common.Tracks
import androidx.media3.common.VideoSize import androidx.media3.common.VideoSize
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_settings_video_quality
import com.vitorpamplona.amethyst.commons.resources.video_quality_auto
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
@@ -108,7 +110,7 @@ fun VideoQualityButton(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Settings, symbol = MaterialSymbols.Settings,
contentDescription = stringRes(id = R.string.call_settings_video_quality), contentDescription = stringRes(id = Res.string.call_settings_video_quality),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
modifier = Size20Modifier, modifier = Size20Modifier,
) )
@@ -192,7 +194,7 @@ private fun VideoQualityChoices(
TextButton(colors = colors, onClick = onSelectAuto) { TextButton(colors = colors, onClick = onSelectAuto) {
val suffix = currentShortSide?.let { " (${it}p)" } ?: "" val suffix = currentShortSide?.let { " (${it}p)" } ?: ""
Text( Text(
stringRes(R.string.video_quality_auto) + suffix, stringRes(Res.string.video_quality_auto) + suffix,
fontWeight = if (isAuto) FontWeight(1000) else FontWeight(400), fontWeight = if (isAuto) FontWeight(1000) else FontWeight(400),
) )
} }
@@ -69,6 +69,25 @@ import com.vitorpamplona.amethyst.commons.relayClient.auth.RelayAuthPrompt
import com.vitorpamplona.amethyst.commons.relayClient.auth.UserAuthChoice import com.vitorpamplona.amethyst.commons.relayClient.auth.UserAuthChoice
import com.vitorpamplona.amethyst.commons.relayauth.AuthPurpose import com.vitorpamplona.amethyst.commons.relayauth.AuthPurpose
import com.vitorpamplona.amethyst.commons.relayauth.AuthPurposeKind import com.vitorpamplona.amethyst.commons.relayauth.AuthPurposeKind
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.relay_auth_how_we_decide
import com.vitorpamplona.amethyst.commons.resources.relay_auth_log_in
import com.vitorpamplona.amethyst.commons.resources.relay_auth_login_as
import com.vitorpamplona.amethyst.commons.resources.relay_auth_never_allow
import com.vitorpamplona.amethyst.commons.resources.relay_auth_not_now
import com.vitorpamplona.amethyst.commons.resources.relay_auth_relay_asks
import com.vitorpamplona.amethyst.commons.resources.relay_auth_remember_relay
import com.vitorpamplona.amethyst.commons.resources.relay_auth_someone_unloaded
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_my_inbox
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_my_own_relay
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_notify_inbox
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_other
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_post_venue
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_read_outbox
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_read_venue
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_send_dm
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_thread
import com.vitorpamplona.amethyst.commons.resources.relay_auth_why_thread_with
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannel import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannel
@@ -189,7 +208,7 @@ private fun RelayAuthPromptDialog(
Column(verticalArrangement = Arrangement.spacedBy(14.dp)) { Column(verticalArrangement = Arrangement.spacedBy(14.dp)) {
RelayHeader(prompt, accountViewModel) RelayHeader(prompt, accountViewModel)
Text( Text(
text = stringRes(R.string.relay_auth_login_as, rememberDisplayName(prompt.askingAccount, accountViewModel)), text = stringRes(Res.string.relay_auth_login_as, rememberDisplayName(prompt.askingAccount, accountViewModel)),
style = MaterialTheme.typography.headlineSmall, style = MaterialTheme.typography.headlineSmall,
) )
} }
@@ -227,11 +246,11 @@ private fun RelayAuthPromptDialog(
OutlinedButton( OutlinedButton(
onClick = { onChoice(UserAuthChoice.DISMISS) }, onClick = { onChoice(UserAuthChoice.DISMISS) },
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) { Text(stringRes(R.string.relay_auth_not_now)) } ) { Text(stringRes(Res.string.relay_auth_not_now)) }
Button( Button(
onClick = { onChoice(if (rememberRelay) UserAuthChoice.ALWAYS_ALLOW else UserAuthChoice.ALLOW_ONCE) }, onClick = { onChoice(if (rememberRelay) UserAuthChoice.ALWAYS_ALLOW else UserAuthChoice.ALLOW_ONCE) },
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) { Text(stringRes(R.string.relay_auth_log_in)) } ) { Text(stringRes(Res.string.relay_auth_log_in)) }
} }
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -240,13 +259,13 @@ private fun RelayAuthPromptDialog(
TextButton( TextButton(
onClick = { onChoice(UserAuthChoice.BLOCK) }, onClick = { onChoice(UserAuthChoice.BLOCK) },
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error), colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error),
) { Text(stringRes(R.string.relay_auth_never_allow), style = MaterialTheme.typography.labelMedium) } ) { Text(stringRes(Res.string.relay_auth_never_allow), style = MaterialTheme.typography.labelMedium) }
TextButton( TextButton(
onClick = { onClick = {
onChoice(UserAuthChoice.DISMISS) onChoice(UserAuthChoice.DISMISS)
nav.nav(Route.RelayAuthSettings) nav.nav(Route.RelayAuthSettings)
}, },
) { Text(stringRes(R.string.relay_auth_how_we_decide), style = MaterialTheme.typography.labelMedium) } ) { Text(stringRes(Res.string.relay_auth_how_we_decide), style = MaterialTheme.typography.labelMedium) }
} }
} }
}, },
@@ -282,7 +301,7 @@ private fun RelayHeader(
overflow = TextOverflow.MiddleEllipsis, overflow = TextOverflow.MiddleEllipsis,
) )
Text( Text(
text = stringRes(R.string.relay_auth_relay_asks), text = stringRes(Res.string.relay_auth_relay_asks),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -359,7 +378,7 @@ private fun RememberRow(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = stringRes(R.string.relay_auth_remember_relay), text = stringRes(Res.string.relay_auth_remember_relay),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) )
@@ -400,29 +419,29 @@ private fun reasonFor(
isMyOwnRelay: Boolean, isMyOwnRelay: Boolean,
): String = ): String =
when (kind) { when (kind) {
AuthPurposeKind.SEND_DM -> stringRes(R.string.relay_auth_why_send_dm, who ?: "") AuthPurposeKind.SEND_DM -> stringRes(Res.string.relay_auth_why_send_dm, who ?: "")
AuthPurposeKind.NOTIFY_INBOX -> stringRes(R.string.relay_auth_why_notify_inbox, who ?: "") AuthPurposeKind.NOTIFY_INBOX -> stringRes(Res.string.relay_auth_why_notify_inbox, who ?: "")
AuthPurposeKind.READ_OUTBOX -> stringRes(R.string.relay_auth_why_read_outbox, who ?: "") AuthPurposeKind.READ_OUTBOX -> stringRes(Res.string.relay_auth_why_read_outbox, who ?: "")
AuthPurposeKind.POST_VENUE -> stringRes(R.string.relay_auth_why_post_venue, who ?: "") AuthPurposeKind.POST_VENUE -> stringRes(Res.string.relay_auth_why_post_venue, who ?: "")
AuthPurposeKind.READ_VENUE -> stringRes(R.string.relay_auth_why_read_venue, who ?: "") AuthPurposeKind.READ_VENUE -> stringRes(Res.string.relay_auth_why_read_venue, who ?: "")
AuthPurposeKind.MY_INBOX -> stringRes(R.string.relay_auth_why_my_inbox) AuthPurposeKind.MY_INBOX -> stringRes(Res.string.relay_auth_why_my_inbox)
// Name the conversation by who is in it — but only when that name is a real one. Splicing the // Name the conversation by who is in it — but only when that name is a real one. Splicing the
// unloaded placeholder in gives "your conversation with someone you haven't loaded yet", which // unloaded placeholder in gives "your conversation with someone you haven't loaded yet", which
// is longer than the vague version and no more informative, so it falls back instead. // is longer than the vague version and no more informative, so it falls back instead.
AuthPurposeKind.THREAD -> AuthPurposeKind.THREAD ->
if (who.isNullOrBlank() || who.startsWith(stringRes(R.string.relay_auth_someone_unloaded))) { if (who.isNullOrBlank() || who.startsWith(stringRes(Res.string.relay_auth_someone_unloaded))) {
stringRes(R.string.relay_auth_why_thread) stringRes(Res.string.relay_auth_why_thread)
} else { } else {
stringRes(R.string.relay_auth_why_thread_with, who) stringRes(Res.string.relay_auth_why_thread_with, who)
} }
// No attributable purpose. If it is the user's own relay we can at least say that much, // No attributable purpose. If it is the user's own relay we can at least say that much,
// which is the only way MY_OWN_RELAY is ever reachable — the deriver is account-agnostic // which is the only way MY_OWN_RELAY is ever reachable — the deriver is account-agnostic
// (one shared socket, many accounts) so it cannot know whose relay this is. // (one shared socket, many accounts) so it cannot know whose relay this is.
else -> else ->
if (isMyOwnRelay) { if (isMyOwnRelay) {
stringRes(R.string.relay_auth_why_my_own_relay) stringRes(Res.string.relay_auth_why_my_own_relay)
} else { } else {
stringRes(R.string.relay_auth_why_other) stringRes(Res.string.relay_auth_why_other)
} }
} }
@@ -472,11 +491,11 @@ private fun rememberCounterpartyName(
if (user == null) { if (user == null) {
LaunchedEffect(pubkey) { user = accountViewModel.checkGetOrCreateUser(pubkey) } LaunchedEffect(pubkey) { user = accountViewModel.checkGetOrCreateUser(pubkey) }
} }
val loaded = user ?: return stringRes(R.string.relay_auth_someone_unloaded) val loaded = user ?: return stringRes(Res.string.relay_auth_someone_unloaded)
val metadata by observeUserInfo(loaded, accountViewModel) val metadata by observeUserInfo(loaded, accountViewModel)
return metadata?.info?.bestName() return metadata?.info?.bestName()
?: loaded.metadataOrNull()?.bestName() ?: loaded.metadataOrNull()?.bestName()
?: stringRes(R.string.relay_auth_someone_unloaded) ?: stringRes(Res.string.relay_auth_someone_unloaded)
} }
/** /**
@@ -572,7 +591,7 @@ private fun rememberDisplayName(
if (user == null) { if (user == null) {
LaunchedEffect(pubkey) { user = accountViewModel.checkGetOrCreateUser(pubkey) } LaunchedEffect(pubkey) { user = accountViewModel.checkGetOrCreateUser(pubkey) }
} }
val loaded = user ?: return stringRes(R.string.relay_auth_someone_unloaded) val loaded = user ?: return stringRes(Res.string.relay_auth_someone_unloaded)
// Reading the observed metadata registers a snapshot read, so the name updates when it arrives. // Reading the observed metadata registers a snapshot read, so the name updates when it arrives.
val metadata by observeUserInfo(loaded, accountViewModel) val metadata by observeUserInfo(loaded, accountViewModel)
return metadata?.info?.bestName() ?: loaded.toBestDisplayName() return metadata?.info?.bestName() ?: loaded.toBestDisplayName()
@@ -35,10 +35,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.commons.model.EmptyTagList
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_dialog_button_ok
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.navs.rememberExtendedNav import com.vitorpamplona.amethyst.ui.navigation.navs.rememberExtendedNav
@@ -90,7 +91,7 @@ fun NotifyRequestDialog(
contentDescription = null, contentDescription = null,
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_button_ok)) Text(stringRes(Res.string.error_dialog_button_ok))
} }
} }
}, },
@@ -34,6 +34,11 @@ import androidx.compose.ui.res.pluralStringResource
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.collectMemorySnapshot import com.vitorpamplona.amethyst.collectMemorySnapshot
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.resource_usage_alert_not_now
import com.vitorpamplona.amethyst.commons.resources.resource_usage_alert_opt_out
import com.vitorpamplona.amethyst.commons.resources.resource_usage_alert_send
import com.vitorpamplona.amethyst.commons.resources.resource_usage_alert_title
import com.vitorpamplona.amethyst.commons.service.crashreports.DEV_REPORT_PUBKEY import com.vitorpamplona.amethyst.commons.service.crashreports.DEV_REPORT_PUBKEY
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -102,7 +107,7 @@ fun DisplayResourceUsageAlert(
alert.value?.let { found -> alert.value?.let { found ->
AlertDialog( AlertDialog(
onDismissRequest = dismiss, onDismissRequest = dismiss,
title = { Text(stringRes(R.string.resource_usage_alert_title)) }, title = { Text(stringRes(Res.string.resource_usage_alert_title)) },
text = { text = {
Text( Text(
stringRes( stringRes(
@@ -119,10 +124,10 @@ fun DisplayResourceUsageAlert(
} }
dismiss() dismiss()
}) { }) {
Text(stringRes(R.string.resource_usage_alert_opt_out)) Text(stringRes(Res.string.resource_usage_alert_opt_out))
} }
TextButton(onClick = dismiss) { TextButton(onClick = dismiss) {
Text(stringRes(R.string.resource_usage_alert_not_now)) Text(stringRes(Res.string.resource_usage_alert_not_now))
} }
} }
}, },
@@ -146,7 +151,7 @@ fun DisplayResourceUsageAlert(
} }
dismiss() dismiss()
}) { }) {
Text(stringRes(R.string.resource_usage_alert_send)) Text(stringRes(Res.string.resource_usage_alert_send))
} }
}, },
) )
@@ -72,6 +72,11 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_bitcoin_invoice
import com.vitorpamplona.amethyst.commons.resources.cancel_bitcoin_invoice
import com.vitorpamplona.amethyst.commons.resources.lightning_create_and_add_invoice
import com.vitorpamplona.amethyst.commons.resources.lightning_invoice
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
import com.vitorpamplona.amethyst.service.playback.composable.VideoView import com.vitorpamplona.amethyst.service.playback.composable.VideoView
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
@@ -297,8 +302,8 @@ fun EditPostView(
lud16, lud16,
user, user,
accountViewModel, accountViewModel,
stringRes(id = R.string.lightning_invoice), stringRes(id = Res.string.lightning_invoice),
stringRes(id = R.string.lightning_create_and_add_invoice), stringRes(id = Res.string.lightning_create_and_add_invoice),
onNewInvoice = { onNewInvoice = {
postViewModel.message.setTextAndPlaceCursorAtEnd( postViewModel.message.setTextAndPlaceCursorAtEnd(
postViewModel.message.text.toString() + "\n\n" + it, postViewModel.message.text.toString() + "\n\n" + it,
@@ -428,14 +433,14 @@ private fun AddLnInvoiceButton(
if (!isLnInvoiceActive) { if (!isLnInvoiceActive) {
Icon( Icon(
symbol = MaterialSymbols.CurrencyBitcoin, symbol = MaterialSymbols.CurrencyBitcoin,
contentDescription = stringRes(id = R.string.add_bitcoin_invoice), contentDescription = stringRes(id = Res.string.add_bitcoin_invoice),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.CurrencyBitcoin, symbol = MaterialSymbols.CurrencyBitcoin,
contentDescription = stringRes(id = R.string.cancel_bitcoin_invoice), contentDescription = stringRes(id = Res.string.cancel_bitcoin_invoice),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = BitcoinOrange, tint = BitcoinOrange,
) )
@@ -40,9 +40,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.LocalClipboard
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.copy_stack_to_clipboard
import com.vitorpamplona.amethyst.commons.resources.error_dialog_button_ok
import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg
import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg2 import com.vitorpamplona.amethyst.ui.components.toasts.ThrowableToastMsg2
import com.vitorpamplona.amethyst.ui.components.util.setText import com.vitorpamplona.amethyst.ui.components.util.setText
@@ -127,7 +129,7 @@ fun InformationDialog(
clipboardManager.setText(it) clipboardManager.setText(it)
} }
}) { }) {
Text(stringRes(R.string.copy_stack_to_clipboard)) Text(stringRes(Res.string.copy_stack_to_clipboard))
} }
} }
@@ -144,7 +146,7 @@ fun InformationDialog(
contentDescription = null, contentDescription = null,
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_button_ok)) Text(stringRes(Res.string.error_dialog_button_ok))
} }
} }
} }
@@ -54,6 +54,15 @@ import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.VideoPostKind import com.vitorpamplona.amethyst.commons.model.VideoPostKind
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_caption
import com.vitorpamplona.amethyst.commons.resources.add_caption_example
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_explainer
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_high
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_label
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_low
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_medium
import com.vitorpamplona.amethyst.commons.resources.media_compression_quality_uncompressed
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
@@ -172,7 +181,7 @@ fun ImageVideoPost(
} }
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.add_caption)) }, label = { Text(text = stringRes(Res.string.add_caption)) },
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -183,7 +192,7 @@ fun ImageVideoPost(
onValueChange = { postViewModel.caption = it }, onValueChange = { postViewModel.caption = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.add_caption_example), text = stringRes(Res.string.add_caption_example),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -226,12 +235,12 @@ fun ImageVideoPost(
verticalArrangement = Arrangement.spacedBy(Size5dp), verticalArrangement = Arrangement.spacedBy(Size5dp),
) { ) {
Text( Text(
text = stringRes(R.string.media_compression_quality_label), text = stringRes(Res.string.media_compression_quality_label),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
Text( Text(
text = stringRes(R.string.media_compression_quality_explainer), text = stringRes(Res.string.media_compression_quality_explainer),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = Color.Gray, color = Color.Gray,
maxLines = 5, maxLines = 5,
@@ -244,11 +253,11 @@ fun ImageVideoPost(
Text( Text(
text = text =
when (postViewModel.mediaQualitySlider) { when (postViewModel.mediaQualitySlider) {
0 -> stringRes(R.string.media_compression_quality_low) 0 -> stringRes(Res.string.media_compression_quality_low)
1 -> stringRes(R.string.media_compression_quality_medium) 1 -> stringRes(Res.string.media_compression_quality_medium)
2 -> stringRes(R.string.media_compression_quality_high) 2 -> stringRes(Res.string.media_compression_quality_high)
3 -> stringRes(R.string.media_compression_quality_uncompressed) 3 -> stringRes(Res.string.media_compression_quality_uncompressed)
else -> stringRes(R.string.media_compression_quality_medium) else -> stringRes(Res.string.media_compression_quality_medium)
}, },
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
) )
@@ -54,6 +54,24 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.about_me
import com.vitorpamplona.amethyst.commons.resources.avatar_url
import com.vitorpamplona.amethyst.commons.resources.banner_url
import com.vitorpamplona.amethyst.commons.resources.clink_offer_label
import com.vitorpamplona.amethyst.commons.resources.display_name
import com.vitorpamplona.amethyst.commons.resources.github_proof_url_template
import com.vitorpamplona.amethyst.commons.resources.lightning_address
import com.vitorpamplona.amethyst.commons.resources.lnurl
import com.vitorpamplona.amethyst.commons.resources.mastodon_proof_url_template
import com.vitorpamplona.amethyst.commons.resources.my_display_name
import com.vitorpamplona.amethyst.commons.resources.my_name
import com.vitorpamplona.amethyst.commons.resources.nip_05
import com.vitorpamplona.amethyst.commons.resources.pronouns
import com.vitorpamplona.amethyst.commons.resources.social_proof
import com.vitorpamplona.amethyst.commons.resources.twitter_proof_url_template
import com.vitorpamplona.amethyst.commons.resources.username
import com.vitorpamplona.amethyst.commons.resources.website_url
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectSingleFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectSingleFromGallery
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -115,13 +133,13 @@ fun NewUserMetadataScreen(
) { ) {
// -- Profile (always visible) -- // -- Profile (always visible) --
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.username)) }, label = { Text(text = stringRes(Res.string.username)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.name.value, value = postViewModel.name.value,
onValueChange = { postViewModel.name.value = it }, onValueChange = { postViewModel.name.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.my_name), text = stringRes(Res.string.my_name),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -136,13 +154,13 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.display_name)) }, label = { Text(text = stringRes(Res.string.display_name)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.displayName.value, value = postViewModel.displayName.value,
onValueChange = { postViewModel.displayName.value = it }, onValueChange = { postViewModel.displayName.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.my_display_name), text = stringRes(Res.string.my_display_name),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -156,13 +174,13 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.about_me)) }, label = { Text(text = stringRes(Res.string.about_me)) },
modifier = Modifier.fillMaxWidth().height(100.dp), modifier = Modifier.fillMaxWidth().height(100.dp),
value = postViewModel.about.value, value = postViewModel.about.value,
onValueChange = { postViewModel.about.value = it }, onValueChange = { postViewModel.about.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(id = R.string.about_me), text = stringRes(id = Res.string.about_me),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -176,7 +194,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.avatar_url)) }, label = { Text(text = stringRes(Res.string.avatar_url)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.picture.value, value = postViewModel.picture.value,
onValueChange = { postViewModel.picture.value = it }, onValueChange = { postViewModel.picture.value = it },
@@ -201,7 +219,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.banner_url)) }, label = { Text(text = stringRes(Res.string.banner_url)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.banner.value, value = postViewModel.banner.value,
onValueChange = { postViewModel.banner.value = it }, onValueChange = { postViewModel.banner.value = it },
@@ -226,7 +244,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.nip_05) + " (NIP-05)") }, label = { Text(text = stringRes(Res.string.nip_05) + " (NIP-05)") },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.nip05.value, value = postViewModel.nip05.value,
onValueChange = { postViewModel.nip05.value = it }, onValueChange = { postViewModel.nip05.value = it },
@@ -242,7 +260,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.website_url)) }, label = { Text(text = stringRes(Res.string.website_url)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.website.value, value = postViewModel.website.value,
onValueChange = { postViewModel.website.value = it }, onValueChange = { postViewModel.website.value = it },
@@ -258,7 +276,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.pronouns)) }, label = { Text(text = stringRes(Res.string.pronouns)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.pronouns.value, value = postViewModel.pronouns.value,
onValueChange = { postViewModel.pronouns.value = it }, onValueChange = { postViewModel.pronouns.value = it },
@@ -274,7 +292,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.lightning_address)) }, label = { Text(text = stringRes(Res.string.lightning_address)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.lnAddress.value, value = postViewModel.lnAddress.value,
onValueChange = { postViewModel.lnAddress.value = it }, onValueChange = { postViewModel.lnAddress.value = it },
@@ -290,7 +308,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.lnurl)) }, label = { Text(text = stringRes(Res.string.lnurl)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.lnURL.value, value = postViewModel.lnURL.value,
onValueChange = { postViewModel.lnURL.value = it }, onValueChange = { postViewModel.lnURL.value = it },
@@ -306,7 +324,7 @@ fun NewUserMetadataScreen(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.clink_offer_label)) }, label = { Text(text = stringRes(Res.string.clink_offer_label)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = postViewModel.clinkOffer.value, value = postViewModel.clinkOffer.value,
onValueChange = { postViewModel.clinkOffer.value = it }, onValueChange = { postViewModel.clinkOffer.value = it },
@@ -321,7 +339,7 @@ fun NewUserMetadataScreen(
// -- Social Proofs -- // -- Social Proofs --
ExpandableSection( ExpandableSection(
title = stringRes(R.string.social_proof), title = stringRes(Res.string.social_proof),
expanded = socialExpanded, expanded = socialExpanded,
) { ) {
OutlinedTextField( OutlinedTextField(
@@ -331,7 +349,7 @@ fun NewUserMetadataScreen(
onValueChange = { postViewModel.twitter.value = it }, onValueChange = { postViewModel.twitter.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.twitter_proof_url_template), text = stringRes(Res.string.twitter_proof_url_template),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -346,7 +364,7 @@ fun NewUserMetadataScreen(
onValueChange = { postViewModel.mastodon.value = it }, onValueChange = { postViewModel.mastodon.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.mastodon_proof_url_template), text = stringRes(Res.string.mastodon_proof_url_template),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -361,7 +379,7 @@ fun NewUserMetadataScreen(
onValueChange = { postViewModel.github.value = it }, onValueChange = { postViewModel.github.value = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.github_proof_url_template), text = stringRes(Res.string.github_proof_url_template),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -25,6 +25,9 @@ import androidx.compose.material3.Button
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.metadata_strip_failed_body
import com.vitorpamplona.amethyst.commons.resources.metadata_strip_failed_upload
import com.vitorpamplona.amethyst.service.uploads.ConfirmationCallbacks import com.vitorpamplona.amethyst.service.uploads.ConfirmationCallbacks
import com.vitorpamplona.amethyst.service.uploads.SuspendableConfirmation import com.vitorpamplona.amethyst.service.uploads.SuspendableConfirmation
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -40,10 +43,10 @@ fun StrippingFailureDialog(dialogState: ConfirmationCallbacks) {
AlertDialog( AlertDialog(
onDismissRequest = { dialogState.onCancel() }, onDismissRequest = { dialogState.onCancel() },
title = { Text(stringRes(R.string.metadata_strip_failed_title)) }, title = { Text(stringRes(R.string.metadata_strip_failed_title)) },
text = { Text(stringRes(R.string.metadata_strip_failed_body)) }, text = { Text(stringRes(Res.string.metadata_strip_failed_body)) },
confirmButton = { confirmButton = {
Button(onClick = { dialogState.onConfirm() }) { Button(onClick = { dialogState.onConfirm() }) {
Text(stringRes(R.string.metadata_strip_failed_upload)) Text(stringRes(Res.string.metadata_strip_failed_upload))
} }
}, },
dismissButton = { dismissButton = {
@@ -55,6 +55,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.bolt12_offer
import com.vitorpamplona.amethyst.commons.resources.bolt12_offers_explainer
import com.vitorpamplona.amethyst.commons.resources.delete_bolt12_offer
import com.vitorpamplona.amethyst.commons.resources.invalid_bolt12_offer
import com.vitorpamplona.amethyst.commons.resources.no_bolt12_offers_message
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
@@ -122,7 +128,7 @@ fun Bolt12OffersScaffold(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Text( Text(
text = stringRes(id = R.string.bolt12_offers_explainer), text = stringRes(id = Res.string.bolt12_offers_explainer),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 10.dp), modifier = Modifier.padding(top = 10.dp),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
@@ -154,7 +160,7 @@ fun Bolt12OffersBody(viewModel: Bolt12OffersViewModel) {
if (offers.isEmpty()) { if (offers.isEmpty()) {
item { item {
Text( Text(
text = stringRes(id = R.string.no_bolt12_offers_message), text = stringRes(id = Res.string.no_bolt12_offers_message),
modifier = Modifier.padding(vertical = 16.dp), modifier = Modifier.padding(vertical = 16.dp),
) )
} }
@@ -195,7 +201,7 @@ fun Bolt12OfferEntry(
IconButton(onClick = onDelete) { IconButton(onClick = onDelete) {
Icon( Icon(
symbol = MaterialSymbols.Delete, symbol = MaterialSymbols.Delete,
contentDescription = stringRes(id = R.string.delete_bolt12_offer), contentDescription = stringRes(id = Res.string.delete_bolt12_offer),
) )
} }
} }
@@ -208,7 +214,7 @@ fun Bolt12OfferAddField(onAdd: (raw: String) -> Boolean) {
Column(verticalArrangement = Arrangement.spacedBy(Size10dp)) { Column(verticalArrangement = Arrangement.spacedBy(Size10dp)) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.bolt12_offer)) }, label = { Text(text = stringRes(Res.string.bolt12_offer)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = offer, value = offer,
onValueChange = { onValueChange = {
@@ -218,7 +224,7 @@ fun Bolt12OfferAddField(onAdd: (raw: String) -> Boolean) {
isError = isError, isError = isError,
supportingText = supportingText =
if (isError) { if (isError) {
{ Text(text = stringRes(R.string.invalid_bolt12_offer)) } { Text(text = stringRes(Res.string.invalid_bolt12_offer)) }
} else { } else {
null null
}, },
@@ -62,6 +62,25 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_media_server
import com.vitorpamplona.amethyst.commons.resources.blossom_mirror_uploads
import com.vitorpamplona.amethyst.commons.resources.blossom_mirror_uploads_caption
import com.vitorpamplona.amethyst.commons.resources.blossom_optimize_media
import com.vitorpamplona.amethyst.commons.resources.blossom_optimize_media_caption
import com.vitorpamplona.amethyst.commons.resources.delete_media_server
import com.vitorpamplona.amethyst.commons.resources.media_server_added
import com.vitorpamplona.amethyst.commons.resources.media_server_primary_badge
import com.vitorpamplona.amethyst.commons.resources.media_server_reorder
import com.vitorpamplona.amethyst.commons.resources.media_servers_add_section
import com.vitorpamplona.amethyst.commons.resources.media_servers_add_url_label
import com.vitorpamplona.amethyst.commons.resources.media_servers_cache_section
import com.vitorpamplona.amethyst.commons.resources.media_servers_priority_section
import com.vitorpamplona.amethyst.commons.resources.media_servers_recommended_label
import com.vitorpamplona.amethyst.commons.resources.media_servers_reorder_hint
import com.vitorpamplona.amethyst.commons.resources.media_servers_upload_section
import com.vitorpamplona.amethyst.commons.resources.no_blossom_server_message
import com.vitorpamplona.amethyst.commons.resources.use_default_servers
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -119,8 +138,8 @@ fun AllMediaBody(
) { ) {
item { item {
SectionLabel( SectionLabel(
title = stringRes(id = R.string.media_servers_priority_section), title = stringRes(id = Res.string.media_servers_priority_section),
caption = stringRes(id = R.string.media_servers_reorder_hint), caption = stringRes(id = Res.string.media_servers_reorder_hint),
topPadding = 4.dp, topPadding = 4.dp,
) )
} }
@@ -128,7 +147,7 @@ fun AllMediaBody(
if (blossomServersState.isEmpty()) { if (blossomServersState.isEmpty()) {
item { item {
Text( Text(
text = stringRes(id = R.string.no_blossom_server_message), text = stringRes(id = Res.string.no_blossom_server_message),
modifier = DoubleVertPadding, modifier = DoubleVertPadding,
) )
} }
@@ -162,12 +181,12 @@ fun AllMediaBody(
} }
item { item {
SectionLabel(title = stringRes(id = R.string.media_servers_upload_section)) SectionLabel(title = stringRes(id = Res.string.media_servers_upload_section))
UploadBehaviorSection(accountViewModel, nav) UploadBehaviorSection(accountViewModel, nav)
} }
item { item {
SectionLabel(title = stringRes(id = R.string.media_servers_cache_section)) SectionLabel(title = stringRes(id = Res.string.media_servers_cache_section))
MediaCacheSection(accountViewModel) MediaCacheSection(accountViewModel)
} }
@@ -199,8 +218,8 @@ private fun UploadBehaviorSection(
.background(MaterialTheme.colorScheme.surfaceContainer), .background(MaterialTheme.colorScheme.surfaceContainer),
) { ) {
UploadToggleRow( UploadToggleRow(
title = stringRes(id = R.string.blossom_mirror_uploads), title = stringRes(id = Res.string.blossom_mirror_uploads),
caption = stringRes(id = R.string.blossom_mirror_uploads_caption), caption = stringRes(id = Res.string.blossom_mirror_uploads_caption),
checked = mirror, checked = mirror,
onCheckedChange = { accountViewModel.account.settings.changeMirrorUploadsToAllServers(it) }, onCheckedChange = { accountViewModel.account.settings.changeMirrorUploadsToAllServers(it) },
) )
@@ -211,8 +230,8 @@ private fun UploadBehaviorSection(
) )
UploadToggleRow( UploadToggleRow(
title = stringRes(id = R.string.blossom_optimize_media), title = stringRes(id = Res.string.blossom_optimize_media),
caption = stringRes(id = R.string.blossom_optimize_media_caption), caption = stringRes(id = Res.string.blossom_optimize_media_caption),
checked = optimize, checked = optimize,
onCheckedChange = { accountViewModel.account.settings.changeOptimizeMediaOnUpload(it) }, onCheckedChange = { accountViewModel.account.settings.changeOptimizeMediaOnUpload(it) },
) )
@@ -331,7 +350,7 @@ fun MediaServerRow(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.DragIndicator, symbol = MaterialSymbols.DragIndicator,
contentDescription = stringRes(id = R.string.media_server_reorder), contentDescription = stringRes(id = Res.string.media_server_reorder),
modifier = Modifier.size(22.dp).relayDragHandle(index, dragState), modifier = Modifier.size(22.dp).relayDragHandle(index, dragState),
tint = MaterialTheme.colorScheme.grayText, tint = MaterialTheme.colorScheme.grayText,
) )
@@ -370,7 +389,7 @@ fun MediaServerRow(
IconButton(onClick = { onDelete(serverEntry.baseUrl) }) { IconButton(onClick = { onDelete(serverEntry.baseUrl) }) {
Icon( Icon(
symbol = MaterialSymbols.Delete, symbol = MaterialSymbols.Delete,
contentDescription = stringRes(id = R.string.delete_media_server), contentDescription = stringRes(id = Res.string.delete_media_server),
tint = MaterialTheme.colorScheme.grayText, tint = MaterialTheme.colorScheme.grayText,
) )
} }
@@ -387,7 +406,7 @@ private fun AddServerSection(
onAddServer: (String) -> Unit, onAddServer: (String) -> Unit,
onAddAll: () -> Unit, onAddAll: () -> Unit,
) { ) {
SectionLabel(title = stringRes(id = R.string.media_servers_add_section)) SectionLabel(title = stringRes(id = Res.string.media_servers_add_section))
// Recommended servers first — one tap adds a known-good host. // Recommended servers first — one tap adds a known-good host.
Row( Row(
@@ -395,13 +414,13 @@ private fun AddServerSection(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = stringRes(id = R.string.media_servers_recommended_label), text = stringRes(id = Res.string.media_servers_recommended_label),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) )
TextButton(onClick = onAddAll) { TextButton(onClick = onAddAll) {
Text(text = stringRes(id = R.string.use_default_servers)) Text(text = stringRes(id = Res.string.use_default_servers))
} }
} }
@@ -425,7 +444,7 @@ private fun AddServerSection(
// ...or paste any server address. // ...or paste any server address.
Text( Text(
text = stringRes(id = R.string.media_servers_add_url_label), text = stringRes(id = Res.string.media_servers_add_url_label),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(top = 16.dp, bottom = 8.dp), modifier = Modifier.padding(top = 16.dp, bottom = 8.dp),
@@ -466,9 +485,9 @@ private fun RecommendedChip(
symbol = if (added) MaterialSymbols.CheckCircle else MaterialSymbols.Add, symbol = if (added) MaterialSymbols.CheckCircle else MaterialSymbols.Add,
contentDescription = contentDescription =
if (added) { if (added) {
stringRes(id = R.string.media_server_added) stringRes(id = Res.string.media_server_added)
} else { } else {
stringRes(id = R.string.add_media_server) stringRes(id = Res.string.add_media_server)
}, },
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
tint = if (added) MaterialTheme.colorScheme.grayText else MaterialTheme.colorScheme.primary, tint = if (added) MaterialTheme.colorScheme.grayText else MaterialTheme.colorScheme.primary,
@@ -565,7 +584,7 @@ private fun PrimaryBadge() {
.padding(horizontal = 6.dp, vertical = 1.dp), .padding(horizontal = 6.dp, vertical = 1.dp),
) { ) {
Text( Text(
text = stringRes(id = R.string.media_server_primary_badge), text = stringRes(id = Res.string.media_server_primary_badge),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onPrimaryContainer, color = MaterialTheme.colorScheme.onPrimaryContainer,
@@ -50,6 +50,13 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.local_blossom_cache_detected
import com.vitorpamplona.amethyst.commons.resources.local_blossom_cache_not_detected
import com.vitorpamplona.amethyst.commons.resources.local_blossom_cache_profile_pics_only
import com.vitorpamplona.amethyst.commons.resources.local_blossom_cache_profile_pics_only_caption
import com.vitorpamplona.amethyst.commons.resources.use_local_blossom_cache
import com.vitorpamplona.amethyst.commons.resources.use_local_blossom_cache_caption
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -147,11 +154,11 @@ fun MediaCacheSection(accountViewModel: AccountViewModel) {
} }
Column(modifier = Modifier.weight(1f).padding(start = 14.dp, end = 12.dp)) { Column(modifier = Modifier.weight(1f).padding(start = 14.dp, end = 12.dp)) {
Text( Text(
text = stringRes(id = R.string.use_local_blossom_cache), text = stringRes(id = Res.string.use_local_blossom_cache),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
) )
Text( Text(
text = stringRes(id = R.string.use_local_blossom_cache_caption), text = stringRes(id = Res.string.use_local_blossom_cache_caption),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -179,11 +186,11 @@ fun MediaCacheSection(accountViewModel: AccountViewModel) {
) { ) {
Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) { Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) {
Text( Text(
text = stringRes(id = R.string.local_blossom_cache_profile_pics_only), text = stringRes(id = Res.string.local_blossom_cache_profile_pics_only),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
Text( Text(
text = stringRes(id = R.string.local_blossom_cache_profile_pics_only_caption), text = stringRes(id = Res.string.local_blossom_cache_profile_pics_only_caption),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -225,9 +232,9 @@ private fun CacheDetectionChip(accountViewModel: AccountViewModel) {
Text( Text(
text = text =
if (probeAvailable) { if (probeAvailable) {
stringRes(id = R.string.local_blossom_cache_detected) stringRes(id = Res.string.local_blossom_cache_detected)
} else { } else {
stringRes(id = R.string.local_blossom_cache_not_detected) stringRes(id = Res.string.local_blossom_cache_not_detected)
}, },
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = color, color = color,
@@ -100,6 +100,27 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.blossom_delete_from_host
import com.vitorpamplona.amethyst.commons.resources.blossom_file_details
import com.vitorpamplona.amethyst.commons.resources.blossom_import_menu
import com.vitorpamplona.amethyst.commons.resources.blossom_mirror_to_missing
import com.vitorpamplona.amethyst.commons.resources.blossom_more_actions
import com.vitorpamplona.amethyst.commons.resources.blossom_open
import com.vitorpamplona.amethyst.commons.resources.blossom_pay
import com.vitorpamplona.amethyst.commons.resources.blossom_payment_message
import com.vitorpamplona.amethyst.commons.resources.blossom_payment_server_says
import com.vitorpamplona.amethyst.commons.resources.blossom_payment_title
import com.vitorpamplona.amethyst.commons.resources.blossom_refresh
import com.vitorpamplona.amethyst.commons.resources.blossom_report
import com.vitorpamplona.amethyst.commons.resources.blossom_report_comment_hint
import com.vitorpamplona.amethyst.commons.resources.blossom_report_title
import com.vitorpamplona.amethyst.commons.resources.blossom_send
import com.vitorpamplona.amethyst.commons.resources.blossom_stored_on
import com.vitorpamplona.amethyst.commons.resources.blossom_sync_all
import com.vitorpamplona.amethyst.commons.resources.blossom_sync_gaps
import com.vitorpamplona.amethyst.commons.resources.copy
import com.vitorpamplona.amethyst.commons.resources.manage_stored_files_empty
import com.vitorpamplona.amethyst.service.playback.composable.VideoViewInner import com.vitorpamplona.amethyst.service.playback.composable.VideoViewInner
import com.vitorpamplona.amethyst.ui.components.util.setText import com.vitorpamplona.amethyst.ui.components.util.setText
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -220,7 +241,7 @@ fun BlossomBlobManagerScreen(
StatusGlyph(MaterialSymbols.Storage, MaterialTheme.colorScheme.grayText) StatusGlyph(MaterialSymbols.Storage, MaterialTheme.colorScheme.grayText)
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
Text( Text(
stringRes(R.string.manage_stored_files_empty), stringRes(Res.string.manage_stored_files_empty),
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
} }
@@ -259,11 +280,11 @@ private fun BlobManagerOverflowMenu(
var open by remember { mutableStateOf(false) } var open by remember { mutableStateOf(false) }
Box { Box {
IconButton(onClick = { open = true }) { IconButton(onClick = { open = true }) {
Icon(symbol = MaterialSymbols.MoreVert, contentDescription = stringRes(R.string.blossom_more_actions)) Icon(symbol = MaterialSymbols.MoreVert, contentDescription = stringRes(Res.string.blossom_more_actions))
} }
DropdownMenu(expanded = open, onDismissRequest = { open = false }) { DropdownMenu(expanded = open, onDismissRequest = { open = false }) {
DropdownMenuItem( DropdownMenuItem(
text = { Text(stringRes(R.string.blossom_refresh)) }, text = { Text(stringRes(Res.string.blossom_refresh)) },
leadingIcon = { OverflowMenuIcon(MaterialSymbols.Sync) }, leadingIcon = { OverflowMenuIcon(MaterialSymbols.Sync) },
onClick = { onClick = {
open = false open = false
@@ -271,7 +292,7 @@ private fun BlobManagerOverflowMenu(
}, },
) )
DropdownMenuItem( DropdownMenuItem(
text = { Text(stringRes(R.string.blossom_import_menu)) }, text = { Text(stringRes(Res.string.blossom_import_menu)) },
leadingIcon = { OverflowMenuIcon(MaterialSymbols.CloudDownload) }, leadingIcon = { OverflowMenuIcon(MaterialSymbols.CloudDownload) },
onClick = { onClick = {
open = false open = false
@@ -334,12 +355,12 @@ private fun SyncAllBanner(onSyncAll: () -> Unit) {
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) { Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) {
Text(stringRes(R.string.blossom_sync_gaps), style = MaterialTheme.typography.bodyMedium) Text(stringRes(Res.string.blossom_sync_gaps), style = MaterialTheme.typography.bodyMedium)
} }
FilledTonalButton(onClick = onSyncAll) { FilledTonalButton(onClick = onSyncAll) {
Icon(symbol = MaterialSymbols.CloudUpload, contentDescription = null, modifier = Modifier.size(18.dp)) Icon(symbol = MaterialSymbols.CloudUpload, contentDescription = null, modifier = Modifier.size(18.dp))
Spacer(Modifier.size(8.dp)) Spacer(Modifier.size(8.dp))
Text(stringRes(R.string.blossom_sync_all)) Text(stringRes(Res.string.blossom_sync_all))
} }
} }
} }
@@ -540,7 +561,7 @@ private fun BlossomBlobViewer(
shareUrl(context, url) shareUrl(context, url)
} }
} }
ViewerIconButton(MaterialSymbols.Info, stringRes(R.string.blossom_file_details)) { ViewerIconButton(MaterialSymbols.Info, stringRes(Res.string.blossom_file_details)) {
drawerOpen = true drawerOpen = true
} }
} }
@@ -660,7 +681,7 @@ private fun BlobActionsContent(
// Where the file lives. // Where the file lives.
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
Text( Text(
text = stringRes(R.string.blossom_stored_on), text = stringRes(Res.string.blossom_stored_on),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -680,33 +701,33 @@ private fun BlobActionsContent(
) { ) {
Icon(symbol = MaterialSymbols.CloudUpload, contentDescription = null, modifier = Modifier.size(18.dp)) Icon(symbol = MaterialSymbols.CloudUpload, contentDescription = null, modifier = Modifier.size(18.dp))
Spacer(Modifier.size(8.dp)) Spacer(Modifier.size(8.dp))
Text(stringRes(R.string.blossom_mirror_to_missing)) Text(stringRes(Res.string.blossom_mirror_to_missing))
} }
} }
// Secondary actions. // Secondary actions.
if (row.url != null) { if (row.url != null) {
val url = row.url val url = row.url
DetailAction(MaterialSymbols.ContentCopy, stringRes(R.string.copy)) { DetailAction(MaterialSymbols.ContentCopy, stringRes(Res.string.copy)) {
scope.launch { clipboard.setText(url) } scope.launch { clipboard.setText(url) }
} }
DetailAction(MaterialSymbols.Share, stringRes(R.string.quick_action_share)) { DetailAction(MaterialSymbols.Share, stringRes(R.string.quick_action_share)) {
shareUrl(context, url) shareUrl(context, url)
} }
DetailAction(MaterialSymbols.AutoMirrored.OpenInNew, stringRes(R.string.blossom_open)) { DetailAction(MaterialSymbols.AutoMirrored.OpenInNew, stringRes(Res.string.blossom_open)) {
runCatching { context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri())) } runCatching { context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri())) }
} }
} }
if (row.hasPresent) { if (row.hasPresent) {
DetailAction(MaterialSymbols.Report, stringRes(R.string.blossom_report)) { reportOpen = true } DetailAction(MaterialSymbols.Report, stringRes(Res.string.blossom_report)) { reportOpen = true }
HorizontalDivider() HorizontalDivider()
row.presentServers.forEach { server -> row.presentServers.forEach { server ->
DetailAction( DetailAction(
symbol = MaterialSymbols.Delete, symbol = MaterialSymbols.Delete,
label = stringRes(R.string.blossom_delete_from_host, vm.hostOf(server)), label = stringRes(Res.string.blossom_delete_from_host, vm.hostOf(server)),
tint = MaterialTheme.colorScheme.error, tint = MaterialTheme.colorScheme.error,
) { vm.delete(row.hash, server) } ) { vm.delete(row.hash, server) }
} }
@@ -807,17 +828,17 @@ private fun BlossomPaymentDialog(
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
icon = { Icon(symbol = MaterialSymbols.Bolt, contentDescription = null, tint = MaterialTheme.colorScheme.allGoodColor) }, icon = { Icon(symbol = MaterialSymbols.Bolt, contentDescription = null, tint = MaterialTheme.colorScheme.allGoodColor) },
title = { Text(stringRes(R.string.blossom_payment_title)) }, title = { Text(stringRes(Res.string.blossom_payment_title)) },
text = { text = {
Column { Column {
Text(text = stringRes(R.string.blossom_payment_message, host)) Text(text = stringRes(Res.string.blossom_payment_message, host))
// X-Reason is server-controlled: it is sanitized upstream and rendered // X-Reason is server-controlled: it is sanitized upstream and rendered
// here attributed to the server, in a dimmer italic, so it can never be // here attributed to the server, in a dimmer italic, so it can never be
// mistaken for Amethyst's own wording (e.g. a fake "Pay 1 sat"). // mistaken for Amethyst's own wording (e.g. a fake "Pay 1 sat").
reason?.let { reason?.let {
Spacer(Modifier.size(12.dp)) Spacer(Modifier.size(12.dp))
Text( Text(
text = stringRes(R.string.blossom_payment_server_says, host, it), text = stringRes(Res.string.blossom_payment_server_says, host, it),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
fontStyle = FontStyle.Italic, fontStyle = FontStyle.Italic,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
@@ -833,7 +854,7 @@ private fun BlossomPaymentDialog(
if (amountSats != null) { if (amountSats != null) {
pluralStringResource(R.plurals.blossom_pay_sats, amountSats.toInt(), amountSats.toInt()) pluralStringResource(R.plurals.blossom_pay_sats, amountSats.toInt(), amountSats.toInt())
} else { } else {
stringRes(R.string.blossom_pay) stringRes(Res.string.blossom_pay)
}, },
) )
} }
@@ -859,7 +880,7 @@ private fun BlossomReportDialog(
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
icon = { Icon(symbol = MaterialSymbols.Report, contentDescription = null) }, icon = { Icon(symbol = MaterialSymbols.Report, contentDescription = null) },
title = { Text(stringRes(R.string.blossom_report_title)) }, title = { Text(stringRes(Res.string.blossom_report_title)) },
text = { text = {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
Box { Box {
@@ -881,7 +902,7 @@ private fun BlossomReportDialog(
OutlinedTextField( OutlinedTextField(
value = comment, value = comment,
onValueChange = { comment = it }, onValueChange = { comment = it },
label = { Text(stringRes(R.string.blossom_report_comment_hint)) }, label = { Text(stringRes(Res.string.blossom_report_comment_hint)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) )
} }
@@ -890,7 +911,7 @@ private fun BlossomReportDialog(
FilledTonalButton(onClick = { FilledTonalButton(onClick = {
vm.report(row.hash, server, type, comment) vm.report(row.hash, server, type, comment)
onDismiss() onDismiss()
}) { Text(stringRes(R.string.blossom_send)) } }) { Text(stringRes(Res.string.blossom_send)) }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = onDismiss) { Text(stringRes(R.string.cancel)) } TextButton(onClick = onDismiss) { Text(stringRes(R.string.cancel)) }
@@ -64,6 +64,18 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.blossom_import_add_url_label
import com.vitorpamplona.amethyst.commons.resources.blossom_import_intro
import com.vitorpamplona.amethyst.commons.resources.blossom_import_manage_servers
import com.vitorpamplona.amethyst.commons.resources.blossom_import_no_targets
import com.vitorpamplona.amethyst.commons.resources.blossom_import_none_found
import com.vitorpamplona.amethyst.commons.resources.blossom_import_scan
import com.vitorpamplona.amethyst.commons.resources.blossom_import_scanning
import com.vitorpamplona.amethyst.commons.resources.blossom_import_source_failed
import com.vitorpamplona.amethyst.commons.resources.blossom_import_sources_section
import com.vitorpamplona.amethyst.commons.resources.blossom_import_title
import com.vitorpamplona.amethyst.commons.resources.delete_media_server
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -108,7 +120,7 @@ fun BlossomImportScreen(
Scaffold( Scaffold(
topBar = { topBar = {
TopBarWithBackButton( TopBarWithBackButton(
caption = stringRes(R.string.blossom_import_title), caption = stringRes(Res.string.blossom_import_title),
nav = nav, nav = nav,
) )
}, },
@@ -140,7 +152,7 @@ fun BlossomImportScreen(
) { ) {
item { item {
Text( Text(
text = stringRes(R.string.blossom_import_intro), text = stringRes(Res.string.blossom_import_intro),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -152,7 +164,7 @@ fun BlossomImportScreen(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = stringRes(R.string.blossom_import_sources_section), text = stringRes(Res.string.blossom_import_sources_section),
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
@@ -179,7 +191,7 @@ fun BlossomImportScreen(
item { item {
Text( Text(
text = stringRes(R.string.blossom_import_add_url_label), text = stringRes(Res.string.blossom_import_add_url_label),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), modifier = Modifier.padding(top = 8.dp, bottom = 4.dp),
@@ -197,11 +209,11 @@ fun BlossomImportScreen(
if (scanning) { if (scanning) {
CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp) CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
Spacer(Modifier.size(8.dp)) Spacer(Modifier.size(8.dp))
Text(stringRes(R.string.blossom_import_scanning)) Text(stringRes(Res.string.blossom_import_scanning))
} else { } else {
Icon(symbol = MaterialSymbols.CloudSync, contentDescription = null, modifier = Modifier.size(18.dp)) Icon(symbol = MaterialSymbols.CloudSync, contentDescription = null, modifier = Modifier.size(18.dp))
Spacer(Modifier.size(8.dp)) Spacer(Modifier.size(8.dp))
Text(stringRes(R.string.blossom_import_scan)) Text(stringRes(Res.string.blossom_import_scan))
} }
} }
} }
@@ -220,7 +232,7 @@ fun BlossomImportScreen(
if (candidates.isEmpty()) { if (candidates.isEmpty()) {
item { item {
Text( Text(
text = stringRes(R.string.blossom_import_none_found), text = stringRes(Res.string.blossom_import_none_found),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
modifier = Modifier.padding(top = 8.dp), modifier = Modifier.padding(top = 8.dp),
@@ -275,13 +287,13 @@ private fun NoTargetsState(
} }
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
Text( Text(
text = stringRes(R.string.blossom_import_no_targets), text = stringRes(Res.string.blossom_import_no_targets),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
OutlinedButton(onClick = onManageServers) { OutlinedButton(onClick = onManageServers) {
Text(stringRes(R.string.blossom_import_manage_servers)) Text(stringRes(Res.string.blossom_import_manage_servers))
} }
} }
} }
@@ -318,7 +330,7 @@ private fun ImportSourceRow(
IconButton(onClick = onRemove) { IconButton(onClick = onRemove) {
Icon( Icon(
symbol = MaterialSymbols.Delete, symbol = MaterialSymbols.Delete,
contentDescription = stringRes(R.string.delete_media_server), contentDescription = stringRes(Res.string.delete_media_server),
tint = MaterialTheme.colorScheme.grayText, tint = MaterialTheme.colorScheme.grayText,
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
) )
@@ -347,7 +359,7 @@ private fun ScanStatusLabel(
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) { Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
CircularProgressIndicator(modifier = Modifier.size(11.dp), strokeWidth = 1.5.dp) CircularProgressIndicator(modifier = Modifier.size(11.dp), strokeWidth = 1.5.dp)
Text( Text(
text = stringRes(R.string.blossom_import_scanning), text = stringRes(Res.string.blossom_import_scanning),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -362,7 +374,7 @@ private fun ScanStatusLabel(
} }
is SourceScanState.Failed -> is SourceScanState.Failed ->
Text( Text(
text = stringRes(R.string.blossom_import_source_failed), text = stringRes(Res.string.blossom_import_source_failed),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
maxLines = 1, maxLines = 1,
@@ -55,6 +55,8 @@ import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.blossom_sync_done
import com.vitorpamplona.amethyst.service.uploads.blossom.BlossomSyncState import com.vitorpamplona.amethyst.service.uploads.blossom.BlossomSyncState
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.allGoodColor import com.vitorpamplona.amethyst.ui.theme.allGoodColor
@@ -118,7 +120,7 @@ fun DisplayBlossomSyncProgress() {
tint = if (s.running) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.allGoodColor, tint = if (s.running) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.allGoodColor,
) )
Text( Text(
text = if (s.running) stringRes(R.string.blossom_syncing) else stringRes(R.string.blossom_sync_done), text = if (s.running) stringRes(R.string.blossom_syncing) else stringRes(Res.string.blossom_sync_done),
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -54,6 +54,17 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.nests_servers_add_auth_field
import com.vitorpamplona.amethyst.commons.resources.nests_servers_add_pair_button
import com.vitorpamplona.amethyst.commons.resources.nests_servers_add_recommended
import com.vitorpamplona.amethyst.commons.resources.nests_servers_add_relay_field
import com.vitorpamplona.amethyst.commons.resources.nests_servers_auth_label
import com.vitorpamplona.amethyst.commons.resources.nests_servers_empty
import com.vitorpamplona.amethyst.commons.resources.nests_servers_explainer
import com.vitorpamplona.amethyst.commons.resources.nests_servers_relay_label
import com.vitorpamplona.amethyst.commons.resources.nests_servers_remove
import com.vitorpamplona.amethyst.commons.resources.nests_servers_use_defaults
import com.vitorpamplona.amethyst.ui.actions.mediaServers.AllMediaServersScreen import com.vitorpamplona.amethyst.ui.actions.mediaServers.AllMediaServersScreen
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -137,7 +148,7 @@ private fun NestsServersScaffold(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Text( Text(
text = stringRes(id = R.string.nests_servers_explainer), text = stringRes(id = Res.string.nests_servers_explainer),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 10.dp), modifier = Modifier.padding(top = 10.dp),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
@@ -168,7 +179,7 @@ private fun NestsServersBody(viewModel: NestsServersViewModel) {
if (servers.isEmpty()) { if (servers.isEmpty()) {
item { item {
Text( Text(
text = stringRes(id = R.string.nests_servers_empty), text = stringRes(id = Res.string.nests_servers_empty),
modifier = DoubleVertPadding, modifier = DoubleVertPadding,
) )
} }
@@ -198,7 +209,7 @@ private fun NestsServersBody(viewModel: NestsServersViewModel) {
OutlinedButton( OutlinedButton(
onClick = { viewModel.addServerList(DEFAULT_NESTS_SERVERS) }, onClick = { viewModel.addServerList(DEFAULT_NESTS_SERVERS) },
) { ) {
Text(text = stringRes(id = R.string.nests_servers_use_defaults)) Text(text = stringRes(id = Res.string.nests_servers_use_defaults))
} }
} }
} }
@@ -234,12 +245,12 @@ private fun NestsServerRow(
) )
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
Text( Text(
text = "${stringRes(R.string.nests_servers_relay_label)}: ${server.relay}", text = "${stringRes(Res.string.nests_servers_relay_label)}: ${server.relay}",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
Text( Text(
text = "${stringRes(R.string.nests_servers_auth_label)}: ${server.auth}", text = "${stringRes(Res.string.nests_servers_auth_label)}: ${server.auth}",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText, color = MaterialTheme.colorScheme.grayText,
) )
@@ -250,9 +261,9 @@ private fun NestsServerRow(
symbol = if (isAmethystDefault) MaterialSymbols.Add else MaterialSymbols.Delete, symbol = if (isAmethystDefault) MaterialSymbols.Add else MaterialSymbols.Delete,
contentDescription = contentDescription =
if (isAmethystDefault) { if (isAmethystDefault) {
stringRes(id = R.string.nests_servers_add_recommended) stringRes(id = Res.string.nests_servers_add_recommended)
} else { } else {
stringRes(id = R.string.nests_servers_remove) stringRes(id = Res.string.nests_servers_remove)
}, },
) )
} }
@@ -287,7 +298,7 @@ private fun NestsServerPairEditField(onAdd: (relay: String, auth: String) -> Uni
verticalArrangement = Arrangement.spacedBy(Size10dp), verticalArrangement = Arrangement.spacedBy(Size10dp),
) { ) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.nests_servers_add_relay_field)) }, label = { Text(text = stringRes(Res.string.nests_servers_add_relay_field)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = relay, value = relay,
onValueChange = { relay = it }, onValueChange = { relay = it },
@@ -301,7 +312,7 @@ private fun NestsServerPairEditField(onAdd: (relay: String, auth: String) -> Uni
singleLine = true, singleLine = true,
) )
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.nests_servers_add_auth_field)) }, label = { Text(text = stringRes(Res.string.nests_servers_add_auth_field)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = auth, value = auth,
onValueChange = { auth = it }, onValueChange = { auth = it },
@@ -329,7 +340,7 @@ private fun NestsServerPairEditField(onAdd: (relay: String, auth: String) -> Uni
shape = ButtonBorder, shape = ButtonBorder,
enabled = canSubmit, enabled = canSubmit,
) { ) {
Text(stringRes(R.string.nests_servers_add_pair_button)) Text(stringRes(Res.string.nests_servers_add_pair_button))
} }
} }
} }
@@ -53,6 +53,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.delete_payment_target
import com.vitorpamplona.amethyst.commons.resources.no_payment_targets_message
import com.vitorpamplona.amethyst.commons.resources.payment_target_authority
import com.vitorpamplona.amethyst.commons.resources.payment_target_type
import com.vitorpamplona.amethyst.commons.resources.payment_targets_explainer
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
@@ -121,7 +127,7 @@ fun PaymentTargetsScaffold(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Text( Text(
text = stringRes(id = R.string.payment_targets_explainer), text = stringRes(id = Res.string.payment_targets_explainer),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 10.dp), modifier = Modifier.padding(top = 10.dp),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
@@ -153,7 +159,7 @@ fun PaymentTargetsBody(viewModel: PaymentTargetsViewModel) {
if (targets.isEmpty()) { if (targets.isEmpty()) {
item { item {
Text( Text(
text = stringRes(id = R.string.no_payment_targets_message), text = stringRes(id = Res.string.no_payment_targets_message),
modifier = Modifier.padding(vertical = 16.dp), modifier = Modifier.padding(vertical = 16.dp),
) )
} }
@@ -203,7 +209,7 @@ fun PaymentTargetEntry(
IconButton(onClick = onDelete) { IconButton(onClick = onDelete) {
Icon( Icon(
symbol = MaterialSymbols.Delete, symbol = MaterialSymbols.Delete,
contentDescription = stringRes(id = R.string.delete_payment_target), contentDescription = stringRes(id = Res.string.delete_payment_target),
) )
} }
} }
@@ -221,7 +227,7 @@ fun PaymentTargetAddField(onAdd: (type: String, authority: String) -> Unit) {
horizontalArrangement = Arrangement.spacedBy(Size10dp), horizontalArrangement = Arrangement.spacedBy(Size10dp),
) { ) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.payment_target_type)) }, label = { Text(text = stringRes(Res.string.payment_target_type)) },
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
value = type, value = type,
onValueChange = { type = it }, onValueChange = { type = it },
@@ -240,7 +246,7 @@ fun PaymentTargetAddField(onAdd: (type: String, authority: String) -> Unit) {
horizontalArrangement = Arrangement.spacedBy(Size10dp), horizontalArrangement = Arrangement.spacedBy(Size10dp),
) { ) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.payment_target_authority)) }, label = { Text(text = stringRes(Res.string.payment_target_authority)) },
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
value = authority, value = authority,
onValueChange = { authority = it }, onValueChange = { authority = it },
@@ -37,9 +37,10 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.record_a_message
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@Composable @Composable
@@ -91,7 +92,7 @@ fun RecordVoiceButton(
// Microphone icon // Microphone icon
Icon( Icon(
symbol = MaterialSymbols.Mic, symbol = MaterialSymbols.Mic,
contentDescription = stringRes(id = R.string.record_a_message), contentDescription = stringRes(id = Res.string.record_a_message),
modifier = Modifier.height(22.dp), modifier = Modifier.height(22.dp),
tint = tint =
if (recordingState) { if (recordingState) {
@@ -47,9 +47,11 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.recording_indicator_description
import com.vitorpamplona.amethyst.commons.resources.recording_indicator_with_time
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
/** /**
@@ -180,12 +182,12 @@ fun FloatingRecordingIndicator(
) { ) {
if (!isRecording) return if (!isRecording) return
val recordingLabel = stringRes(id = R.string.recording_indicator_description) val recordingLabel = stringRes(id = Res.string.recording_indicator_description)
val recordingWithTime = val recordingWithTime =
if (isCompact) { if (isCompact) {
formatSecondsToTime(elapsedSeconds) formatSecondsToTime(elapsedSeconds)
} else { } else {
stringRes(id = R.string.recording_indicator_with_time, formatSecondsToTime(elapsedSeconds)) stringRes(id = Res.string.recording_indicator_with_time, formatSecondsToTime(elapsedSeconds))
} }
val horizontalPadding = if (isCompact) 8.dp else 16.dp val horizontalPadding = if (isCompact) 8.dp else 16.dp
val innerPadding = if (isCompact) 6.dp else 12.dp val innerPadding = if (isCompact) 6.dp else 12.dp
@@ -35,9 +35,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.upload_file
import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -83,7 +84,7 @@ private fun FileSelectButton(
if (!isUploading) { if (!isUploading) {
Icon( Icon(
symbol = MaterialSymbols.AttachFile, symbol = MaterialSymbols.AttachFile,
contentDescription = stringRes(id = R.string.upload_file), contentDescription = stringRes(id = Res.string.upload_file),
modifier = Modifier.height(20.dp), modifier = Modifier.height(20.dp),
tint = tint, tint = tint,
) )
@@ -37,9 +37,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.upload_image
import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation
import com.vitorpamplona.amethyst.service.uploads.isAvif import com.vitorpamplona.amethyst.service.uploads.isAvif
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -150,7 +151,7 @@ private fun GallerySelectButton(
if (!isUploading) { if (!isUploading) {
Icon( Icon(
symbol = MaterialSymbols.AddPhotoAlternate, symbol = MaterialSymbols.AddPhotoAlternate,
contentDescription = stringRes(id = R.string.upload_image), contentDescription = stringRes(id = Res.string.upload_image),
modifier = Modifier.height(25.dp), modifier = Modifier.height(25.dp),
tint = tint, tint = tint,
) )
@@ -60,10 +60,18 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbol
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.uploading_state_compressing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_downloading
import com.vitorpamplona.amethyst.commons.resources.uploading_state_error
import com.vitorpamplona.amethyst.commons.resources.uploading_state_finished
import com.vitorpamplona.amethyst.commons.resources.uploading_state_hashing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_ready
import com.vitorpamplona.amethyst.commons.resources.uploading_state_server_processing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_uploading
import com.vitorpamplona.amethyst.service.playback.composable.VideoView import com.vitorpamplona.amethyst.service.playback.composable.VideoView
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
@@ -266,14 +274,14 @@ fun UploadingState(
val txt = val txt =
when (progressState) { when (progressState) {
is UploadingState.Ready -> stringRes(R.string.uploading_state_ready) is UploadingState.Ready -> stringRes(Res.string.uploading_state_ready)
is UploadingState.Compressing -> stringRes(R.string.uploading_state_compressing) is UploadingState.Compressing -> stringRes(Res.string.uploading_state_compressing)
is UploadingState.Uploading -> stringRes(R.string.uploading_state_uploading) is UploadingState.Uploading -> stringRes(Res.string.uploading_state_uploading)
is UploadingState.ServerProcessing -> stringRes(R.string.uploading_state_server_processing) is UploadingState.ServerProcessing -> stringRes(Res.string.uploading_state_server_processing)
is UploadingState.Downloading -> stringRes(R.string.uploading_state_downloading) is UploadingState.Downloading -> stringRes(Res.string.uploading_state_downloading)
is UploadingState.Hashing -> stringRes(R.string.uploading_state_hashing) is UploadingState.Hashing -> stringRes(Res.string.uploading_state_hashing)
is UploadingState.Finished -> stringRes(R.string.uploading_state_finished) is UploadingState.Finished -> stringRes(Res.string.uploading_state_finished)
is UploadingState.Error -> stringRes(R.string.uploading_state_error) is UploadingState.Error -> stringRes(Res.string.uploading_state_error)
} }
Text( Text(
@@ -49,6 +49,9 @@ import com.google.accompanist.permissions.rememberPermissionState
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.record_a_video
import com.vitorpamplona.amethyst.commons.resources.take_a_picture
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@@ -136,7 +139,7 @@ fun PictureButton(onClick: () -> Unit) {
) { ) {
Icon( Icon(
symbol = MaterialSymbols.CameraAlt, symbol = MaterialSymbols.CameraAlt,
contentDescription = stringRes(id = R.string.take_a_picture), contentDescription = stringRes(id = Res.string.take_a_picture),
modifier = Modifier.height(22.dp), modifier = Modifier.height(22.dp),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
@@ -249,7 +252,7 @@ fun VideoButton(onClick: () -> Unit) {
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Videocam, symbol = MaterialSymbols.Videocam,
contentDescription = stringRes(id = R.string.record_a_video), contentDescription = stringRes(id = Res.string.record_a_video),
modifier = Modifier.height(22.dp), modifier = Modifier.height(22.dp),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
@@ -39,7 +39,15 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.uploading_state_compressing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_downloading
import com.vitorpamplona.amethyst.commons.resources.uploading_state_error
import com.vitorpamplona.amethyst.commons.resources.uploading_state_finished
import com.vitorpamplona.amethyst.commons.resources.uploading_state_hashing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_ready
import com.vitorpamplona.amethyst.commons.resources.uploading_state_server_processing
import com.vitorpamplona.amethyst.commons.resources.uploading_state_uploading
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
@@ -80,14 +88,14 @@ fun UploadProgressIndicator(
val txt = val txt =
when (progressStatusValue) { when (progressStatusValue) {
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Ready -> stringRes(R.string.uploading_state_ready) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Ready -> stringRes(Res.string.uploading_state_ready)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Compressing -> stringRes(R.string.uploading_state_compressing) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Compressing -> stringRes(Res.string.uploading_state_compressing)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Uploading -> stringRes(R.string.uploading_state_uploading) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Uploading -> stringRes(Res.string.uploading_state_uploading)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.ServerProcessing -> stringRes(R.string.uploading_state_server_processing) is com.vitorpamplona.amethyst.service.uploads.UploadingState.ServerProcessing -> stringRes(Res.string.uploading_state_server_processing)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Downloading -> stringRes(R.string.uploading_state_downloading) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Downloading -> stringRes(Res.string.uploading_state_downloading)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Hashing -> stringRes(R.string.uploading_state_hashing) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Hashing -> stringRes(Res.string.uploading_state_hashing)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Finished -> stringRes(R.string.uploading_state_finished) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Finished -> stringRes(Res.string.uploading_state_finished)
is com.vitorpamplona.amethyst.service.uploads.UploadingState.Error -> stringRes(R.string.uploading_state_error) is com.vitorpamplona.amethyst.service.uploads.UploadingState.Error -> stringRes(Res.string.uploading_state_error)
} }
Text( Text(
@@ -32,7 +32,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.voice_anonymize_description
import com.vitorpamplona.amethyst.commons.resources.voice_anonymize_title
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.Size5dp import com.vitorpamplona.amethyst.ui.theme.Size5dp
@@ -55,12 +57,12 @@ fun VoiceAnonymizationSection(
verticalArrangement = Arrangement.spacedBy(Size5dp), verticalArrangement = Arrangement.spacedBy(Size5dp),
) { ) {
Text( Text(
text = stringRes(R.string.voice_anonymize_title), text = stringRes(Res.string.voice_anonymize_title),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
Text( Text(
text = stringRes(R.string.voice_anonymize_description), text = stringRes(Res.string.voice_anonymize_description),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 3, maxLines = 3,
@@ -51,6 +51,10 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.re_record
import com.vitorpamplona.amethyst.commons.resources.record_a_message
import com.vitorpamplona.amethyst.commons.resources.recording_indicator_description
import com.vitorpamplona.amethyst.ui.components.AudioWaveformReadOnly import com.vitorpamplona.amethyst.ui.components.AudioWaveformReadOnly
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.quartz.nipA0VoiceMessages.AudioMeta import com.vitorpamplona.quartz.nipA0VoiceMessages.AudioMeta
@@ -195,11 +199,11 @@ private fun ReRecordButton(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Mic, symbol = MaterialSymbols.Mic,
contentDescription = stringRes(id = R.string.record_a_message), contentDescription = stringRes(id = Res.string.record_a_message),
tint = MaterialTheme.colorScheme.onSurfaceVariant, tint = MaterialTheme.colorScheme.onSurfaceVariant,
) )
Text( Text(
text = stringRes(id = R.string.re_record), text = stringRes(id = Res.string.re_record),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
} }
@@ -227,13 +231,13 @@ private fun ReRecordButton(
if (isRecording) { if (isRecording) {
formatSecondsToTime(elapsedSeconds) formatSecondsToTime(elapsedSeconds)
} else { } else {
stringRes(id = R.string.re_record) stringRes(id = Res.string.re_record)
} }
val iconDescription = val iconDescription =
if (isRecording) { if (isRecording) {
stringRes(id = R.string.recording_indicator_description) stringRes(id = Res.string.recording_indicator_description)
} else { } else {
stringRes(id = R.string.record_a_message) stringRes(id = Res.string.record_a_message)
} }
Row( Row(
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
@@ -70,6 +70,22 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.defaults.Constants import com.vitorpamplona.amethyst.commons.defaults.Constants
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.bradcasting_result_failure
import com.vitorpamplona.amethyst.commons.resources.bradcasting_result_partial
import com.vitorpamplona.amethyst.commons.resources.bradcasting_result_success
import com.vitorpamplona.amethyst.commons.resources.broadcasting
import com.vitorpamplona.amethyst.commons.resources.broadcasting_name
import com.vitorpamplona.amethyst.commons.resources.broadcasting_number_events
import com.vitorpamplona.amethyst.commons.resources.event_sent
import com.vitorpamplona.amethyst.commons.resources.pow_cancel_dialog_discard
import com.vitorpamplona.amethyst.commons.resources.pow_cancel_dialog_message
import com.vitorpamplona.amethyst.commons.resources.pow_cancel_dialog_send_without_pow
import com.vitorpamplona.amethyst.commons.resources.pow_cancel_dialog_title
import com.vitorpamplona.amethyst.commons.resources.retry_failed
import com.vitorpamplona.amethyst.commons.resources.sent_number_events
import com.vitorpamplona.amethyst.commons.resources.share_of
import com.vitorpamplona.amethyst.commons.resources.tap_to_view_details
import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastEvent import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastEvent
import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastStatus import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastStatus
import com.vitorpamplona.amethyst.commons.service.broadcast.RelayResult import com.vitorpamplona.amethyst.commons.service.broadcast.RelayResult
@@ -371,17 +387,17 @@ private fun PoWCancelDialog(
) { ) {
AlertDialog( AlertDialog(
onDismissRequest = onKeepMining, onDismissRequest = onKeepMining,
title = { Text(stringRes(R.string.pow_cancel_dialog_title)) }, title = { Text(stringRes(Res.string.pow_cancel_dialog_title)) },
text = { Text(stringRes(R.string.pow_cancel_dialog_message)) }, text = { Text(stringRes(Res.string.pow_cancel_dialog_message)) },
confirmButton = { confirmButton = {
TextButton(onClick = onSendWithoutPow) { TextButton(onClick = onSendWithoutPow) {
Text(stringRes(R.string.pow_cancel_dialog_send_without_pow)) Text(stringRes(Res.string.pow_cancel_dialog_send_without_pow))
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = onDiscard) { TextButton(onClick = onDiscard) {
Text( Text(
text = stringRes(R.string.pow_cancel_dialog_discard), text = stringRes(Res.string.pow_cancel_dialog_discard),
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
) )
} }
@@ -398,7 +414,7 @@ private fun SingleBroadcastContent(broadcast: BroadcastEvent) {
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Sync, symbol = MaterialSymbols.Sync,
contentDescription = stringRes(R.string.broadcasting), contentDescription = stringRes(Res.string.broadcasting),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
) )
@@ -409,7 +425,7 @@ private fun SingleBroadcastContent(broadcast: BroadcastEvent) {
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text( Text(
text = stringRes(R.string.broadcasting_name, broadcast.event.toKindName()), text = stringRes(Res.string.broadcasting_name, broadcast.event.toKindName()),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
maxLines = 1, maxLines = 1,
@@ -420,7 +436,7 @@ private fun SingleBroadcastContent(broadcast: BroadcastEvent) {
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(8.dp))
Text( Text(
text = stringRes(R.string.share_of, broadcast.results.size, broadcast.totalRelays), text = stringRes(Res.string.share_of, broadcast.results.size, broadcast.totalRelays),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
) )
@@ -456,7 +472,7 @@ private fun MultipleBroadcastsContent(broadcasts: ImmutableList<BroadcastEvent>)
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Sync, symbol = MaterialSymbols.Sync,
contentDescription = stringRes(R.string.broadcasting), contentDescription = stringRes(Res.string.broadcasting),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
) )
@@ -467,13 +483,13 @@ private fun MultipleBroadcastsContent(broadcasts: ImmutableList<BroadcastEvent>)
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text( Text(
text = stringRes(R.string.broadcasting_number_events, broadcasts.size), text = stringRes(Res.string.broadcasting_number_events, broadcasts.size),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
) )
Text( Text(
text = stringRes(R.string.share_of, completedResponses, totalRelays), text = stringRes(Res.string.share_of, completedResponses, totalRelays),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
) )
@@ -536,7 +552,7 @@ fun CompletedBroadcastContent(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text( Text(
text = stringRes(R.string.event_sent, broadcast.event.toKindName()), text = stringRes(Res.string.event_sent, broadcast.event.toKindName()),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
maxLines = 1, maxLines = 1,
@@ -547,7 +563,7 @@ fun CompletedBroadcastContent(
if (broadcast.failedRelays.isNotEmpty()) { if (broadcast.failedRelays.isNotEmpty()) {
Text( Text(
text = stringRes(R.string.tap_to_view_details), text = stringRes(Res.string.tap_to_view_details),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -555,7 +571,7 @@ fun CompletedBroadcastContent(
} }
Text( Text(
text = stringRes(R.string.share_of, broadcast.successCount, broadcast.totalRelays), text = stringRes(Res.string.share_of, broadcast.successCount, broadcast.totalRelays),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = iconTint, color = iconTint,
) )
@@ -568,7 +584,7 @@ fun CompletedBroadcastContent(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Refresh, symbol = MaterialSymbols.Refresh,
contentDescription = stringRes(R.string.retry_failed), contentDescription = stringRes(Res.string.retry_failed),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
) )
@@ -622,11 +638,11 @@ fun MultipleCompletedBroadcastContent(
symbol = statusIcon, symbol = statusIcon,
contentDescription = contentDescription =
if (allSuccess) { if (allSuccess) {
stringRes(R.string.bradcasting_result_success) stringRes(Res.string.bradcasting_result_success)
} else if (allFailed) { } else if (allFailed) {
stringRes(R.string.bradcasting_result_failure) stringRes(Res.string.bradcasting_result_failure)
} else { } else {
stringRes(R.string.bradcasting_result_partial) stringRes(Res.string.bradcasting_result_partial)
}, },
tint = iconTint, tint = iconTint,
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
@@ -639,7 +655,7 @@ fun MultipleCompletedBroadcastContent(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text( Text(
text = stringRes(R.string.sent_number_events, broadcasts.size), text = stringRes(Res.string.sent_number_events, broadcasts.size),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
maxLines = 1, maxLines = 1,
@@ -650,7 +666,7 @@ fun MultipleCompletedBroadcastContent(
if (failedRelayCount > 0) { if (failedRelayCount > 0) {
Text( Text(
text = stringRes(R.string.tap_to_view_details), text = stringRes(Res.string.tap_to_view_details),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -658,7 +674,7 @@ fun MultipleCompletedBroadcastContent(
} }
Text( Text(
text = stringRes(R.string.share_of, (totalRelayCount - failedRelayCount), totalRelayCount), text = stringRes(Res.string.share_of, (totalRelayCount - failedRelayCount), totalRelayCount),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = iconTint, color = iconTint,
) )
@@ -671,7 +687,7 @@ fun MultipleCompletedBroadcastContent(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Refresh, symbol = MaterialSymbols.Refresh,
contentDescription = stringRes(R.string.retry_failed), contentDescription = stringRes(Res.string.retry_failed),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
) )
@@ -72,6 +72,15 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.defaults.Constants import com.vitorpamplona.amethyst.commons.defaults.Constants
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.broadcast_results
import com.vitorpamplona.amethyst.commons.resources.broadcasts_number
import com.vitorpamplona.amethyst.commons.resources.collapse
import com.vitorpamplona.amethyst.commons.resources.dismiss
import com.vitorpamplona.amethyst.commons.resources.retry_failed_number
import com.vitorpamplona.amethyst.commons.resources.retrying
import com.vitorpamplona.amethyst.commons.resources.share_of
import com.vitorpamplona.amethyst.commons.resources.timeout
import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastEvent import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastEvent
import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastStatus import com.vitorpamplona.amethyst.commons.service.broadcast.BroadcastStatus
import com.vitorpamplona.amethyst.commons.service.broadcast.RelayResult import com.vitorpamplona.amethyst.commons.service.broadcast.RelayResult
@@ -164,7 +173,7 @@ fun MultiBroadcastDetailsSheetContent(
) { ) {
// Header // Header
Text( Text(
text = if (broadcasts.size == 1) stringRes(R.string.broadcast_results) else stringRes(R.string.broadcasts_number, broadcasts.size), text = if (broadcasts.size == 1) stringRes(Res.string.broadcast_results) else stringRes(Res.string.broadcasts_number, broadcasts.size),
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
) )
@@ -201,7 +210,7 @@ fun MultiBroadcastDetailsSheetContent(
onClick = onDismiss, onClick = onDismiss,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text(stringRes(R.string.dismiss)) Text(stringRes(Res.string.dismiss))
} }
} }
} }
@@ -242,14 +251,14 @@ private fun BroadcastSection(
} }
Text( Text(
text = stringResource(R.string.share_of, broadcast.successCount, broadcast.totalRelays), text = stringRes(Res.string.share_of, broadcast.successCount, broadcast.totalRelays),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = statusColor(broadcast.status), color = statusColor(broadcast.status),
) )
Icon( Icon(
symbol = if (isExpanded) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore, symbol = if (isExpanded) MaterialSymbols.ExpandLess else MaterialSymbols.ExpandMore,
contentDescription = if (isExpanded) stringRes(R.string.collapse) else stringRes(R.string.expand), contentDescription = if (isExpanded) stringRes(Res.string.collapse) else stringRes(R.string.expand),
tint = MaterialTheme.colorScheme.onSurfaceVariant, tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
) )
@@ -290,7 +299,7 @@ private fun BroadcastSection(
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
) )
Spacer(Modifier.width(4.dp)) Spacer(Modifier.width(4.dp))
Text(stringRes(R.string.retry_failed_number, broadcast.failedRelays.size)) Text(stringRes(Res.string.retry_failed_number, broadcast.failedRelays.size))
} }
} }
} }
@@ -408,7 +417,7 @@ private fun RelayResultRow(
is RelayResult.Timeout -> { is RelayResult.Timeout -> {
Text( Text(
text = stringRes(R.string.timeout), text = stringRes(Res.string.timeout),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = warningColor, color = warningColor,
) )
@@ -416,7 +425,7 @@ private fun RelayResultRow(
is RelayResult.Retrying -> { is RelayResult.Retrying -> {
Text( Text(
text = stringRes(R.string.retrying), text = stringRes(Res.string.retrying),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
) )
@@ -39,6 +39,10 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_permission_denied_cancel
import com.vitorpamplona.amethyst.commons.resources.call_permission_denied_open_settings
import com.vitorpamplona.amethyst.commons.resources.call_permission_denied_title
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
fun hasPermission( fun hasPermission(
@@ -145,7 +149,7 @@ private fun CallPermissionDeniedDialog(
) { ) {
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
title = { Text(stringRes(R.string.call_permission_denied_title)) }, title = { Text(stringRes(Res.string.call_permission_denied_title)) },
text = { text = {
Text( Text(
stringRes( stringRes(
@@ -159,12 +163,12 @@ private fun CallPermissionDeniedDialog(
}, },
confirmButton = { confirmButton = {
TextButton(onClick = onOpenSettings) { TextButton(onClick = onOpenSettings) {
Text(stringRes(R.string.call_permission_denied_open_settings)) Text(stringRes(Res.string.call_permission_denied_open_settings))
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = onDismiss) { TextButton(onClick = onDismiss) {
Text(stringRes(R.string.call_permission_denied_cancel)) Text(stringRes(Res.string.call_permission_denied_cancel))
} }
}, },
) )
@@ -61,6 +61,11 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallManager import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallManager
import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallState import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallState
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_calling
import com.vitorpamplona.amethyst.commons.resources.call_connecting
import com.vitorpamplona.amethyst.commons.resources.call_dismiss
import com.vitorpamplona.amethyst.commons.resources.call_ended
import com.vitorpamplona.amethyst.ui.call.session.CallSession import com.vitorpamplona.amethyst.ui.call.session.CallSession
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -111,11 +116,11 @@ fun CallScreen(
state.peerPubKeys - accountViewModel.account.signer.pubKey state.peerPubKeys - accountViewModel.account.signer.pubKey
} }
if (isInPipMode) { if (isInPipMode) {
PipCallUI(peerPubKeys = otherMembers, statusText = stringRes(R.string.call_calling), accountViewModel = accountViewModel) PipCallUI(peerPubKeys = otherMembers, statusText = stringRes(Res.string.call_calling), accountViewModel = accountViewModel)
} else { } else {
CallInProgressUI( CallInProgressUI(
peerPubKeys = otherMembers, peerPubKeys = otherMembers,
statusText = stringRes(R.string.call_calling), statusText = stringRes(Res.string.call_calling),
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
onHangup = { scope.launch { callManager.hangup() } }, onHangup = { scope.launch { callManager.hangup() } },
) )
@@ -151,11 +156,11 @@ fun CallScreen(
state.peerPubKeys - accountViewModel.account.signer.pubKey state.peerPubKeys - accountViewModel.account.signer.pubKey
} }
if (isInPipMode) { if (isInPipMode) {
PipCallUI(peerPubKeys = otherMembers, statusText = stringRes(R.string.call_connecting), accountViewModel = accountViewModel) PipCallUI(peerPubKeys = otherMembers, statusText = stringRes(Res.string.call_connecting), accountViewModel = accountViewModel)
} else { } else {
CallInProgressUI( CallInProgressUI(
peerPubKeys = otherMembers, peerPubKeys = otherMembers,
statusText = stringRes(R.string.call_connecting), statusText = stringRes(Res.string.call_connecting),
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
onHangup = { scope.launch { callManager.hangup() } }, onHangup = { scope.launch { callManager.hangup() } },
) )
@@ -191,7 +196,7 @@ fun CallScreen(
if (!isInPipMode) { if (!isInPipMode) {
CallInProgressUI( CallInProgressUI(
peerPubKeys = otherMembers, peerPubKeys = otherMembers,
statusText = stringRes(R.string.call_ended), statusText = stringRes(Res.string.call_ended),
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
onHangup = { onCallEnded() }, onHangup = { onCallEnded() },
) )
@@ -212,7 +217,7 @@ fun CallScreen(
onClick = { callSession?.clearError() }, onClick = { callSession?.clearError() },
) { ) {
Text( Text(
stringRes(R.string.call_dismiss), stringRes(Res.string.call_dismiss),
color = MaterialTheme.colorScheme.inversePrimary, color = MaterialTheme.colorScheme.inversePrimary,
) )
} }
@@ -48,7 +48,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_calling
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
@@ -130,7 +131,7 @@ fun PeerVideoGrid(
PeerAvatarCell( PeerAvatarCell(
peerPubKey = peerKey, peerPubKey = peerKey,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
statusText = if (isPending) stringRes(R.string.call_calling) else null, statusText = if (isPending) stringRes(Res.string.call_calling) else null,
modifier = modifier, modifier = modifier,
) )
} }
@@ -161,7 +162,7 @@ fun PeerVideoGrid(
PeerAvatarCell( PeerAvatarCell(
peerPubKey = peerKey, peerPubKey = peerKey,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
statusText = if (isPending) stringRes(R.string.call_calling) else null, statusText = if (isPending) stringRes(Res.string.call_calling) else null,
modifier = cellModifier, modifier = cellModifier,
) )
} }
@@ -59,6 +59,11 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallState import com.vitorpamplona.amethyst.commons.nipACWebRtcCalls.CallState
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.call_add_participant
import com.vitorpamplona.amethyst.commons.resources.call_dismiss
import com.vitorpamplona.amethyst.commons.resources.call_search_users
import com.vitorpamplona.amethyst.commons.resources.call_switch_camera
import com.vitorpamplona.amethyst.service.call.AudioRoute import com.vitorpamplona.amethyst.service.call.AudioRoute
import com.vitorpamplona.amethyst.ui.call.session.CallSession import com.vitorpamplona.amethyst.ui.call.session.CallSession
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
@@ -313,7 +318,7 @@ private fun CallControls(
} else { } else {
MaterialSymbols.CameraFront MaterialSymbols.CameraFront
}, },
contentDescription = stringRes(R.string.call_switch_camera), contentDescription = stringRes(Res.string.call_switch_camera),
tint = Color.White, tint = Color.White,
modifier = Modifier.size(28.dp), modifier = Modifier.size(28.dp),
) )
@@ -347,7 +352,7 @@ private fun CallControls(
IconButton(onClick = onAddParticipant, modifier = Modifier.size(56.dp)) { IconButton(onClick = onAddParticipant, modifier = Modifier.size(56.dp)) {
Icon( Icon(
symbol = MaterialSymbols.PersonAdd, symbol = MaterialSymbols.PersonAdd,
contentDescription = stringRes(R.string.call_add_participant), contentDescription = stringRes(Res.string.call_add_participant),
tint = Color.White, tint = Color.White,
modifier = Modifier.size(28.dp), modifier = Modifier.size(28.dp),
) )
@@ -385,7 +390,7 @@ private fun AddParticipantDialog(
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
title = { Text(stringRes(R.string.call_add_participant)) }, title = { Text(stringRes(Res.string.call_add_participant)) },
text = { text = {
Column { Column {
OutlinedTextField( OutlinedTextField(
@@ -394,7 +399,7 @@ private fun AddParticipantDialog(
searchText = it searchText = it
userSuggestions.processCurrentWord(it) userSuggestions.processCurrentWord(it)
}, },
label = { Text(stringRes(R.string.call_search_users)) }, label = { Text(stringRes(Res.string.call_search_users)) },
singleLine = true, singleLine = true,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) )
@@ -414,7 +419,7 @@ private fun AddParticipantDialog(
confirmButton = {}, confirmButton = {},
dismissButton = { dismissButton = {
TextButton(onClick = onDismiss) { TextButton(onClick = onDismiss) {
Text(stringRes(R.string.call_dismiss)) Text(stringRes(Res.string.call_dismiss))
} }
}, },
) )
@@ -29,8 +29,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.cast_searching_for_devices
import com.vitorpamplona.amethyst.commons.resources.cast_to_device_dialog_title
import com.vitorpamplona.amethyst.service.cast.CastRegistry import com.vitorpamplona.amethyst.service.cast.CastRegistry
import com.vitorpamplona.amethyst.service.cast.CastRequest import com.vitorpamplona.amethyst.service.cast.CastRequest
import com.vitorpamplona.amethyst.service.cast.CastSessionState import com.vitorpamplona.amethyst.service.cast.CastSessionState
@@ -67,12 +69,12 @@ fun CastDevicePickerDialog(
val castScope = Amethyst.instance.applicationIOScope val castScope = Amethyst.instance.applicationIOScope
M3ActionDialog( M3ActionDialog(
title = stringRes(R.string.cast_to_device_dialog_title), title = stringRes(Res.string.cast_to_device_dialog_title),
onDismiss = onDismiss, onDismiss = onDismiss,
) { ) {
if (devices.isEmpty()) { if (devices.isEmpty()) {
Text( Text(
text = stringRes(R.string.cast_searching_for_devices), text = stringRes(Res.string.cast_searching_for_devices),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp), modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp),
@@ -52,6 +52,9 @@ import androidx.core.net.toUri
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.Cashu import com.vitorpamplona.amethyst.commons.hashtags.Cashu
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.cashu_mint_label
import com.vitorpamplona.amethyst.commons.resources.cashu_redeem
import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable
import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation
import com.vitorpamplona.amethyst.service.cashu.CachedCashuParser import com.vitorpamplona.amethyst.service.cashu.CachedCashuParser
@@ -181,7 +184,7 @@ fun CashuPreviewNew(
} }
Text( Text(
text = stringRes(R.string.cashu_mint_label, token.mint.removePrefix("https://")), text = stringRes(Res.string.cashu_mint_label, token.mint.removePrefix("https://")),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@@ -221,7 +224,7 @@ fun CashuPreviewNew(
} }
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.cashu_redeem)) Text(stringRes(Res.string.cashu_redeem))
} }
Spacer(modifier = StdHorzSpacer) Spacer(modifier = StdHorzSpacer)
@@ -54,11 +54,12 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.commons.model.EmptyTagList
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.concord_invite_naddr_label
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserNickname import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserNickname
@@ -231,7 +232,7 @@ private fun DisplayAddress(
// (and here always-empty) addressable-note card. // (and here always-empty) addressable-note card.
if (nip19.kind == ConcordInviteBundleEvent.KIND) { if (nip19.kind == ConcordInviteBundleEvent.KIND) {
Text( Text(
text = stringRes(R.string.concord_invite_naddr_label) + (additionalChars ?: ""), text = stringRes(Res.string.concord_invite_naddr_label) + (additionalChars ?: ""),
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
) )
return return
@@ -45,6 +45,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.actions.ConcordActions import com.vitorpamplona.amethyst.commons.actions.ConcordActions
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.concord_invite_card_join
import com.vitorpamplona.amethyst.commons.resources.concord_invite_card_subtitle
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -91,13 +94,13 @@ fun ConcordInviteCard(
ConcordInvitePreviewRow( ConcordInvitePreviewRow(
robotSeed = robotSeed, robotSeed = robotSeed,
title = title, title = title,
subtitle = stringRes(R.string.concord_invite_card_subtitle), subtitle = stringRes(Res.string.concord_invite_card_subtitle),
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
autoPlayGif = autoPlayGif, autoPlayGif = autoPlayGif,
) { ) {
SymbolIcon( SymbolIcon(
symbol = MaterialSymbols.ChevronRight, symbol = MaterialSymbols.ChevronRight,
contentDescription = stringRes(R.string.concord_invite_card_join), contentDescription = stringRes(Res.string.concord_invite_card_join),
modifier = Modifier.size(22.dp), modifier = Modifier.size(22.dp),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
) )
@@ -32,7 +32,10 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.deleted_items_banner_dismiss
import com.vitorpamplona.amethyst.commons.resources.deleted_items_banner_remove
import com.vitorpamplona.amethyst.commons.resources.deleted_items_banner_title
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.BigPadding import com.vitorpamplona.amethyst.ui.theme.BigPadding
import com.vitorpamplona.amethyst.ui.theme.StdPadding import com.vitorpamplona.amethyst.ui.theme.StdPadding
@@ -54,7 +57,7 @@ fun DeletedItemsBanner(
) { ) {
Column(modifier = BigPadding) { Column(modifier = BigPadding) {
Text( Text(
text = stringRes(R.string.deleted_items_banner_title, count), text = stringRes(Res.string.deleted_items_banner_title, count),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
@@ -65,10 +68,10 @@ fun DeletedItemsBanner(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
) { ) {
TextButton(onClick = onDismiss) { TextButton(onClick = onDismiss) {
Text(text = stringRes(R.string.deleted_items_banner_dismiss)) Text(text = stringRes(Res.string.deleted_items_banner_dismiss))
} }
Button(onClick = onRemove) { Button(onClick = onRemove) {
Text(text = stringRes(R.string.deleted_items_banner_remove)) Text(text = stringRes(Res.string.deleted_items_banner_remove))
} }
} }
} }
@@ -39,8 +39,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.show_more
import com.vitorpamplona.amethyst.commons.richtext.ExpandableTextCutOffCalculator import com.vitorpamplona.amethyst.commons.richtext.ExpandableTextCutOffCalculator
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.getGradient import com.vitorpamplona.amethyst.ui.note.getGradient
@@ -133,6 +134,6 @@ fun ShowMoreButton(onClick: () -> Unit) {
shape = ButtonBorder, shape = ButtonBorder,
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text(text = stringRes(R.string.show_more)) Text(text = stringRes(Res.string.show_more))
} }
} }
@@ -39,16 +39,17 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.asDrawable import coil3.asDrawable
import coil3.compose.AsyncImagePainter import coil3.compose.AsyncImagePainter
import coil3.compose.SubcomposeAsyncImage import coil3.compose.SubcomposeAsyncImage
import coil3.compose.SubcomposeAsyncImageContent import coil3.compose.SubcomposeAsyncImageContent
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.gif
import com.vitorpamplona.amethyst.model.MediaAspectRatioCache import com.vitorpamplona.amethyst.model.MediaAspectRatioCache
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Font10SP import com.vitorpamplona.amethyst.ui.theme.Font10SP
import com.vitorpamplona.amethyst.ui.theme.SmallBorder import com.vitorpamplona.amethyst.ui.theme.SmallBorder
import com.vitorpamplona.amethyst.ui.theme.imageModifier import com.vitorpamplona.amethyst.ui.theme.imageModifier
@@ -135,7 +136,7 @@ fun GifVideoView(
if (!autoPlay) { if (!autoPlay) {
Text( Text(
text = stringResource(R.string.gif), text = stringRes(Res.string.gif),
color = Color.White, color = Color.White,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = Font10SP, fontSize = Font10SP,
@@ -49,6 +49,10 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.relay_group_badge_invite_only
import com.vitorpamplona.amethyst.commons.resources.relay_group_badge_private
import com.vitorpamplona.amethyst.commons.resources.relay_group_open
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -110,8 +114,8 @@ private fun RelayGroupCardContent(
// private, so it wins when both are set. Null for a plain open group. // private, so it wins when both are set. Null for a plain open group.
val statusBadge = val statusBadge =
when { when {
channel.isClosed() -> stringRes(R.string.relay_group_badge_invite_only) channel.isClosed() -> stringRes(Res.string.relay_group_badge_invite_only)
channel.isPrivate() -> stringRes(R.string.relay_group_badge_private) channel.isPrivate() -> stringRes(Res.string.relay_group_badge_private)
else -> null else -> null
} }
@@ -200,7 +204,7 @@ private fun RelayGroupCardContent(
Icon( Icon(
symbol = MaterialSymbols.ChevronRight, symbol = MaterialSymbols.ChevronRight,
contentDescription = stringRes(R.string.relay_group_open), contentDescription = stringRes(Res.string.relay_group_open),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(22.dp), modifier = Modifier.size(22.dp),
) )
@@ -47,6 +47,9 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.donate_now
import com.vitorpamplona.amethyst.commons.resources.thank_you
import com.vitorpamplona.amethyst.service.ZapPaymentHandler import com.vitorpamplona.amethyst.service.ZapPaymentHandler
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
@@ -291,9 +294,9 @@ fun ReusableZapButton(
val displayText = val displayText =
when { when {
hasZapped -> config.thankYouText ?: stringRes(id = R.string.thank_you) hasZapped -> config.thankYouText ?: stringRes(id = Res.string.thank_you)
config.buttonText != null -> config.buttonText config.buttonText != null -> config.buttonText
else -> stringRes(id = R.string.donate_now) else -> stringRes(id = Res.string.donate_now)
} }
Text(text = displayText) Text(text = displayText)
@@ -58,10 +58,14 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.imageLoader import coil3.imageLoader
import coil3.request.ImageRequest import coil3.request.ImageRequest
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.content_warning
import com.vitorpamplona.amethyst.commons.resources.content_warning_explanation
import com.vitorpamplona.amethyst.commons.resources.content_warning_with_reason
import com.vitorpamplona.amethyst.commons.resources.show_anyway
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -283,7 +287,7 @@ private fun ContentWarningOverlayBody(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Visibility, symbol = MaterialSymbols.Visibility,
contentDescription = stringRes(R.string.content_warning), contentDescription = stringRes(Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(70.dp) .size(70.dp)
@@ -292,7 +296,7 @@ private fun ContentWarningOverlayBody(
) )
Icon( Icon(
symbol = MaterialSymbols.Warning, symbol = MaterialSymbols.Warning,
contentDescription = stringRes(R.string.content_warning), contentDescription = stringRes(Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(30.dp) .size(30.dp)
@@ -302,7 +306,7 @@ private fun ContentWarningOverlayBody(
} }
Text( Text(
text = stringRes(R.string.content_warning), text = stringRes(Res.string.content_warning),
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 18.sp, fontSize = 18.sp,
color = Color.White, color = Color.White,
@@ -344,7 +348,7 @@ private fun ContentWarningOverlayBody(
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text( Text(
text = stringRes(R.string.show_anyway), text = stringRes(Res.string.show_anyway),
) )
} }
} }
@@ -367,7 +371,7 @@ fun ContentWarningNote(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Visibility, symbol = MaterialSymbols.Visibility,
contentDescription = stringRes(R.string.content_warning), contentDescription = stringRes(Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(70.dp) .size(70.dp)
@@ -376,7 +380,7 @@ fun ContentWarningNote(
) )
Icon( Icon(
symbol = MaterialSymbols.Warning, symbol = MaterialSymbols.Warning,
contentDescription = stringRes(R.string.content_warning), contentDescription = stringRes(Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(30.dp) .size(30.dp)
@@ -390,9 +394,9 @@ fun ContentWarningNote(
Text( Text(
text = text =
if (reason.isNullOrBlank()) { if (reason.isNullOrBlank()) {
stringRes(R.string.content_warning) stringRes(Res.string.content_warning)
} else { } else {
stringRes(R.string.content_warning_with_reason, reason) stringRes(Res.string.content_warning_with_reason, reason)
}, },
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 18.sp, fontSize = 18.sp,
@@ -404,7 +408,7 @@ fun ContentWarningNote(
if (reason.isNullOrBlank()) { if (reason.isNullOrBlank()) {
Row { Row {
Text( Text(
text = stringRes(R.string.content_warning_explanation), text = stringRes(Res.string.content_warning_explanation),
color = Color.Gray, color = Color.Gray,
modifier = Modifier.padding(top = 10.dp), modifier = Modifier.padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@@ -420,7 +424,7 @@ fun ContentWarningNote(
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text( Text(
text = stringRes(R.string.show_anyway), text = stringRes(Res.string.show_anyway),
) )
} }
} }
@@ -57,7 +57,9 @@ import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.open_dropdown_menu
import com.vitorpamplona.amethyst.commons.resources.option_of
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Font14SP import com.vitorpamplona.amethyst.ui.theme.Font14SP
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -124,7 +126,7 @@ private fun BaseTextSpinner(
"Dropdown menu, $currentText selected" "Dropdown menu, $currentText selected"
} }
val openDropdownLabel = stringRes(R.string.open_dropdown_menu) val openDropdownLabel = stringRes(Res.string.open_dropdown_menu)
Box( Box(
modifier = modifier, modifier = modifier,
@@ -225,7 +227,7 @@ fun <T> SpinnerSelectionDialog(
} }
} }
itemsIndexed(options) { index, item -> itemsIndexed(options) { index, item ->
val optionsOfLabel = stringRes(R.string.option_of, index + 1, options.size) val optionsOfLabel = stringRes(Res.string.option_of, index + 1, options.size)
Row( Row(
modifier = modifier =
Modifier Modifier
@@ -44,6 +44,10 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.preview.UrlInfoItem import com.vitorpamplona.amethyst.commons.preview.UrlInfoItem
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.copy_url_to_clipboard
import com.vitorpamplona.amethyst.commons.resources.link_actions_dialog_title
import com.vitorpamplona.amethyst.commons.resources.url_preview_open_in_browser
import com.vitorpamplona.amethyst.ui.components.util.setText import com.vitorpamplona.amethyst.ui.components.util.setText
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
@@ -71,13 +75,13 @@ fun UrlPreviewCard(
val clipboardManager = LocalClipboard.current val clipboardManager = LocalClipboard.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
M3ActionDialog( M3ActionDialog(
title = stringRes(R.string.link_actions_dialog_title), title = stringRes(Res.string.link_actions_dialog_title),
onDismiss = { popupExpanded.value = false }, onDismiss = { popupExpanded.value = false },
) { ) {
M3ActionSection { M3ActionSection {
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.ContentCopy, icon = MaterialSymbols.ContentCopy,
text = stringRes(R.string.copy_url_to_clipboard), text = stringRes(Res.string.copy_url_to_clipboard),
) { ) {
scope.launch { scope.launch {
clipboardManager.setText(url) clipboardManager.setText(url)
@@ -141,7 +145,7 @@ fun UrlPreviewCard(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.AutoMirrored.OpenInNew, symbol = MaterialSymbols.AutoMirrored.OpenInNew,
contentDescription = stringRes(R.string.url_preview_open_in_browser), contentDescription = stringRes(Res.string.url_preview_open_in_browser),
modifier = Size14Modifier, modifier = Size14Modifier,
tint = Color.Gray, tint = Color.Gray,
) )
@@ -79,6 +79,13 @@ import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_media_to_gallery
import com.vitorpamplona.amethyst.commons.resources.copy_the_note_id_to_the_clipboard
import com.vitorpamplona.amethyst.commons.resources.copy_url_to_clipboard
import com.vitorpamplona.amethyst.commons.resources.media_actions_dialog_title
import com.vitorpamplona.amethyst.commons.resources.share_image
import com.vitorpamplona.amethyst.commons.resources.share_video
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalImage import com.vitorpamplona.amethyst.commons.richtext.MediaLocalImage
import com.vitorpamplona.amethyst.commons.richtext.MediaLocalVideo import com.vitorpamplona.amethyst.commons.richtext.MediaLocalVideo
@@ -967,7 +974,7 @@ fun ShareMediaAction(
if (popupExpanded.value) { if (popupExpanded.value) {
M3ActionDialog( M3ActionDialog(
title = stringRes(R.string.media_actions_dialog_title), title = stringRes(Res.string.media_actions_dialog_title),
onDismiss = { if (!isDownloadingVideo.value) onDismiss() }, onDismiss = { if (!isDownloadingVideo.value) onDismiss() },
) { ) {
val clipboardManager = LocalClipboard.current val clipboardManager = LocalClipboard.current
@@ -977,7 +984,7 @@ fun ShareMediaAction(
if ((videoUri != null && !videoUri.startsWith("file")) || postNostrUri != null) { if ((videoUri != null && !videoUri.startsWith("file")) || postNostrUri != null) {
M3ActionSection { M3ActionSection {
if (videoUri != null && !videoUri.startsWith("file")) { if (videoUri != null && !videoUri.startsWith("file")) {
M3ActionRow(icon = MaterialSymbols.Link, text = stringRes(R.string.copy_url_to_clipboard)) { M3ActionRow(icon = MaterialSymbols.Link, text = stringRes(Res.string.copy_url_to_clipboard)) {
scope.launch { scope.launch {
clipboardManager.setText(videoUri) clipboardManager.setText(videoUri)
} }
@@ -1000,13 +1007,13 @@ fun ShareMediaAction(
} }
} }
postNostrUri?.let { postNostrUri?.let {
M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(R.string.copy_the_note_id_to_the_clipboard)) { M3ActionRow(icon = MaterialSymbols.ContentCopy, text = stringRes(Res.string.copy_the_note_id_to_the_clipboard)) {
scope.launch { scope.launch {
clipboardManager.setText(it) clipboardManager.setText(it)
} }
onDismiss() onDismiss()
} }
M3ActionRow(icon = MaterialSymbols.Collections, text = stringRes(R.string.add_media_to_gallery)) { M3ActionRow(icon = MaterialSymbols.Collections, text = stringRes(Res.string.add_media_to_gallery)) {
if (videoUri != null) { if (videoUri != null) {
val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent
if (n19 != null) { if (n19 != null) {
@@ -1036,7 +1043,7 @@ fun ShareMediaAction(
is MediaUrlImage -> { is MediaUrlImage -> {
videoUri?.let { videoUri?.let {
if (videoUri.isNotEmpty()) { if (videoUri.isNotEmpty()) {
M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(R.string.share_image)) { M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(Res.string.share_image)) {
accountViewModel.viewModelScope.launch { shareImageFile(context, videoUri, mimeType) } accountViewModel.viewModelScope.launch { shareImageFile(context, videoUri, mimeType) }
onDismiss() onDismiss()
} }
@@ -1049,7 +1056,7 @@ fun ShareMediaAction(
if (videoUri.isNotEmpty()) { if (videoUri.isNotEmpty()) {
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.Share, icon = MaterialSymbols.Share,
text = stringRes(R.string.share_video), text = stringRes(Res.string.share_video),
enabled = !isDownloadingVideo.value, enabled = !isDownloadingVideo.value,
) { ) {
isDownloadingVideo.value = true isDownloadingVideo.value = true
@@ -1078,7 +1085,7 @@ fun ShareMediaAction(
is MediaLocalVideo -> { is MediaLocalVideo -> {
content.localFile?.let { localFile -> content.localFile?.let { localFile ->
M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(R.string.share_video)) { M3ActionRow(icon = MaterialSymbols.Share, text = stringRes(Res.string.share_video)) {
accountViewModel.viewModelScope.launch { shareLocalVideoFile(context, localFile, mimeType) } accountViewModel.viewModelScope.launch { shareLocalVideoFile(context, localFile, mimeType) }
onDismiss() onDismiss()
} }
@@ -43,6 +43,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_dialog_talk_to_user
import com.vitorpamplona.amethyst.commons.resources.error_dialog_talk_to_user_name
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -136,8 +139,8 @@ fun ErrorRow(
) { ) {
val descriptor = val descriptor =
it.metadataOrNull()?.flow?.value?.info?.bestName()?.let { it.metadataOrNull()?.flow?.value?.info?.bestName()?.let {
stringRes(R.string.error_dialog_talk_to_user_name, it) stringRes(Res.string.error_dialog_talk_to_user_name, it)
} ?: stringRes(R.string.error_dialog_talk_to_user) } ?: stringRes(Res.string.error_dialog_talk_to_user)
Icon( Icon(
painter = painterRes(R.drawable.ic_dm, 2), painter = painterRes(R.drawable.ic_dm, 2),
@@ -31,6 +31,8 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_dialog_button_ok
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -98,7 +100,7 @@ fun MultiUserErrorMessageDialog(
contentDescription = null, contentDescription = null,
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_button_ok)) Text(stringRes(Res.string.error_dialog_button_ok))
} }
}, },
) )
@@ -29,7 +29,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.feed_is_empty
import com.vitorpamplona.amethyst.commons.resources.refresh
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
@@ -40,8 +42,8 @@ fun FeedEmpty(onRefresh: () -> Unit) {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text(stringRes(R.string.feed_is_empty)) Text(stringRes(Res.string.feed_is_empty))
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) } OutlinedButton(onClick = onRefresh) { Text(text = stringRes(Res.string.refresh)) }
} }
} }
@@ -30,7 +30,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_loading_replies
import com.vitorpamplona.amethyst.commons.resources.try_again
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
@@ -44,13 +46,13 @@ fun FeedError(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text("${stringRes(R.string.error_loading_replies)} $errorMessage") Text("${stringRes(Res.string.error_loading_replies)} $errorMessage")
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
Button( Button(
modifier = Modifier.align(Alignment.CenterHorizontally), modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = onRefresh, onClick = onRefresh,
) { ) {
Text(text = stringRes(R.string.try_again)) Text(text = stringRes(Res.string.try_again))
} }
} }
} }
@@ -28,7 +28,8 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.loading_feed
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@Composable @Composable
@@ -38,6 +39,6 @@ fun LoadingFeed() {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text(stringRes(R.string.loading_feed)) Text(stringRes(Res.string.loading_feed))
} }
} }
@@ -29,7 +29,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.unblock_user
import com.vitorpamplona.amethyst.commons.resources.user_is_blocked_hidden
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
@@ -40,8 +42,8 @@ fun UserBlockedFeed(onUnblock: () -> Unit) {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text(stringRes(R.string.user_is_blocked_hidden)) Text(stringRes(Res.string.user_is_blocked_hidden))
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
OutlinedButton(onClick = onUnblock) { Text(text = stringRes(R.string.unblock_user)) } OutlinedButton(onClick = onUnblock) { Text(text = stringRes(Res.string.unblock_user)) }
} }
} }
@@ -59,6 +59,13 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.account_switch_active_account
import com.vitorpamplona.amethyst.commons.resources.account_switch_add_account_btn
import com.vitorpamplona.amethyst.commons.resources.account_switch_select_account
import com.vitorpamplona.amethyst.commons.resources.are_you_sure_you_want_to_log_out
import com.vitorpamplona.amethyst.commons.resources.log_out
import com.vitorpamplona.amethyst.commons.resources.profile_image
import com.vitorpamplona.amethyst.commons.scheduledposts.ScheduledPostStatus import com.vitorpamplona.amethyst.commons.scheduledposts.ScheduledPostStatus
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
@@ -95,7 +102,7 @@ fun AccountSwitchBottomSheet(
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text(stringRes(R.string.account_switch_select_account), fontWeight = FontWeight.Bold) Text(stringRes(Res.string.account_switch_select_account), fontWeight = FontWeight.Bold)
} }
DisplayAllAccounts(accountViewModel, accountSessionManager) DisplayAllAccounts(accountViewModel, accountSessionManager)
Row( Row(
@@ -107,7 +114,7 @@ fun AccountSwitchBottomSheet(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
TextButton(onClick = { popupExpanded = true }) { TextButton(onClick = { popupExpanded = true }) {
Text(stringRes(R.string.account_switch_add_account_btn)) Text(stringRes(Res.string.account_switch_add_account_btn))
} }
} }
} }
@@ -209,7 +216,7 @@ private fun ActiveMarker(
if (isCurrentUser) { if (isCurrentUser) {
Icon( Icon(
symbol = MaterialSymbols.RadioButtonChecked, symbol = MaterialSymbols.RadioButtonChecked,
contentDescription = stringRes(R.string.account_switch_active_account), contentDescription = stringRes(Res.string.account_switch_active_account),
tint = MaterialTheme.colorScheme.secondary, tint = MaterialTheme.colorScheme.secondary,
) )
} }
@@ -225,7 +232,7 @@ private fun AccountPicture(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = user.pubkeyHex, robot = user.pubkeyHex,
model = userInfo?.info?.profilePicture(), model = userInfo?.info?.profilePicture(),
contentDescription = stringRes(R.string.profile_image), contentDescription = stringRes(Res.string.profile_image),
modifier = AccountPictureModifier, modifier = AccountPictureModifier,
loadProfilePicture = accountViewModel.settings.showProfilePictures(), loadProfilePicture = accountViewModel.settings.showProfilePictures(),
loadRobohash = accountViewModel.settings.isNotPerformanceMode(), loadRobohash = accountViewModel.settings.isNotPerformanceMode(),
@@ -288,7 +295,7 @@ private fun LogoutButton(
} }
} }
AlertDialog( AlertDialog(
title = { Text(text = stringRes(R.string.log_out)) }, title = { Text(text = stringRes(Res.string.log_out)) },
text = { text = {
if (unpublishedCount > 0) { if (unpublishedCount > 0) {
Text( Text(
@@ -300,7 +307,7 @@ private fun LogoutButton(
), ),
) )
} else { } else {
Text(text = stringRes(R.string.are_you_sure_you_want_to_log_out)) Text(text = stringRes(Res.string.are_you_sure_you_want_to_log_out))
} }
}, },
onDismissRequest = { logoutDialog = false }, onDismissRequest = { logoutDialog = false },
@@ -332,7 +339,7 @@ private fun LogoutButton(
.show() .show()
}, },
) { ) {
Text(text = stringRes(R.string.log_out)) Text(text = stringRes(Res.string.log_out))
} }
}, },
dismissButton = { dismissButton = {
@@ -350,7 +357,7 @@ private fun LogoutButton(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.AutoMirrored.Logout, symbol = MaterialSymbols.AutoMirrored.Logout,
contentDescription = stringRes(R.string.log_out), contentDescription = stringRes(Res.string.log_out),
tint = MaterialTheme.colorScheme.onSurface, tint = MaterialTheme.colorScheme.onSurface,
) )
} }
@@ -96,7 +96,12 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.followers
import com.vitorpamplona.amethyst.commons.resources.following
import com.vitorpamplona.amethyst.commons.resources.profile_banner import com.vitorpamplona.amethyst.commons.resources.profile_banner
import com.vitorpamplona.amethyst.commons.resources.profile_image
import com.vitorpamplona.amethyst.commons.resources.show_npub_as_a_qr_code
import com.vitorpamplona.amethyst.commons.resources.status_update
import com.vitorpamplona.amethyst.commons.scheduledposts.ScheduledPostStatus import com.vitorpamplona.amethyst.commons.scheduledposts.ScheduledPostStatus
import com.vitorpamplona.amethyst.isDebug import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
@@ -272,7 +277,7 @@ fun ProfileContentTemplate(
if (profileBanner != null) { if (profileBanner != null) {
AsyncImage( AsyncImage(
model = profileBanner, model = profileBanner,
contentDescription = stringRes(id = R.string.profile_image), contentDescription = stringRes(id = Res.string.profile_image),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = bannerModifier, modifier = bannerModifier,
) )
@@ -289,7 +294,7 @@ fun ProfileContentTemplate(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = profilePubHex, robot = profilePubHex,
model = profilePicture, model = profilePicture,
contentDescription = stringRes(id = R.string.profile_image), contentDescription = stringRes(id = Res.string.profile_image),
modifier = modifier =
Modifier Modifier
.width(100.dp) .width(100.dp)
@@ -388,7 +393,7 @@ fun FakeEditBar(
contentAlignment = Alignment.CenterStart, contentAlignment = Alignment.CenterStart,
) { ) {
Text( Text(
text = savedStatus?.ifEmpty { null } ?: stringRes(R.string.status_update), text = savedStatus?.ifEmpty { null } ?: stringRes(Res.string.status_update),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = color =
if (savedStatus?.ifEmpty { null } == null) { if (savedStatus?.ifEmpty { null } == null) {
@@ -401,7 +406,7 @@ fun FakeEditBar(
// Floating label — sits on top of the border like Material does // Floating label — sits on top of the border like Material does
Text( Text(
text = stringRes(R.string.status_update), text = stringRes(Res.string.status_update),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = modifier =
@@ -442,11 +447,11 @@ fun StatusEditBar(
OutlinedTextField( OutlinedTextField(
value = currentStatus.value, value = currentStatus.value,
onValueChange = { currentStatus.value = it }, onValueChange = { currentStatus.value = it },
label = { Text(text = stringRes(R.string.status_update)) }, label = { Text(text = stringRes(Res.string.status_update)) },
modifier = Modifier.fillMaxWidth().focusRequester(focusRequester), modifier = Modifier.fillMaxWidth().focusRequester(focusRequester),
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.status_update), text = stringRes(Res.string.status_update),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -543,13 +548,13 @@ private fun FollowingAndFollowerCounts(
) { ) {
DisplayFollowingCount(baseAccountUser) DisplayFollowingCount(baseAccountUser)
Text(stringRes(R.string.following)) Text(stringRes(Res.string.following))
Spacer(modifier = DoubleHorzSpacer) Spacer(modifier = DoubleHorzSpacer)
DisplayFollowerCount(baseAccountUser, accountViewModel) DisplayFollowerCount(baseAccountUser, accountViewModel)
Text(stringRes(R.string.followers)) Text(stringRes(Res.string.followers))
} }
} }
@@ -1074,7 +1079,7 @@ fun BottomContent(
) { ) {
Icon( Icon(
painter = painterRes(R.drawable.ic_qrcode, 2), painter = painterRes(R.drawable.ic_qrcode, 2),
contentDescription = stringRes(id = R.string.show_npub_as_a_qr_code), contentDescription = stringRes(id = Res.string.show_npub_as_a_qr_code),
modifier = Size24Modifier, modifier = Size24Modifier,
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
) )
@@ -70,6 +70,13 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.topNavFeeds.TopFilter import com.vitorpamplona.amethyst.commons.model.topNavFeeds.TopFilter
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.feed_filter_select_an_option
import com.vitorpamplona.amethyst.commons.resources.feed_filter_selected
import com.vitorpamplona.amethyst.commons.resources.lack_location_permissions
import com.vitorpamplona.amethyst.commons.resources.loading_location
import com.vitorpamplona.amethyst.commons.resources.open_dropdown_menu
import com.vitorpamplona.amethyst.commons.resources.select_an_option
import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation
import com.vitorpamplona.amethyst.service.location.LocationState import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
@@ -109,7 +116,7 @@ fun FeedFilterSpinner(
var optionsShowing by remember { mutableStateOf(false) } var optionsShowing by remember { mutableStateOf(false) }
val context = LocalContext.current val context = LocalContext.current
val selectAnOption = stringRes(id = R.string.select_an_option) val selectAnOption = stringRes(id = Res.string.select_an_option)
val selected = val selected =
remember(placeholderCode, options) { remember(placeholderCode, options) {
@@ -125,12 +132,12 @@ fun FeedFilterSpinner(
val accessibilityDescription = val accessibilityDescription =
if (selected != null) { if (selected != null) {
stringRes(R.string.feed_filter_selected, currentText) stringRes(Res.string.feed_filter_selected, currentText)
} else { } else {
stringRes(R.string.feed_filter_select_an_option, selectAnOption) stringRes(Res.string.feed_filter_select_an_option, selectAnOption)
} }
val openDropdownLabel = stringRes(R.string.open_dropdown_menu) val openDropdownLabel = stringRes(Res.string.open_dropdown_menu)
val filter = selected?.code ?: placeholderCode val filter = selected?.code ?: placeholderCode
@@ -183,7 +190,7 @@ fun FeedFilterSpinner(
LaunchedEffect(locationPermissionState) { locationPermissionState.launchPermissionRequest() } LaunchedEffect(locationPermissionState) { locationPermissionState.launchPermissionRequest() }
Text( Text(
text = stringRes(R.string.lack_location_permissions), text = stringRes(Res.string.lack_location_permissions),
fontSize = Font12SP, fontSize = Font12SP,
lineHeight = 12.sp, lineHeight = 12.sp,
maxLines = 1, maxLines = 1,
@@ -223,7 +230,7 @@ fun FeedFilterSpinner(
LocationState.LocationResult.LackPermission -> { LocationState.LocationResult.LackPermission -> {
Text( Text(
text = stringRes(R.string.lack_location_permissions), text = stringRes(Res.string.lack_location_permissions),
fontSize = Font12SP, fontSize = Font12SP,
lineHeight = 12.sp, lineHeight = 12.sp,
maxLines = 1, maxLines = 1,
@@ -233,7 +240,7 @@ fun FeedFilterSpinner(
LocationState.LocationResult.Loading -> { LocationState.LocationResult.Loading -> {
Text( Text(
text = stringRes(R.string.loading_location), text = stringRes(Res.string.loading_location),
fontSize = Font12SP, fontSize = Font12SP,
lineHeight = 12.sp, lineHeight = 12.sp,
maxLines = 1, maxLines = 1,
@@ -41,9 +41,11 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.clear
import com.vitorpamplona.amethyst.commons.resources.settings_search_placeholder
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -135,7 +137,7 @@ private fun CompactSettingsSearchField(
) { ) {
if (query.isEmpty()) { if (query.isEmpty()) {
Text( Text(
text = stringRes(R.string.settings_search_placeholder), text = stringRes(Res.string.settings_search_placeholder),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
color = colorScheme.onSurfaceVariant, color = colorScheme.onSurfaceVariant,
maxLines = 1, maxLines = 1,
@@ -148,7 +150,7 @@ private fun CompactSettingsSearchField(
IconButton(onClick = onClear) { IconButton(onClick = onClear) {
Icon( Icon(
symbol = MaterialSymbols.Close, symbol = MaterialSymbols.Close,
contentDescription = stringRes(R.string.clear), contentDescription = stringRes(Res.string.clear),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = LocalContentColor.current, tint = LocalContentColor.current,
) )
@@ -32,7 +32,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.your_profile_image
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserPicture import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserPicture
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.layouts.LocalScreenLayout import com.vitorpamplona.amethyst.ui.layouts.LocalScreenLayout
@@ -103,7 +104,7 @@ internal fun LoggedInUserPictureDrawer(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = accountViewModel.userProfile().pubkeyHex, robot = accountViewModel.userProfile().pubkeyHex,
model = profilePicture, model = profilePicture,
contentDescription = stringRes(id = R.string.your_profile_image), contentDescription = stringRes(id = Res.string.your_profile_image),
modifier = HeaderPictureModifier, modifier = HeaderPictureModifier,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
loadProfilePicture = accountViewModel.settings.showProfilePictures(), loadProfilePicture = accountViewModel.settings.showProfilePictures(),
@@ -34,10 +34,11 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.accepted_by_relays
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -118,7 +119,7 @@ internal fun RenderAcceptedByRelaysGallery(
Box(modifier = NotificationIconModifier) { Box(modifier = NotificationIconModifier) {
Icon( Icon(
symbol = MaterialSymbols.Dns, symbol = MaterialSymbols.Dns,
contentDescription = stringRes(id = R.string.accepted_by_relays), contentDescription = stringRes(id = Res.string.accepted_by_relays),
modifier = Modifier.size(Size20dp).align(Alignment.TopEnd), modifier = Modifier.size(Size20dp).align(Alignment.TopEnd),
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -38,9 +38,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.new_badge_award_notif
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
@@ -112,7 +113,7 @@ fun BadgeCompose(
Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) { Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) {
Row { Row {
Text( Text(
stringRes(R.string.new_badge_award_notif), stringRes(Res.string.new_badge_award_notif),
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
modifier = Modifier.padding(bottom = 5.dp).weight(1f), modifier = Modifier.padding(bottom = 5.dp).weight(1f),
) )
@@ -38,6 +38,12 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.post_not_found
import com.vitorpamplona.amethyst.commons.resources.post_not_found_short
import com.vitorpamplona.amethyst.commons.resources.post_was_flagged_as_inappropriate_by
import com.vitorpamplona.amethyst.commons.resources.post_was_hidden
import com.vitorpamplona.amethyst.commons.resources.show_anyway
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -78,9 +84,9 @@ fun BlankNote(
Text( Text(
text = text =
if (shortPreview) { if (shortPreview) {
stringRes(R.string.post_not_found_short) stringRes(Res.string.post_not_found_short)
} else { } else {
stringRes(R.string.post_not_found) stringRes(Res.string.post_not_found)
}, },
modifier = Modifier.padding(30.dp), modifier = Modifier.padding(30.dp),
color = Color.Gray, color = Color.Gray,
@@ -157,7 +163,7 @@ fun HiddenNote(
if (hasReporters || !hasExcessiveHashtags) { if (hasReporters || !hasExcessiveHashtags) {
Text( Text(
text = stringRes(R.string.post_was_flagged_as_inappropriate_by), text = stringRes(Res.string.post_was_flagged_as_inappropriate_by),
color = Color.Gray, color = Color.Gray,
modifier = modifier =
if (hasExcessiveHashtags) { if (hasExcessiveHashtags) {
@@ -192,7 +198,7 @@ fun HiddenNote(
shape = ButtonBorder, shape = ButtonBorder,
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text(text = stringRes(R.string.show_anyway)) Text(text = stringRes(Res.string.show_anyway))
} }
} }
} }
@@ -223,7 +229,7 @@ fun HiddenNoteByMe(
modifier = Modifier.padding(30.dp), modifier = Modifier.padding(30.dp),
) { ) {
Text( Text(
text = stringRes(R.string.post_was_hidden), text = stringRes(Res.string.post_was_hidden),
color = Color.Gray, color = Color.Gray,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
@@ -234,7 +240,7 @@ fun HiddenNoteByMe(
shape = ButtonBorder, shape = ButtonBorder,
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text(text = stringRes(R.string.show_anyway)) Text(text = stringRes(Res.string.show_anyway))
} }
} }
} }
@@ -26,9 +26,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.LocalClipboard
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.copy_text
import com.vitorpamplona.amethyst.commons.resources.copy_text_original
import com.vitorpamplona.amethyst.commons.resources.copy_text_translated
import com.vitorpamplona.amethyst.ui.components.M3ActionDialog import com.vitorpamplona.amethyst.ui.components.M3ActionDialog
import com.vitorpamplona.amethyst.ui.components.M3ActionRow import com.vitorpamplona.amethyst.ui.components.M3ActionRow
import com.vitorpamplona.amethyst.ui.components.M3ActionSection import com.vitorpamplona.amethyst.ui.components.M3ActionSection
@@ -128,18 +131,18 @@ fun CopyTextChooserDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
M3ActionDialog( M3ActionDialog(
title = stringRes(R.string.copy_text), title = stringRes(Res.string.copy_text),
onDismiss = onDismiss, onDismiss = onDismiss,
) { ) {
M3ActionSection { M3ActionSection {
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.ContentCopy, icon = MaterialSymbols.ContentCopy,
text = stringRes(R.string.copy_text_original), text = stringRes(Res.string.copy_text_original),
onClick = onCopyOriginal, onClick = onCopyOriginal,
) )
M3ActionRow( M3ActionRow(
icon = MaterialSymbols.Translate, icon = MaterialSymbols.Translate,
text = stringRes(R.string.copy_text_translated), text = stringRes(Res.string.copy_text_translated),
onClick = onCopyTranslated, onClick = onCopyTranslated,
) )
} }
@@ -42,6 +42,9 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.error_dialog_button_ok
import com.vitorpamplona.amethyst.commons.resources.error_dialog_talk_to_user
import com.vitorpamplona.amethyst.ui.painterRes import com.vitorpamplona.amethyst.ui.painterRes
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size16dp import com.vitorpamplona.amethyst.ui.theme.Size16dp
@@ -85,7 +88,7 @@ fun ErrorMessageDialog(
contentDescription = null, contentDescription = null,
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_talk_to_user)) Text(stringRes(Res.string.error_dialog_talk_to_user))
} }
} }
Button( Button(
@@ -101,7 +104,7 @@ fun ErrorMessageDialog(
contentDescription = null, contentDescription = null,
) )
Spacer(StdHorzSpacer) Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_button_ok)) Text(stringRes(Res.string.error_dialog_button_ok))
} }
} }
} }
@@ -45,6 +45,25 @@ import com.vitorpamplona.amethyst.commons.icons.Zap
import com.vitorpamplona.amethyst.commons.icons.following import com.vitorpamplona.amethyst.commons.icons.following
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.accessibility_download_for_offline
import com.vitorpamplona.amethyst.commons.resources.accessibility_play_username
import com.vitorpamplona.amethyst.commons.resources.accessibility_pushpin
import com.vitorpamplona.amethyst.commons.resources.app_logo
import com.vitorpamplona.amethyst.commons.resources.boost_or_quote_description
import com.vitorpamplona.amethyst.commons.resources.change_reaction
import com.vitorpamplona.amethyst.commons.resources.clear
import com.vitorpamplona.amethyst.commons.resources.enter_picture_in_picture
import com.vitorpamplona.amethyst.commons.resources.following
import com.vitorpamplona.amethyst.commons.resources.lightning_address
import com.vitorpamplona.amethyst.commons.resources.like_description
import com.vitorpamplona.amethyst.commons.resources.note_options
import com.vitorpamplona.amethyst.commons.resources.onchain_zap_description
import com.vitorpamplona.amethyst.commons.resources.onchain_zap_pending
import com.vitorpamplona.amethyst.commons.resources.record_a_message
import com.vitorpamplona.amethyst.commons.resources.reply_description
import com.vitorpamplona.amethyst.commons.resources.search_button
import com.vitorpamplona.amethyst.commons.resources.website
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
import com.vitorpamplona.amethyst.ui.theme.Size19Modifier import com.vitorpamplona.amethyst.ui.theme.Size19Modifier
@@ -59,7 +78,7 @@ import com.vitorpamplona.amethyst.ui.theme.subtleButton
fun AmethystIcon(iconSize: Dp) { fun AmethystIcon(iconSize: Dp) {
Icon( Icon(
imageVector = CustomHashTagIcons.Amethyst, imageVector = CustomHashTagIcons.Amethyst,
contentDescription = stringRes(id = R.string.app_logo), contentDescription = stringRes(id = Res.string.app_logo),
modifier = Modifier.size(iconSize), modifier = Modifier.size(iconSize),
tint = Color.Unspecified, tint = Color.Unspecified,
) )
@@ -76,7 +95,7 @@ fun FollowingIcon(modifier: Modifier) {
val icon = remember(shield) { following(shield, Color.White) } val icon = remember(shield) { following(shield, Color.White) }
Icon( Icon(
imageVector = icon, imageVector = icon,
contentDescription = stringRes(id = R.string.following), contentDescription = stringRes(id = Res.string.following),
modifier = modifier, modifier = modifier,
tint = Color.Unspecified, tint = Color.Unspecified,
) )
@@ -98,7 +117,7 @@ fun DownloadForOfflineIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.DownloadForOffline, symbol = MaterialSymbols.DownloadForOffline,
contentDescription = stringRes(id = R.string.accessibility_download_for_offline), contentDescription = stringRes(id = Res.string.accessibility_download_for_offline),
modifier = remember(iconSize) { Modifier.size(iconSize) }, modifier = remember(iconSize) { Modifier.size(iconSize) },
tint = tint, tint = tint,
) )
@@ -111,7 +130,7 @@ fun LikedIcon(
) { ) {
Icon( Icon(
imageVector = Liked, imageVector = Liked,
contentDescription = stringRes(id = R.string.like_description), contentDescription = stringRes(id = Res.string.like_description),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -124,7 +143,7 @@ fun ChangeReactionIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.AddReaction, symbol = MaterialSymbols.AddReaction,
contentDescription = stringRes(id = R.string.change_reaction), contentDescription = stringRes(id = Res.string.change_reaction),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -137,7 +156,7 @@ fun LikeIcon(
) { ) {
Icon( Icon(
imageVector = Like, imageVector = Like,
contentDescription = stringRes(id = R.string.like_description), contentDescription = stringRes(id = Res.string.like_description),
modifier = iconSizeModifier, modifier = iconSizeModifier,
tint = grayTint, tint = grayTint,
) )
@@ -150,7 +169,7 @@ fun RepostIcon(
) { ) {
Icon( Icon(
imageVector = Repost, imageVector = Repost,
contentDescription = stringRes(id = R.string.boost_or_quote_description), contentDescription = stringRes(id = Res.string.boost_or_quote_description),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -163,7 +182,7 @@ fun RepostedIcon(
) { ) {
Icon( Icon(
imageVector = Reposted, imageVector = Reposted,
contentDescription = stringRes(id = R.string.boost_or_quote_description), contentDescription = stringRes(id = Res.string.boost_or_quote_description),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -176,7 +195,7 @@ fun LightningAddressIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Bolt, symbol = MaterialSymbols.Bolt,
contentDescription = stringRes(R.string.lightning_address), contentDescription = stringRes(Res.string.lightning_address),
tint = tint, tint = tint,
modifier = modifier, modifier = modifier,
) )
@@ -307,7 +326,7 @@ fun VoiceReplyIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Mic, symbol = MaterialSymbols.Mic,
contentDescription = stringRes(id = R.string.record_a_message), contentDescription = stringRes(id = Res.string.record_a_message),
tint = tint, tint = tint,
modifier = iconSizeModifier, modifier = iconSizeModifier,
) )
@@ -320,7 +339,7 @@ fun CommentIcon(
) { ) {
Icon( Icon(
imageVector = Reply, imageVector = Reply,
contentDescription = stringRes(id = R.string.reply_description), contentDescription = stringRes(id = Res.string.reply_description),
modifier = iconSizeModifier, modifier = iconSizeModifier,
tint = tint, tint = tint,
) )
@@ -352,7 +371,7 @@ fun SearchIcon(
) { ) {
Icon( Icon(
imageVector = Search, imageVector = Search,
contentDescription = stringRes(id = R.string.search_button), contentDescription = stringRes(id = Res.string.search_button),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -365,7 +384,7 @@ fun PlayIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.PlayCircle, symbol = MaterialSymbols.PlayCircle,
contentDescription = stringRes(id = R.string.accessibility_play_username), contentDescription = stringRes(id = Res.string.accessibility_play_username),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -378,7 +397,7 @@ fun PinIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.PushPin, symbol = MaterialSymbols.PushPin,
contentDescription = stringRes(id = R.string.accessibility_pushpin), contentDescription = stringRes(id = Res.string.accessibility_pushpin),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -391,7 +410,7 @@ fun EnablePiP(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.AutoMirrored.OpenInNew, symbol = MaterialSymbols.AutoMirrored.OpenInNew,
contentDescription = stringRes(id = R.string.enter_picture_in_picture), contentDescription = stringRes(id = Res.string.enter_picture_in_picture),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -401,7 +420,7 @@ fun EnablePiP(
fun ClearTextIcon() { fun ClearTextIcon() {
Icon( Icon(
symbol = MaterialSymbols.Clear, symbol = MaterialSymbols.Clear,
contentDescription = stringRes(R.string.clear), contentDescription = stringRes(Res.string.clear),
) )
} }
@@ -412,7 +431,7 @@ fun LinkIcon(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Link, symbol = MaterialSymbols.Link,
contentDescription = stringRes(R.string.website), contentDescription = stringRes(Res.string.website),
modifier = modifier, modifier = modifier,
tint = tint, tint = tint,
) )
@@ -422,7 +441,7 @@ fun LinkIcon(
fun VerticalDotsIcon() { fun VerticalDotsIcon() {
Icon( Icon(
symbol = MaterialSymbols.MoreVert, symbol = MaterialSymbols.MoreVert,
contentDescription = stringRes(id = R.string.note_options), contentDescription = stringRes(id = Res.string.note_options),
modifier = Size19Modifier, modifier = Size19Modifier,
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -432,7 +451,7 @@ fun VerticalDotsIcon() {
fun OnchainZappedIcon(modifier: Modifier) { fun OnchainZappedIcon(modifier: Modifier) {
Icon( Icon(
symbol = MaterialSymbols.CurrencyBitcoin, symbol = MaterialSymbols.CurrencyBitcoin,
contentDescription = stringRes(R.string.onchain_zap_description), contentDescription = stringRes(Res.string.onchain_zap_description),
tint = BitcoinOrange, tint = BitcoinOrange,
modifier = modifier, modifier = modifier,
) )
@@ -442,7 +461,7 @@ fun OnchainZappedIcon(modifier: Modifier) {
fun PendingClockBadge(modifier: Modifier) { fun PendingClockBadge(modifier: Modifier) {
Icon( Icon(
symbol = MaterialSymbols.Schedule, symbol = MaterialSymbols.Schedule,
contentDescription = stringRes(R.string.onchain_zap_pending), contentDescription = stringRes(Res.string.onchain_zap_pending),
tint = BitcoinOrange, tint = BitcoinOrange,
modifier = modifier, modifier = modifier,
) )
@@ -64,7 +64,6 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties import androidx.compose.ui.window.PopupProperties
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder
import com.vitorpamplona.amethyst.commons.hashtags.Cashu import com.vitorpamplona.amethyst.commons.hashtags.Cashu
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
@@ -72,6 +71,9 @@ import com.vitorpamplona.amethyst.commons.model.EmptyTagList
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.NoteState import com.vitorpamplona.amethyst.commons.model.NoteState
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.nutzap
import com.vitorpamplona.amethyst.commons.resources.profile_image
import com.vitorpamplona.amethyst.commons.richtext.CachedRichTextParser import com.vitorpamplona.amethyst.commons.richtext.CachedRichTextParser
import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription
@@ -458,7 +460,7 @@ fun RenderNutzapGallery(
) { ) {
Icon( Icon(
imageVector = CustomHashTagIcons.Cashu, imageVector = CustomHashTagIcons.Cashu,
contentDescription = stringRes(R.string.nutzap), contentDescription = stringRes(Res.string.nutzap),
modifier = Modifier.size(Size20dp).align(Alignment.TopEnd), modifier = Modifier.size(Size20dp).align(Alignment.TopEnd),
// Tint the monochrome cashu outline brand orange so the nutzap // Tint the monochrome cashu outline brand orange so the nutzap
// gallery matches the lightning ZappedIcon in RenderZapGallery. // gallery matches the lightning ZappedIcon in RenderZapGallery.
@@ -795,7 +797,7 @@ fun WatchUserMetadataAndFollowsAndRenderUserProfilePicture(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = author.pubkeyHex, robot = author.pubkeyHex,
model = baseUserPicture, model = baseUserPicture,
contentDescription = stringRes(id = R.string.profile_image), contentDescription = stringRes(id = Res.string.profile_image),
modifier = MaterialTheme.colorScheme.profile35dpModifier, modifier = MaterialTheme.colorScheme.profile35dpModifier,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
loadProfilePicture = accountViewModel.settings.showProfilePictures(), loadProfilePicture = accountViewModel.settings.showProfilePictures(),
@@ -51,6 +51,10 @@ import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05State import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05State
import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05VerifState import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05VerifState
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.nip05_checking
import com.vitorpamplona.amethyst.commons.resources.nip05_failed
import com.vitorpamplona.amethyst.commons.resources.nip05_verified
import com.vitorpamplona.amethyst.commons.ui.components.ClickableTextPrimary import com.vitorpamplona.amethyst.commons.ui.components.ClickableTextPrimary
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderFilterAssemblerSubscription
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
@@ -469,7 +473,7 @@ fun RenderNIP05VerifiedSymbol(
// badge doesn't blank-flash before the first check fires. // badge doesn't blank-flash before the first check fires.
Icon( Icon(
symbol = MaterialSymbols.Downloading, symbol = MaterialSymbols.Downloading,
contentDescription = stringRes(id = R.string.nip05_checking), contentDescription = stringRes(id = Res.string.nip05_checking),
modifier = modifier, modifier = modifier,
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -478,7 +482,7 @@ fun RenderNIP05VerifiedSymbol(
is Nip05VerifState.Verified -> { is Nip05VerifState.Verified -> {
Icon( Icon(
painter = painterRes(R.drawable.nip_05, compositionSizeReference), painter = painterRes(R.drawable.nip_05, compositionSizeReference),
contentDescription = stringRes(id = R.string.nip05_verified), contentDescription = stringRes(id = Res.string.nip05_verified),
modifier = modifier, modifier = modifier,
tint = MaterialTheme.colorScheme.nip05, tint = MaterialTheme.colorScheme.nip05,
) )
@@ -489,7 +493,7 @@ fun RenderNIP05VerifiedSymbol(
// timing but look the same to the user — both mean "badge isn't showing". // timing but look the same to the user — both mean "badge isn't showing".
Icon( Icon(
symbol = MaterialSymbols.Report, symbol = MaterialSymbols.Report,
contentDescription = stringRes(id = R.string.nip05_failed), contentDescription = stringRes(id = Res.string.nip05_failed),
modifier = modifier, modifier = modifier,
tint = MaterialTheme.colorScheme.error, tint = MaterialTheme.colorScheme.error,
) )
@@ -64,6 +64,14 @@ import com.vitorpamplona.amethyst.commons.model.concord.ConcordChannel
import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel
import com.vitorpamplona.amethyst.commons.model.textNoteModifications import com.vitorpamplona.amethyst.commons.model.textNoteModifications
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.approve
import com.vitorpamplona.amethyst.commons.resources.draft
import com.vitorpamplona.amethyst.commons.resources.group_picture
import com.vitorpamplona.amethyst.commons.resources.jump_to_parent_reply
import com.vitorpamplona.amethyst.commons.resources.one_year_plus
import com.vitorpamplona.amethyst.commons.resources.pinned_notes
import com.vitorpamplona.amethyst.commons.resources.private_rumor_mark
import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable
import com.vitorpamplona.amethyst.commons.ui.note.HeaderPill import com.vitorpamplona.amethyst.commons.ui.note.HeaderPill
import com.vitorpamplona.amethyst.commons.ui.note.QuietMark import com.vitorpamplona.amethyst.commons.ui.note.QuietMark
@@ -857,7 +865,7 @@ fun RenderApproveButton(
accountViewModel.approveCommunityPost(post, community) accountViewModel.approveCommunityPost(post, community)
}, },
) { ) {
Text(stringRes(R.string.approve)) Text(stringRes(Res.string.approve))
} }
} }
@@ -1811,7 +1819,7 @@ fun DisplayExpiration(
// for the pill: clamp it. // for the pill: clamp it.
val text = val text =
if (expirationDate - TimeUtils.now() > TimeUtils.ONE_YEAR) { if (expirationDate - TimeUtils.now() > TimeUtils.ONE_YEAR) {
stringRes(R.string.one_year_plus) stringRes(Res.string.one_year_plus)
} else { } else {
timeAheadNoDot(expirationDate, context) timeAheadNoDot(expirationDate, context)
} }
@@ -1846,12 +1854,12 @@ fun DisplayOtsIfInOriginal(
@Composable @Composable
fun DisplayDraft() { fun DisplayDraft() {
QuietMark(text = stringRes(R.string.draft)) QuietMark(text = stringRes(Res.string.draft))
} }
@Composable @Composable
fun DisplayDraftChat() { fun DisplayDraftChat() {
QuietMark(text = stringRes(R.string.draft)) QuietMark(text = stringRes(Res.string.draft))
} }
@Composable @Composable
@@ -1980,7 +1988,7 @@ fun FirstUserInfoRow(
fun PinnedMark() { fun PinnedMark() {
QuietMark( QuietMark(
symbol = MaterialSymbols.PushPin, symbol = MaterialSymbols.PushPin,
contentDescription = stringRes(R.string.pinned_notes), contentDescription = stringRes(Res.string.pinned_notes),
) )
} }
@@ -1988,7 +1996,7 @@ fun PinnedMark() {
fun PrivateRumorMark(accountViewModel: AccountViewModel) { fun PrivateRumorMark(accountViewModel: AccountViewModel) {
QuietMark( QuietMark(
symbol = MaterialSymbols.Lock, symbol = MaterialSymbols.Lock,
contentDescription = stringRes(R.string.private_rumor_mark), contentDescription = stringRes(Res.string.private_rumor_mark),
onClick = { onClick = {
accountViewModel.toastManager.toast( accountViewModel.toastManager.toast(
R.string.private_rumor_info_title, R.string.private_rumor_info_title,
@@ -2020,7 +2028,7 @@ fun JumpToParentReplyButton(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.KeyboardArrowUp, symbol = MaterialSymbols.KeyboardArrowUp,
contentDescription = stringRes(R.string.jump_to_parent_reply), contentDescription = stringRes(Res.string.jump_to_parent_reply),
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -2152,7 +2160,7 @@ private fun ChannelNotePicture(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = baseChannel.idHex, robot = baseChannel.idHex,
model = model, model = model,
contentDescription = stringRes(R.string.group_picture), contentDescription = stringRes(Res.string.group_picture),
modifier = MaterialTheme.colorScheme.channelNotePictureModifier, modifier = MaterialTheme.colorScheme.channelNotePictureModifier,
loadProfilePicture = accountViewModel.settings.showProfilePictures(), loadProfilePicture = accountViewModel.settings.showProfilePictures(),
loadRobohash = accountViewModel.settings.isNotPerformanceMode(), loadRobohash = accountViewModel.settings.isNotPerformanceMode(),
@@ -71,6 +71,24 @@ import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.model.textNoteModifications import com.vitorpamplona.amethyst.commons.model.textNoteModifications
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.broadcast
import com.vitorpamplona.amethyst.commons.resources.concord_ban_user
import com.vitorpamplona.amethyst.commons.resources.concord_ban_user_body
import com.vitorpamplona.amethyst.commons.resources.concord_ban_user_title
import com.vitorpamplona.amethyst.commons.resources.edit_draft
import com.vitorpamplona.amethyst.commons.resources.quick_action_block
import com.vitorpamplona.amethyst.commons.resources.quick_action_block_dialog_btn
import com.vitorpamplona.amethyst.commons.resources.quick_action_copy_text
import com.vitorpamplona.amethyst.commons.resources.quick_action_copy_user_id
import com.vitorpamplona.amethyst.commons.resources.quick_action_delete_dialog_btn
import com.vitorpamplona.amethyst.commons.resources.quick_action_dont_show_again_button
import com.vitorpamplona.amethyst.commons.resources.quick_action_follow
import com.vitorpamplona.amethyst.commons.resources.quick_action_report
import com.vitorpamplona.amethyst.commons.resources.quick_action_request_deletion_alert_body
import com.vitorpamplona.amethyst.commons.resources.quick_action_request_deletion_alert_title
import com.vitorpamplona.amethyst.commons.resources.quick_action_unfollow
import com.vitorpamplona.amethyst.commons.resources.report_dialog_blocking_a_user
import com.vitorpamplona.amethyst.ui.components.util.setText import com.vitorpamplona.amethyst.ui.components.util.setText
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.routeEditDraftTo import com.vitorpamplona.amethyst.ui.navigation.routes.routeEditDraftTo
@@ -283,10 +301,10 @@ fun CardBody(
if (showConcordBanDialog.value) { if (showConcordBanDialog.value) {
QuickActionAlertDialogOneButton( QuickActionAlertDialogOneButton(
title = stringRes(R.string.concord_ban_user_title), title = stringRes(Res.string.concord_ban_user_title),
textContent = stringRes(R.string.concord_ban_user_body), textContent = stringRes(Res.string.concord_ban_user_body),
buttonIcon = MaterialSymbols.Gavel, buttonIcon = MaterialSymbols.Gavel,
buttonText = stringRes(R.string.concord_ban_user), buttonText = stringRes(Res.string.concord_ban_user),
buttonColors = buttonColors =
ButtonDefaults.buttonColors( ButtonDefaults.buttonColors(
containerColor = LightRedColor, containerColor = LightRedColor,
@@ -323,14 +341,14 @@ fun CardBody(
Row(modifier = Modifier.height(IntrinsicSize.Min)) { Row(modifier = Modifier.height(IntrinsicSize.Min)) {
NoteQuickActionItem( NoteQuickActionItem(
icon = MaterialSymbols.ContentCopy, icon = MaterialSymbols.ContentCopy,
label = stringRes(R.string.quick_action_copy_text), label = stringRes(Res.string.quick_action_copy_text),
) { ) {
copyNoteText(note, noteVersionToCopy) copyNoteText(note, noteVersionToCopy)
} }
VerticalDivider(color = primaryLight) VerticalDivider(color = primaryLight)
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.AlternateEmail, MaterialSymbols.AlternateEmail,
stringRes(R.string.quick_action_copy_user_id), stringRes(Res.string.quick_action_copy_user_id),
) { ) {
note.author?.let { note.author?.let {
scope.launch { scope.launch {
@@ -357,7 +375,7 @@ fun CardBody(
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.Block, MaterialSymbols.Block,
stringRes(R.string.quick_action_block), stringRes(Res.string.quick_action_block),
) { ) {
if (accountViewModel.account.settings.hideBlockAlertDialog) { if (accountViewModel.account.settings.hideBlockAlertDialog) {
note.author?.let { accountViewModel.hide(it) } note.author?.let { accountViewModel.hide(it) }
@@ -415,7 +433,7 @@ fun CardBody(
} else if (isFollowingUser) { } else if (isFollowingUser) {
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.PersonRemove, MaterialSymbols.PersonRemove,
stringRes(R.string.quick_action_unfollow), stringRes(Res.string.quick_action_unfollow),
) { ) {
accountViewModel.unfollow(note.author!!) accountViewModel.unfollow(note.author!!)
onDismiss() onDismiss()
@@ -423,7 +441,7 @@ fun CardBody(
} else { } else {
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.PersonAdd, MaterialSymbols.PersonAdd,
stringRes(R.string.quick_action_follow), stringRes(Res.string.quick_action_follow),
) { ) {
accountViewModel.follow(note.author!!) accountViewModel.follow(note.author!!)
onDismiss() onDismiss()
@@ -437,7 +455,7 @@ fun CardBody(
VerticalDivider(color = primaryLight) VerticalDivider(color = primaryLight)
NoteQuickActionItem( NoteQuickActionItem(
icon = MaterialSymbols.Dns, icon = MaterialSymbols.Dns,
label = stringRes(R.string.broadcast), label = stringRes(Res.string.broadcast),
) { ) {
accountViewModel.broadcast(note) accountViewModel.broadcast(note)
// showSelectTextDialog = true // showSelectTextDialog = true
@@ -448,7 +466,7 @@ fun CardBody(
if (isOwnNote && note.isDraft()) { if (isOwnNote && note.isDraft()) {
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.Edit, MaterialSymbols.Edit,
stringRes(R.string.edit_draft), stringRes(Res.string.edit_draft),
) { ) {
onWantsToEditDraft() onWantsToEditDraft()
} }
@@ -489,7 +507,7 @@ fun CardBody(
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.Report, MaterialSymbols.Report,
stringRes(R.string.quick_action_report), stringRes(Res.string.quick_action_report),
) { ) {
showReportDialog.value = true showReportDialog.value = true
} }
@@ -513,7 +531,7 @@ fun CardBody(
NoteQuickActionItem( NoteQuickActionItem(
MaterialSymbols.Gavel, MaterialSymbols.Gavel,
stringRes(R.string.concord_ban_user), stringRes(Res.string.concord_ban_user),
) { ) {
showConcordBanDialog.value = true showConcordBanDialog.value = true
} }
@@ -556,10 +574,10 @@ fun DeleteAlertDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
QuickActionAlertDialog( QuickActionAlertDialog(
title = stringRes(R.string.quick_action_request_deletion_alert_title), title = stringRes(Res.string.quick_action_request_deletion_alert_title),
textContent = stringRes(R.string.quick_action_request_deletion_alert_body), textContent = stringRes(Res.string.quick_action_request_deletion_alert_body),
buttonIcon = MaterialSymbols.Delete, buttonIcon = MaterialSymbols.Delete,
buttonText = stringRes(R.string.quick_action_delete_dialog_btn), buttonText = stringRes(Res.string.quick_action_delete_dialog_btn),
onClickDoOnce = { onClickDoOnce = {
accountViewModel.delete(note) accountViewModel.delete(note)
onDismiss() onDismiss()
@@ -580,9 +598,9 @@ private fun BlockAlertDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
) = QuickActionAlertDialog( ) = QuickActionAlertDialog(
title = stringRes(R.string.report_dialog_block_hide_user_btn), title = stringRes(R.string.report_dialog_block_hide_user_btn),
textContent = stringRes(R.string.report_dialog_blocking_a_user), textContent = stringRes(Res.string.report_dialog_blocking_a_user),
buttonIcon = MaterialSymbols.Block, buttonIcon = MaterialSymbols.Block,
buttonText = stringRes(R.string.quick_action_block_dialog_btn), buttonText = stringRes(Res.string.quick_action_block_dialog_btn),
buttonColors = buttonColors =
ButtonDefaults.buttonColors( ButtonDefaults.buttonColors(
containerColor = LightRedColor, containerColor = LightRedColor,
@@ -681,7 +699,7 @@ fun QuickActionAlertDialog(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
) { ) {
TextButton(onClick = onClickDontShowAgain) { TextButton(onClick = onClickDontShowAgain) {
Text(stringRes(R.string.quick_action_dont_show_again_button)) Text(stringRes(Res.string.quick_action_dont_show_again_button))
} }
Button( Button(
onClick = onClickDoOnce, onClick = onClickDoOnce,
@@ -34,11 +34,12 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.Cashu import com.vitorpamplona.amethyst.commons.hashtags.Cashu
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.NutzapEntry import com.vitorpamplona.amethyst.commons.model.NutzapEntry
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.nutzap
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteZaps import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteZaps
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
@@ -93,7 +94,7 @@ private fun RenderNutzapGalleryRow(
Box(modifier = WidthAuthorPictureModifier) { Box(modifier = WidthAuthorPictureModifier) {
Icon( Icon(
imageVector = CustomHashTagIcons.Cashu, imageVector = CustomHashTagIcons.Cashu,
contentDescription = stringRes(R.string.nutzap), contentDescription = stringRes(Res.string.nutzap),
modifier = Modifier.size(Size20dp).align(Alignment.TopEnd), modifier = Modifier.size(Size20dp).align(Alignment.TopEnd),
// Tint the monochrome cashu outline brand orange so it reads as // Tint the monochrome cashu outline brand orange so it reads as
// a value transfer, matching the lightning ZappedIcon in the // a value transfer, matching the lightning ZappedIcon in the
@@ -35,9 +35,10 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.Cashu import com.vitorpamplona.amethyst.commons.hashtags.Cashu
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.nutzap
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -112,7 +113,7 @@ fun NutzapUserSetCompose(
) { ) {
Icon( Icon(
imageVector = CustomHashTagIcons.Cashu, imageVector = CustomHashTagIcons.Cashu,
contentDescription = stringRes(R.string.nutzap), contentDescription = stringRes(Res.string.nutzap),
modifier = Modifier.size(Size25dp).align(Alignment.TopEnd), modifier = Modifier.size(Size25dp).align(Alignment.TopEnd),
// Tint the monochrome cashu outline brand orange so it // Tint the monochrome cashu outline brand orange so it
// matches the lightning ZappedIcon in the zap set card. // matches the lightning ZappedIcon in the zap set card.
@@ -117,6 +117,13 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.fork
import com.vitorpamplona.amethyst.commons.resources.nutzap
import com.vitorpamplona.amethyst.commons.resources.quick_zap_amounts
import com.vitorpamplona.amethyst.commons.resources.quote
import com.vitorpamplona.amethyst.commons.resources.reload_mint_title
import com.vitorpamplona.amethyst.commons.resources.sats_to_complete
import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius
import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable
import com.vitorpamplona.amethyst.model.MIN_ONCHAIN_ZAP_SATS import com.vitorpamplona.amethyst.model.MIN_ONCHAIN_ZAP_SATS
@@ -511,7 +518,7 @@ fun RenderZapRaiser(
Text( Text(
text = text =
stringRes(id = R.string.sats_to_complete, totalPercentage, zapraiserStatus.left), stringRes(id = Res.string.sats_to_complete, totalPercentage, zapraiserStatus.left),
modifier = NoSoTinyBorders, modifier = NoSoTinyBorders,
// color = MaterialTheme.colorScheme.placeholderText, // color = MaterialTheme.colorScheme.placeholderText,
fontSize = Font14SP, fontSize = Font14SP,
@@ -1710,7 +1717,7 @@ fun BoostTypeChoicePopupContent(
} }
BoostActionChip( BoostActionChip(
label = stringRes(R.string.quote), label = stringRes(Res.string.quote),
onClick = onQuote, onClick = onQuote,
) { tint -> ) { tint ->
Icon( Icon(
@@ -1723,7 +1730,7 @@ fun BoostTypeChoicePopupContent(
if (showFork) { if (showFork) {
BoostActionChip( BoostActionChip(
label = stringRes(R.string.fork), label = stringRes(Res.string.fork),
onClick = onFork, onClick = onFork,
) { tint -> ) { tint ->
Icon( Icon(
@@ -2295,7 +2302,7 @@ fun ZapAmountChoiceGrid(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.Tune, symbol = MaterialSymbols.Tune,
contentDescription = stringRes(R.string.quick_zap_amounts), contentDescription = stringRes(Res.string.quick_zap_amounts),
modifier = Size18Modifier, modifier = Size18Modifier,
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -2495,7 +2502,7 @@ internal fun ZapRailIcon(
ZapRail.CASHU -> ZapRail.CASHU ->
Material3Icon( Material3Icon(
imageVector = CustomHashTagIcons.Cashu, imageVector = CustomHashTagIcons.Cashu,
contentDescription = stringRes(R.string.nutzap), contentDescription = stringRes(Res.string.nutzap),
modifier = Modifier.size(cashuSize), modifier = Modifier.size(cashuSize),
// The cashu mark is a monochrome, tintable outline — colour it the // The cashu mark is a monochrome, tintable outline — colour it the
// same brand orange as the other rails when selected, else mono. // same brand orange as the other rails when selected, else mono.
@@ -2507,7 +2514,7 @@ internal fun ZapRailIcon(
Box(contentAlignment = Alignment.BottomEnd) { Box(contentAlignment = Alignment.BottomEnd) {
Material3Icon( Material3Icon(
imageVector = CustomHashTagIcons.Cashu, imageVector = CustomHashTagIcons.Cashu,
contentDescription = stringRes(R.string.reload_mint_title), contentDescription = stringRes(Res.string.reload_mint_title),
modifier = Modifier.size(cashuSize).alpha(0.5f), modifier = Modifier.size(cashuSize).alpha(0.5f),
tint = if (colored) BitcoinOrange else mono, tint = if (colored) BitcoinOrange else mono,
) )
@@ -41,6 +41,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.posts_received
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.relays.MyRelayInfo import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.relays.MyRelayInfo
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -89,7 +91,7 @@ fun RelayCompose(
} }
Text( Text(
"${relay.counter} ${stringRes(R.string.posts_received)}", "${relay.counter} ${stringRes(Res.string.posts_received)}",
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -45,10 +45,11 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.expand_relay_list
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -237,7 +238,7 @@ private fun ShowMoreRelaysButton(onClick: () -> Unit) {
) { ) {
Icon( Icon(
symbol = MaterialSymbols.ExpandMore, symbol = MaterialSymbols.ExpandMore,
contentDescription = stringRes(id = R.string.expand_relay_list), contentDescription = stringRes(id = Res.string.expand_relay_list),
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
} }
@@ -47,10 +47,12 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.expand_relay_list
import com.vitorpamplona.amethyst.commons.resources.relay_info
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
import com.vitorpamplona.amethyst.ui.components.ClickableBox import com.vitorpamplona.amethyst.ui.components.ClickableBox
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
@@ -116,7 +118,7 @@ fun ChatRelayExpandButton(onClick: () -> Unit) {
) { ) {
Icon( Icon(
symbol = MaterialSymbols.ChevronRight, symbol = MaterialSymbols.ChevronRight,
contentDescription = stringRes(id = R.string.expand_relay_list), contentDescription = stringRes(id = Res.string.expand_relay_list),
modifier = Size15Modifier, modifier = Size15Modifier,
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
@@ -218,7 +220,7 @@ fun RenderRelayIcon(
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = displayUrl, robot = displayUrl,
model = iconUrl, model = iconUrl,
contentDescription = stringRes(id = R.string.relay_info, displayUrl), contentDescription = stringRes(id = Res.string.relay_info, displayUrl),
colorFilter = RelayIconFilter, colorFilter = RelayIconFilter,
modifier = iconModifier, modifier = iconModifier,
loadProfilePicture = loadProfilePicture, loadProfilePicture = loadProfilePicture,
@@ -33,9 +33,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.and
import com.vitorpamplona.amethyst.commons.resources.replying_to
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -88,7 +90,7 @@ fun ReplyInformationChannel(
FlowRow { FlowRow {
if (!mentions.isNullOrEmpty() && !replyTo.isNullOrEmpty()) { if (!mentions.isNullOrEmpty() && !replyTo.isNullOrEmpty()) {
Text( Text(
stringRes(id = R.string.replying_to), stringRes(id = Res.string.replying_to),
fontSize = 13.sp, fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
@@ -104,7 +106,7 @@ fun ReplyInformationChannel(
) )
} else if (idx < mentions.size - 1) { } else if (idx < mentions.size - 1) {
Text( Text(
" ${stringRes(id = R.string.and)} ", " ${stringRes(id = Res.string.and)} ",
fontSize = 13.sp, fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
@@ -28,7 +28,8 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.unblock
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.ButtonPadding import com.vitorpamplona.amethyst.ui.theme.ButtonPadding
@@ -45,6 +46,6 @@ fun ShowUserButton(onClick: () -> Unit) {
), ),
contentPadding = ButtonPadding, contentPadding = ButtonPadding,
) { ) {
Text(text = stringRes(R.string.unblock)) Text(text = stringRes(Res.string.unblock))
} }
} }
@@ -73,6 +73,8 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder
import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.new_reaction_symbol
import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius
import com.vitorpamplona.amethyst.commons.util.firstFullChar import com.vitorpamplona.amethyst.commons.util.firstFullChar
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
@@ -222,7 +224,7 @@ fun UpdateReactionTypeScreen(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.new_reaction_symbol)) }, label = { Text(text = stringRes(Res.string.new_reaction_symbol)) },
value = postViewModel.nextChoice, value = postViewModel.nextChoice,
onValueChange = { postViewModel.nextChoice = it }, onValueChange = { postViewModel.nextChoice = it },
keyboardOptions = keyboardOptions =
@@ -82,6 +82,21 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.new_amount_in_sats
import com.vitorpamplona.amethyst.commons.resources.quick_zap_amounts
import com.vitorpamplona.amethyst.commons.resources.quick_zap_amounts_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_privacy_section
import com.vitorpamplona.amethyst.commons.resources.zap_type_anonymous
import com.vitorpamplona.amethyst.commons.resources.zap_type_anonymous_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_nonzap
import com.vitorpamplona.amethyst.commons.resources.zap_type_nonzap_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_private
import com.vitorpamplona.amethyst.commons.resources.zap_type_private_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_public
import com.vitorpamplona.amethyst.commons.resources.zap_type_public_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_section_explainer
import com.vitorpamplona.amethyst.ui.components.TextSpinner import com.vitorpamplona.amethyst.ui.components.TextSpinner
import com.vitorpamplona.amethyst.ui.components.TitleExplainer import com.vitorpamplona.amethyst.ui.components.TitleExplainer
import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe import com.vitorpamplona.amethyst.ui.insets.imePaddingSafe
@@ -128,23 +143,23 @@ fun UpdateZapAmountContent(
listOf( listOf(
Triple( Triple(
LnZapEvent.ZapType.PUBLIC, LnZapEvent.ZapType.PUBLIC,
stringRes(id = R.string.zap_type_public), stringRes(id = Res.string.zap_type_public),
stringRes(id = R.string.zap_type_public_explainer), stringRes(id = Res.string.zap_type_public_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.PRIVATE, LnZapEvent.ZapType.PRIVATE,
stringRes(id = R.string.zap_type_private), stringRes(id = Res.string.zap_type_private),
stringRes(id = R.string.zap_type_private_explainer), stringRes(id = Res.string.zap_type_private_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.ANONYMOUS, LnZapEvent.ZapType.ANONYMOUS,
stringRes(id = R.string.zap_type_anonymous), stringRes(id = Res.string.zap_type_anonymous),
stringRes(id = R.string.zap_type_anonymous_explainer), stringRes(id = Res.string.zap_type_anonymous_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.NONZAP, LnZapEvent.ZapType.NONZAP,
stringRes(id = R.string.zap_type_nonzap), stringRes(id = Res.string.zap_type_nonzap),
stringRes(id = R.string.zap_type_nonzap_explainer), stringRes(id = Res.string.zap_type_nonzap_explainer),
), ),
) )
@@ -164,13 +179,13 @@ fun UpdateZapAmountContent(
// ── Section 1: Quick Zap Amounts ────────────────────────────────────── // ── Section 1: Quick Zap Amounts ──────────────────────────────────────
Text( Text(
text = stringRes(R.string.quick_zap_amounts), text = stringRes(Res.string.quick_zap_amounts),
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
modifier = SettingsCategoryFirstModifier, modifier = SettingsCategoryFirstModifier,
) )
Text( Text(
text = stringRes(R.string.quick_zap_amounts_explainer), text = stringRes(Res.string.quick_zap_amounts_explainer),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
modifier = Modifier.padding(bottom = 6.dp), modifier = Modifier.padding(bottom = 6.dp),
@@ -261,7 +276,7 @@ fun UpdateZapAmountContent(
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
) { ) {
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.new_amount_in_sats)) }, label = { Text(text = stringRes(Res.string.new_amount_in_sats)) },
value = postViewModel.nextAmount, value = postViewModel.nextAmount,
onValueChange = { postViewModel.nextAmount = it }, onValueChange = { postViewModel.nextAmount = it },
keyboardOptions = keyboardOptions =
@@ -296,13 +311,13 @@ fun UpdateZapAmountContent(
// ── Section 2: Zap Privacy ──────────────────────────────────────────── // ── Section 2: Zap Privacy ────────────────────────────────────────────
Text( Text(
text = stringRes(R.string.zap_privacy_section), text = stringRes(Res.string.zap_privacy_section),
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
modifier = SettingsCategorySpacingModifier, modifier = SettingsCategorySpacingModifier,
) )
Text( Text(
text = stringRes(R.string.zap_type_section_explainer), text = stringRes(Res.string.zap_type_section_explainer),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
modifier = Modifier.padding(bottom = 8.dp), modifier = Modifier.padding(bottom = 8.dp),
@@ -313,7 +328,7 @@ fun UpdateZapAmountContent(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
TextSpinner( TextSpinner(
label = stringRes(id = R.string.zap_type_explainer), label = stringRes(id = Res.string.zap_type_explainer),
placeholder = placeholder =
zapTypes zapTypes
.firstOrNull { it.first == accountViewModel.defaultZapType() } .firstOrNull { it.first == accountViewModel.defaultZapType() }
@@ -44,9 +44,12 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.profile_image
import com.vitorpamplona.amethyst.commons.resources.profile_image_of_user
import com.vitorpamplona.amethyst.commons.resources.unknown_author
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserContactCardsScore import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserContactCardsScore
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
@@ -108,7 +111,7 @@ fun DisplayBlankAuthor(
RobohashAsyncImage( RobohashAsyncImage(
robot = "authornotfound", robot = "authornotfound",
contentDescription = stringRes(R.string.unknown_author), contentDescription = stringRes(Res.string.unknown_author),
modifier = nullModifier, modifier = nullModifier,
loadRobohash = accountViewModel.settings.isNotPerformanceMode(), loadRobohash = accountViewModel.settings.isNotPerformanceMode(),
) )
@@ -629,9 +632,9 @@ fun InnerUserPicture(
model = userPicture, model = userPicture,
contentDescription = contentDescription =
if (userName != null) { if (userName != null) {
stringRes(id = R.string.profile_image_of_user, userName) stringRes(id = Res.string.profile_image_of_user, userName)
} else { } else {
stringRes(id = R.string.profile_image) stringRes(id = Res.string.profile_image)
}, },
modifier = myImageModifier, modifier = myImageModifier,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
@@ -75,6 +75,27 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.amount_in_sats
import com.vitorpamplona.amethyst.commons.resources.custom_zaps_add_a_message
import com.vitorpamplona.amethyst.commons.resources.custom_zaps_add_a_message_example
import com.vitorpamplona.amethyst.commons.resources.custom_zaps_add_a_message_nonzap
import com.vitorpamplona.amethyst.commons.resources.custom_zaps_add_a_message_private
import com.vitorpamplona.amethyst.commons.resources.feed_is_empty
import com.vitorpamplona.amethyst.commons.resources.manual_zaps
import com.vitorpamplona.amethyst.commons.resources.paid
import com.vitorpamplona.amethyst.commons.resources.send_onchain_instead
import com.vitorpamplona.amethyst.commons.resources.send_zap
import com.vitorpamplona.amethyst.commons.resources.wallet_number
import com.vitorpamplona.amethyst.commons.resources.zap_type
import com.vitorpamplona.amethyst.commons.resources.zap_type_anonymous
import com.vitorpamplona.amethyst.commons.resources.zap_type_anonymous_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_nonzap
import com.vitorpamplona.amethyst.commons.resources.zap_type_nonzap_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_private
import com.vitorpamplona.amethyst.commons.resources.zap_type_private_explainer
import com.vitorpamplona.amethyst.commons.resources.zap_type_public
import com.vitorpamplona.amethyst.commons.resources.zap_type_public_explainer
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.ZapPaymentHandler import com.vitorpamplona.amethyst.service.ZapPaymentHandler
import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage
@@ -140,23 +161,23 @@ fun ZapCustomDialog(
listOf( listOf(
Triple( Triple(
LnZapEvent.ZapType.PUBLIC, LnZapEvent.ZapType.PUBLIC,
stringRes(id = R.string.zap_type_public), stringRes(id = Res.string.zap_type_public),
stringRes(id = R.string.zap_type_public_explainer), stringRes(id = Res.string.zap_type_public_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.PRIVATE, LnZapEvent.ZapType.PRIVATE,
stringRes(id = R.string.zap_type_private), stringRes(id = Res.string.zap_type_private),
stringRes(id = R.string.zap_type_private_explainer), stringRes(id = Res.string.zap_type_private_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.ANONYMOUS, LnZapEvent.ZapType.ANONYMOUS,
stringRes(id = R.string.zap_type_anonymous), stringRes(id = Res.string.zap_type_anonymous),
stringRes(id = R.string.zap_type_anonymous_explainer), stringRes(id = Res.string.zap_type_anonymous_explainer),
), ),
Triple( Triple(
LnZapEvent.ZapType.NONZAP, LnZapEvent.ZapType.NONZAP,
stringRes(id = R.string.zap_type_nonzap), stringRes(id = Res.string.zap_type_nonzap),
stringRes(id = R.string.zap_type_nonzap_explainer), stringRes(id = Res.string.zap_type_nonzap_explainer),
), ),
).filter { ).filter {
!isPrivateTarget || it.first == LnZapEvent.ZapType.PRIVATE || it.first == LnZapEvent.ZapType.NONZAP !isPrivateTarget || it.first == LnZapEvent.ZapType.PRIVATE || it.first == LnZapEvent.ZapType.NONZAP
@@ -211,7 +232,7 @@ fun ZapCustomDialog(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = stringRes(id = R.string.send_zap), text = stringRes(id = Res.string.send_zap),
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
) )
@@ -247,7 +268,7 @@ fun ZapCustomDialog(
// Amount input // Amount input
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(id = R.string.amount_in_sats)) }, label = { Text(text = stringRes(id = Res.string.amount_in_sats)) },
value = postViewModel.customAmount, value = postViewModel.customAmount,
onValueChange = { postViewModel.customAmount = it }, onValueChange = { postViewModel.customAmount = it },
keyboardOptions = keyboardOptions =
@@ -271,7 +292,7 @@ fun ZapCustomDialog(
// Zap type label // Zap type label
Text( Text(
text = stringRes(id = R.string.zap_type), text = stringRes(id = Res.string.zap_type),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(bottom = 4.dp), modifier = Modifier.padding(bottom = 4.dp),
@@ -304,15 +325,15 @@ fun ZapCustomDialog(
label = { label = {
when (selectedZapType) { when (selectedZapType) {
LnZapEvent.ZapType.PUBLIC, LnZapEvent.ZapType.ANONYMOUS -> { LnZapEvent.ZapType.PUBLIC, LnZapEvent.ZapType.ANONYMOUS -> {
Text(text = stringRes(id = R.string.custom_zaps_add_a_message)) Text(text = stringRes(id = Res.string.custom_zaps_add_a_message))
} }
LnZapEvent.ZapType.PRIVATE -> { LnZapEvent.ZapType.PRIVATE -> {
Text(text = stringRes(id = R.string.custom_zaps_add_a_message_private)) Text(text = stringRes(id = Res.string.custom_zaps_add_a_message_private))
} }
LnZapEvent.ZapType.NONZAP -> { LnZapEvent.ZapType.NONZAP -> {
Text(text = stringRes(id = R.string.custom_zaps_add_a_message_nonzap)) Text(text = stringRes(id = Res.string.custom_zaps_add_a_message_nonzap))
} }
} }
}, },
@@ -325,7 +346,7 @@ fun ZapCustomDialog(
), ),
placeholder = { placeholder = {
Text( Text(
text = stringRes(id = R.string.custom_zaps_add_a_message_example), text = stringRes(id = Res.string.custom_zaps_add_a_message_example),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -369,7 +390,7 @@ fun ZapCustomDialog(
.fillMaxWidth() .fillMaxWidth()
.padding(top = 4.dp), .padding(top = 4.dp),
) { ) {
Text(text = stringRes(id = R.string.send_onchain_instead)) Text(text = stringRes(id = Res.string.send_onchain_instead))
} }
} }
} }
@@ -420,7 +441,7 @@ fun PayViaIntentScreen(
) { ) {
Scaffold( Scaffold(
topBar = { topBar = {
TopBarWithBackButton(stringRes(id = R.string.manual_zaps), nav) TopBarWithBackButton(stringRes(id = Res.string.manual_zaps), nav)
}, },
) { pad -> ) { pad ->
val list = accountViewModel.tempManualPaymentCache.get(paymentId) val list = accountViewModel.tempManualPaymentCache.get(paymentId)
@@ -431,7 +452,7 @@ fun PayViaIntentScreen(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text(stringRes(R.string.feed_is_empty)) Text(stringRes(Res.string.feed_is_empty))
} }
} else { } else {
LazyColumn( LazyColumn(
@@ -480,7 +501,7 @@ fun DisplayPayable(
UsernameDisplay(payable.info.user, accountViewModel = accountViewModel) UsernameDisplay(payable.info.user, accountViewModel = accountViewModel)
} else { } else {
Text( Text(
text = stringRes(id = R.string.wallet_number, index + 1), text = stringRes(id = Res.string.wallet_number, index + 1),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
@@ -589,7 +610,7 @@ fun PayButton(
if (isActive) { if (isActive) {
Text(text = stringRes(R.string.pay), color = Color.White) Text(text = stringRes(R.string.pay), color = Color.White)
} else { } else {
Text(text = stringRes(R.string.paid), color = Color.White) Text(text = stringRes(Res.string.paid), color = Color.White)
} }
} }
} }
@@ -43,7 +43,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.ai_tone_correct
import com.vitorpamplona.amethyst.commons.resources.ai_tone_elaborate
import com.vitorpamplona.amethyst.commons.resources.ai_tone_emojify
import com.vitorpamplona.amethyst.commons.resources.ai_tone_friendly
import com.vitorpamplona.amethyst.commons.resources.ai_tone_professional
import com.vitorpamplona.amethyst.commons.resources.ai_tone_rephrase
import com.vitorpamplona.amethyst.commons.resources.ai_tone_shorter
import com.vitorpamplona.amethyst.commons.resources.ai_writing_dismiss
import com.vitorpamplona.amethyst.commons.resources.ai_writing_use_this
import com.vitorpamplona.amethyst.commons.service.ai.WritingResult import com.vitorpamplona.amethyst.commons.service.ai.WritingResult
import com.vitorpamplona.amethyst.commons.service.ai.WritingTone import com.vitorpamplona.amethyst.commons.service.ai.WritingTone
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -120,10 +129,10 @@ private fun AiResultCard(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
) { ) {
TextButton(onClick = onDismiss) { TextButton(onClick = onDismiss) {
Text(stringRes(R.string.ai_writing_dismiss)) Text(stringRes(Res.string.ai_writing_dismiss))
} }
OutlinedButton(onClick = onApply) { OutlinedButton(onClick = onApply) {
Text(stringRes(R.string.ai_writing_use_this)) Text(stringRes(Res.string.ai_writing_use_this))
} }
} }
} }
@@ -158,11 +167,11 @@ private fun ToneChipRow(
@Composable @Composable
private fun toneDisplayName(tone: WritingTone): String = private fun toneDisplayName(tone: WritingTone): String =
when (tone) { when (tone) {
WritingTone.CORRECT -> stringRes(R.string.ai_tone_correct) WritingTone.CORRECT -> stringRes(Res.string.ai_tone_correct)
WritingTone.REPHRASE -> stringRes(R.string.ai_tone_rephrase) WritingTone.REPHRASE -> stringRes(Res.string.ai_tone_rephrase)
WritingTone.SHORTER -> stringRes(R.string.ai_tone_shorter) WritingTone.SHORTER -> stringRes(Res.string.ai_tone_shorter)
WritingTone.ELABORATE -> stringRes(R.string.ai_tone_elaborate) WritingTone.ELABORATE -> stringRes(Res.string.ai_tone_elaborate)
WritingTone.FRIENDLY -> stringRes(R.string.ai_tone_friendly) WritingTone.FRIENDLY -> stringRes(Res.string.ai_tone_friendly)
WritingTone.PROFESSIONAL -> stringRes(R.string.ai_tone_professional) WritingTone.PROFESSIONAL -> stringRes(Res.string.ai_tone_professional)
WritingTone.EMOJIFY -> stringRes(R.string.ai_tone_emojify) WritingTone.EMOJIFY -> stringRes(Res.string.ai_tone_emojify)
} }
@@ -24,9 +24,10 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.post_anonymously
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size19Modifier import com.vitorpamplona.amethyst.ui.theme.Size19Modifier
@@ -41,14 +42,14 @@ fun AnonymousPostButton(
if (!isActive) { if (!isActive) {
Icon( Icon(
symbol = MaterialSymbols.PersonOff, symbol = MaterialSymbols.PersonOff,
contentDescription = stringRes(R.string.post_anonymously), contentDescription = stringRes(Res.string.post_anonymously),
modifier = Size19Modifier, modifier = Size19Modifier,
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.PersonOff, symbol = MaterialSymbols.PersonOff,
contentDescription = stringRes(R.string.post_anonymously), contentDescription = stringRes(Res.string.post_anonymously),
modifier = Size19Modifier, modifier = Size19Modifier,
tint = Color.Red, tint = Color.Red,
) )
@@ -42,6 +42,10 @@ import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_sensitive_content_description_placeholder
import com.vitorpamplona.amethyst.commons.resources.add_sensitive_content_explainer
import com.vitorpamplona.amethyst.commons.resources.content_warning
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.placeholderText
@@ -66,7 +70,7 @@ fun ContentSensitivityExplainer(
) { ) {
Icon( Icon(
symbol = MaterialSymbols.VisibilityOff, symbol = MaterialSymbols.VisibilityOff,
contentDescription = stringRes(id = R.string.content_warning), contentDescription = stringRes(id = Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(18.dp) .size(18.dp)
@@ -75,7 +79,7 @@ fun ContentSensitivityExplainer(
) )
Icon( Icon(
symbol = MaterialSymbols.Warning, symbol = MaterialSymbols.Warning,
contentDescription = stringRes(id = R.string.content_warning), contentDescription = stringRes(id = Res.string.content_warning),
modifier = modifier =
Modifier Modifier
.size(10.dp) .size(10.dp)
@@ -95,7 +99,7 @@ fun ContentSensitivityExplainer(
HorizontalDivider(thickness = DividerThickness) HorizontalDivider(thickness = DividerThickness)
Text( Text(
text = stringRes(R.string.add_sensitive_content_explainer), text = stringRes(Res.string.add_sensitive_content_explainer),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
modifier = Modifier.padding(vertical = 10.dp), modifier = Modifier.padding(vertical = 10.dp),
) )
@@ -106,7 +110,7 @@ fun ContentSensitivityExplainer(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.add_sensitive_content_description_placeholder), text = stringRes(Res.string.add_sensitive_content_description_placeholder),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -31,9 +31,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_content_warning
import com.vitorpamplona.amethyst.commons.resources.remove_content_warning
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@Composable @Composable
@@ -52,7 +54,7 @@ fun MarkAsSensitiveButton(
if (!isActive) { if (!isActive) {
Icon( Icon(
symbol = MaterialSymbols.Visibility, symbol = MaterialSymbols.Visibility,
contentDescription = stringRes(R.string.add_content_warning), contentDescription = stringRes(Res.string.add_content_warning),
modifier = modifier =
Modifier Modifier
.size(18.dp) .size(18.dp)
@@ -61,7 +63,7 @@ fun MarkAsSensitiveButton(
) )
Icon( Icon(
symbol = MaterialSymbols.Warning, symbol = MaterialSymbols.Warning,
contentDescription = stringRes(R.string.add_content_warning), contentDescription = stringRes(Res.string.add_content_warning),
modifier = modifier =
Modifier Modifier
.size(10.dp) .size(10.dp)
@@ -71,7 +73,7 @@ fun MarkAsSensitiveButton(
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.VisibilityOff, symbol = MaterialSymbols.VisibilityOff,
contentDescription = stringRes(id = R.string.remove_content_warning), contentDescription = stringRes(id = Res.string.remove_content_warning),
modifier = modifier =
Modifier Modifier
.size(18.dp) .size(18.dp)
@@ -80,7 +82,7 @@ fun MarkAsSensitiveButton(
) )
Icon( Icon(
symbol = MaterialSymbols.Warning, symbol = MaterialSymbols.Warning,
contentDescription = stringRes(id = R.string.remove_content_warning), contentDescription = stringRes(id = Res.string.remove_content_warning),
modifier = modifier =
Modifier Modifier
.size(10.dp) .size(10.dp)
@@ -27,9 +27,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_expiration_date
import com.vitorpamplona.amethyst.commons.resources.remove_expiration_date
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@Composable @Composable
@@ -43,14 +45,14 @@ fun ExpirationDateButton(
if (!isActive) { if (!isActive) {
Icon( Icon(
symbol = MaterialSymbols.Timer, symbol = MaterialSymbols.Timer,
contentDescription = stringRes(R.string.add_expiration_date), contentDescription = stringRes(Res.string.add_expiration_date),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.TimerOff, symbol = MaterialSymbols.TimerOff,
contentDescription = stringRes(R.string.remove_expiration_date), contentDescription = stringRes(Res.string.remove_expiration_date),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = Color(0xFFFF6600), tint = Color(0xFFFF6600),
) )
@@ -50,13 +50,19 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.confirm
import com.vitorpamplona.amethyst.commons.resources.expiration_date_explainer
import com.vitorpamplona.amethyst.commons.resources.expiration_date_select
import com.vitorpamplona.amethyst.commons.resources.expiration_expires_in
import com.vitorpamplona.amethyst.commons.resources.expiration_time
import com.vitorpamplona.amethyst.commons.resources.next
import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.DividerThickness
@@ -118,7 +124,7 @@ fun ExpirationDatePicker(model: IExpiration) {
HorizontalDivider(thickness = DividerThickness) HorizontalDivider(thickness = DividerThickness)
Text( Text(
text = stringRes(R.string.expiration_date_explainer), text = stringRes(Res.string.expiration_date_explainer),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
modifier = Modifier.padding(vertical = 10.dp), modifier = Modifier.padding(vertical = 10.dp),
) )
@@ -131,14 +137,14 @@ fun ExpirationDatePicker(model: IExpiration) {
modifier = Modifier.padding(16.dp), modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon(MaterialSymbols.Timer, contentDescription = stringResource(R.string.expiration_date_select)) Icon(MaterialSymbols.Timer, contentDescription = stringRes(Res.string.expiration_date_select))
Spacer(Modifier.width(12.dp)) Spacer(Modifier.width(12.dp))
if (model.expirationDate < TimeUtils.oneMinuteFromNow()) { if (model.expirationDate < TimeUtils.oneMinuteFromNow()) {
Text(stringRes(R.string.expiration_date_label) + " " + model.expirationDate, style = MaterialTheme.typography.bodyLarge) Text(stringRes(R.string.expiration_date_label) + " " + model.expirationDate, style = MaterialTheme.typography.bodyLarge)
} else { } else {
Text( Text(
text = stringRes(R.string.expiration_expires_in, timeAheadNoDot(model.expirationDate, context)), text = stringRes(Res.string.expiration_expires_in, timeAheadNoDot(model.expirationDate, context)),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
) )
} }
@@ -153,7 +159,7 @@ fun ExpirationDatePicker(model: IExpiration) {
TextButton(onClick = { TextButton(onClick = {
showDatePicker = false showDatePicker = false
showTimePicker = true showTimePicker = true
}) { Text(stringResource(R.string.next)) } }) { Text(stringRes(Res.string.next)) }
}, },
) { ) {
DatePicker(state = datePickerState) DatePicker(state = datePickerState)
@@ -163,7 +169,7 @@ fun ExpirationDatePicker(model: IExpiration) {
if (showTimePicker) { if (showTimePicker) {
TimePickerDialog( TimePickerDialog(
title = { title = {
Text(stringResource(R.string.expiration_time)) Text(stringRes(Res.string.expiration_time))
}, },
onDismissRequest = { showTimePicker = false }, onDismissRequest = { showTimePicker = false },
confirmButton = { confirmButton = {
@@ -182,7 +188,7 @@ fun ExpirationDatePicker(model: IExpiration) {
showTimePicker = false showTimePicker = false
}, },
) { Text(stringResource(R.string.confirm)) } ) { Text(stringRes(Res.string.confirm)) }
}, },
) { ) {
TimePicker(state = timePickerState) TimePicker(state = timePickerState)
@@ -23,9 +23,11 @@ package com.vitorpamplona.amethyst.ui.note.creators.invoice
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_bitcoin_invoice
import com.vitorpamplona.amethyst.commons.resources.cancel_bitcoin_invoice
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
@@ -41,14 +43,14 @@ fun AddLnInvoiceButton(
if (!isLnInvoiceActive) { if (!isLnInvoiceActive) {
Icon( Icon(
symbol = MaterialSymbols.CurrencyBitcoin, symbol = MaterialSymbols.CurrencyBitcoin,
contentDescription = stringRes(id = R.string.add_bitcoin_invoice), contentDescription = stringRes(id = Res.string.add_bitcoin_invoice),
modifier = Size20Modifier, modifier = Size20Modifier,
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.CurrencyBitcoin, symbol = MaterialSymbols.CurrencyBitcoin,
contentDescription = stringRes(id = R.string.cancel_bitcoin_invoice), contentDescription = stringRes(id = Res.string.cancel_bitcoin_invoice),
modifier = Size20Modifier, modifier = Size20Modifier,
tint = BitcoinOrange, tint = BitcoinOrange,
) )
@@ -47,6 +47,11 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.hashtags.Lightning import com.vitorpamplona.amethyst.commons.hashtags.Lightning
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.clink_lightning_offer
import com.vitorpamplona.amethyst.commons.resources.clink_offer_amount_range
import com.vitorpamplona.amethyst.commons.resources.clink_offer_amount_sats
import com.vitorpamplona.amethyst.commons.resources.clink_offer_pay_to
import com.vitorpamplona.amethyst.service.ClinkOfferPayer import com.vitorpamplona.amethyst.service.ClinkOfferPayer
import com.vitorpamplona.amethyst.ui.components.PaymentCard import com.vitorpamplona.amethyst.ui.components.PaymentCard
import com.vitorpamplona.amethyst.ui.components.PaymentCardAmount import com.vitorpamplona.amethyst.ui.components.PaymentCardAmount
@@ -112,7 +117,7 @@ fun ClinkOfferPreview(
) )
PaymentCard( PaymentCard(
title = stringRes(R.string.clink_lightning_offer), title = stringRes(Res.string.clink_lightning_offer),
icon = { icon = {
Icon( Icon(
imageVector = CustomHashTagIcons.Lightning, imageVector = CustomHashTagIcons.Lightning,
@@ -143,7 +148,7 @@ fun ClinkOfferPreview(
OutlinedTextField( OutlinedTextField(
value = amountInput, value = amountInput,
onValueChange = { new -> amountInput = new.filter(Char::isDigit) }, onValueChange = { new -> amountInput = new.filter(Char::isDigit) },
label = { Text(stringRes(R.string.clink_offer_amount_sats)) }, label = { Text(stringRes(Res.string.clink_offer_amount_sats)) },
singleLine = true, singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
supportingText = supportingText =
@@ -151,7 +156,7 @@ fun ClinkOfferPreview(
val min = range.min val min = range.min
val max = range.max val max = range.max
if (min != null && max != null) { if (min != null && max != null) {
{ Text(stringRes(R.string.clink_offer_amount_range, min.toString(), max.toString())) } { Text(stringRes(Res.string.clink_offer_amount_range, min.toString(), max.toString())) }
} else { } else {
null null
} }
@@ -246,7 +251,7 @@ private fun OfferRecipientRow(
.padding(4.dp), .padding(4.dp),
) { ) {
Text( Text(
text = stringRes(R.string.clink_offer_pay_to), text = stringRes(Res.string.clink_offer_pay_to),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(end = 8.dp), modifier = Modifier.padding(end = 8.dp),
@@ -30,6 +30,8 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.model.payments.PaymentSource import com.vitorpamplona.amethyst.commons.model.payments.PaymentSource
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.clink_confirm_payment_title
import com.vitorpamplona.amethyst.ui.note.payViaIntent import com.vitorpamplona.amethyst.ui.note.payViaIntent
import com.vitorpamplona.amethyst.ui.nwc.nwcFailureDetail import com.vitorpamplona.amethyst.ui.nwc.nwcFailureDetail
import com.vitorpamplona.amethyst.ui.nwc.nwcTimeoutMessage import com.vitorpamplona.amethyst.ui.nwc.nwcTimeoutMessage
@@ -131,7 +133,7 @@ private fun ConfirmPaymentDialog(
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
title = { Text(stringRes(R.string.clink_confirm_payment_title)) }, title = { Text(stringRes(Res.string.clink_confirm_payment_title)) },
text = { Text(message) }, text = { Text(message) },
confirmButton = { confirmButton = {
Button(onClick = onConfirm) { Text(stringRes(R.string.pay)) } Button(onClick = onConfirm) { Text(stringRes(R.string.pay)) }
@@ -42,6 +42,9 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.hashtags.Lightning import com.vitorpamplona.amethyst.commons.hashtags.Lightning
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.invoice_expired
import com.vitorpamplona.amethyst.commons.resources.lightning_invoice
import com.vitorpamplona.amethyst.service.lnurl.CachedLnInvoiceParser import com.vitorpamplona.amethyst.service.lnurl.CachedLnInvoiceParser
import com.vitorpamplona.amethyst.service.lnurl.InvoiceAmount import com.vitorpamplona.amethyst.service.lnurl.InvoiceAmount
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
@@ -126,7 +129,7 @@ fun InvoicePreview(
val isExpired = remember(expiresAt) { expiresAt != null && expiresAt < TimeUtils.now() } val isExpired = remember(expiresAt) { expiresAt != null && expiresAt < TimeUtils.now() }
PaymentCard( PaymentCard(
title = stringRes(R.string.lightning_invoice), title = stringRes(Res.string.lightning_invoice),
icon = { icon = {
Icon( Icon(
imageVector = CustomHashTagIcons.Lightning, imageVector = CustomHashTagIcons.Lightning,
@@ -147,7 +150,7 @@ fun InvoicePreview(
if (isExpired) { if (isExpired) {
Text( Text(
text = stringRes(R.string.invoice_expired), text = stringRes(Res.string.invoice_expired),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@@ -47,10 +47,15 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.hashtags.Lightning import com.vitorpamplona.amethyst.commons.hashtags.Lightning
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.amount_in_sats
import com.vitorpamplona.amethyst.commons.resources.lightning_tips
import com.vitorpamplona.amethyst.commons.resources.note_to_receiver
import com.vitorpamplona.amethyst.commons.resources.send_sats
import com.vitorpamplona.amethyst.commons.resources.thank_you_so_much
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.DividerThickness
@@ -83,7 +88,7 @@ fun InvoiceRequest(
) )
Text( Text(
text = titleText ?: stringRes(R.string.lightning_tips), text = titleText ?: stringRes(Res.string.lightning_tips),
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.W500, fontWeight = FontWeight.W500,
modifier = Modifier.padding(start = 10.dp), modifier = Modifier.padding(start = 10.dp),
@@ -96,13 +101,13 @@ fun InvoiceRequest(
var amount by remember { mutableLongStateOf(1000L) } var amount by remember { mutableLongStateOf(1000L) }
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.note_to_receiver)) }, label = { Text(text = stringRes(Res.string.note_to_receiver)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = message, value = message,
onValueChange = { message = it }, onValueChange = { message = it },
placeholder = { placeholder = {
Text( Text(
text = stringRes(R.string.thank_you_so_much), text = stringRes(Res.string.thank_you_so_much),
color = MaterialTheme.colorScheme.placeholderText, color = MaterialTheme.colorScheme.placeholderText,
) )
}, },
@@ -114,7 +119,7 @@ fun InvoiceRequest(
) )
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringRes(R.string.amount_in_sats)) }, label = { Text(text = stringRes(Res.string.amount_in_sats)) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
value = amount.toString(), value = amount.toString(),
onValueChange = { onValueChange = {
@@ -160,7 +165,7 @@ fun InvoiceRequest(
), ),
) { ) {
Text( Text(
text = buttonText ?: stringRes(R.string.send_sats), text = buttonText ?: stringRes(Res.string.send_sats),
color = Color.White, color = Color.White,
fontSize = 20.sp, fontSize = 20.sp,
) )
@@ -22,7 +22,9 @@ package com.vitorpamplona.amethyst.ui.note.creators.invoice
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.lightning_create_and_add_invoice
import com.vitorpamplona.amethyst.commons.resources.lightning_invoice
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -41,8 +43,8 @@ fun NewPostInvoiceRequest(
lud16 = lnAddress, lud16 = lnAddress,
user = accountViewModel.account.userProfile(), user = accountViewModel.account.userProfile(),
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
titleText = stringRes(id = R.string.lightning_invoice), titleText = stringRes(id = Res.string.lightning_invoice),
buttonText = stringRes(id = R.string.lightning_create_and_add_invoice), buttonText = stringRes(id = Res.string.lightning_create_and_add_invoice),
onNewInvoice = onSuccess, onNewInvoice = onSuccess,
onError = accountViewModel.toastManager::toast, onError = accountViewModel.toastManager::toast,
) )
@@ -26,9 +26,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.add_location
import com.vitorpamplona.amethyst.commons.resources.remove_location
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@Composable @Composable
@@ -42,14 +44,14 @@ fun AddGeoHashButton(
if (!isActive) { if (!isActive) {
Icon( Icon(
symbol = MaterialSymbols.LocationOff, symbol = MaterialSymbols.LocationOff,
contentDescription = stringRes(id = R.string.add_location), contentDescription = stringRes(id = Res.string.add_location),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
) )
} else { } else {
Icon( Icon(
symbol = MaterialSymbols.LocationOn, symbol = MaterialSymbols.LocationOn,
contentDescription = stringRes(id = R.string.remove_location), contentDescription = stringRes(id = Res.string.remove_location),
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
) )
@@ -30,7 +30,9 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.lack_location_permissions
import com.vitorpamplona.amethyst.commons.resources.loading_location
import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation import com.vitorpamplona.amethyst.commons.ui.components.LoadingAnimation
import com.vitorpamplona.amethyst.service.location.LocationState import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
@@ -48,7 +50,7 @@ fun DisplayLocationObserver(viewModel: ILocationGrabber) {
LocationState.LocationResult.LackPermission -> { LocationState.LocationResult.LackPermission -> {
Text( Text(
text = stringRes(R.string.lack_location_permissions), text = stringRes(Res.string.lack_location_permissions),
fontSize = 12.sp, fontSize = 12.sp,
lineHeight = 12.sp, lineHeight = 12.sp,
) )
@@ -56,7 +58,7 @@ fun DisplayLocationObserver(viewModel: ILocationGrabber) {
LocationState.LocationResult.Loading -> { LocationState.LocationResult.Loading -> {
Text( Text(
text = stringRes(R.string.loading_location), text = stringRes(Res.string.loading_location),
fontSize = 12.sp, fontSize = 12.sp,
lineHeight = 12.sp, lineHeight = 12.sp,
) )

Some files were not shown because too many files have changed in this diff Show More