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

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