mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 11:18:24 +00:00
Merge pull request #4205 from vitorpamplona/claude/affectionate-ptolemy-0q909o
Migrate backup conflict strings to composResources
This commit is contained in:
@@ -285,6 +285,48 @@ Quartz uses expect/actual for platform-specific implementations (e.g. crypto
|
||||
backed by `secp256k1-kmp-jni-android` on Android and `secp256k1-kmp-jni-jvm` on
|
||||
JVM). See `/kotlin-multiplatform` for the expect/actual and source-set patterns.
|
||||
|
||||
## Strings
|
||||
|
||||
**MANDATORY: every new user-visible string goes in `commonsUI` Compose resources**,
|
||||
`commonsUI/src/commonMain/composeResources/values/strings.xml` — **never** in
|
||||
`amethyst/src/main/res/values/strings.xml`, even for an Android-only screen. A
|
||||
screen cannot move to `commonsUI` (or be rendered by Desktop) while its labels
|
||||
live in Android `res/`, and every key added there has to be migrated back out
|
||||
later. (The 2026-09-22 move emptied Android `res/` down to ~190 keys; the next two
|
||||
features put 447 back.)
|
||||
|
||||
- Reference it as `Res.string.my_key` / `Res.plurals.my_key`, importing
|
||||
`com.vitorpamplona.amethyst.commons.resources.Res` **and** the per-key accessor
|
||||
`com.vitorpamplona.amethyst.commons.resources.my_key` (Compose resources generates
|
||||
each key as an extension property).
|
||||
- Read it with `stringRes(Res.string.x)` / `pluralStringRes(Res.plurals.x, n, …)`
|
||||
in composition — the app-side `ui.stringRes` overloads delegate to the
|
||||
commonsUI bridge (`commons/ui/StringRes.kt`), so one import serves both kinds.
|
||||
- Outside composition there is **no blocking accessor**: use `loadStringRes(…)`
|
||||
from a coroutine (or make the function `suspend`), or resolve the label in
|
||||
composition and pass it down as a `String`. A `runBlocking` bridge is ruled out.
|
||||
- Hold a string reference as `StringResource` / `PluralStringResource`, not a
|
||||
`@StringRes Int`.
|
||||
- Format arguments must be positional (`%1$s`, `%2$d`) — compose-resources does
|
||||
not format bare `%s`/`%d`.
|
||||
- Escaping is not Android's: write `'` and `"` bare (no `\'`), and never wrap a
|
||||
value in quotes to keep its whitespace. `.claude/hooks/compose_escaping_check.py`
|
||||
checks this before a push.
|
||||
|
||||
The **only** strings that stay in Android `res/` are the ones a platform API
|
||||
reads synchronously under a deadline, where a `suspend` read cannot run: a
|
||||
foreground service's `startForeground` notification, a notification channel
|
||||
created during service startup, PiP `RemoteAction`s, napplet capability labels
|
||||
read in the sandbox process, and `AndroidManifest.xml` / `res/xml` references.
|
||||
Most of those are *copies* of a key that also lives in `commonsUI`. See
|
||||
`commons/plans/2026-09-22-strings-to-compose-resources.md` ("the
|
||||
synchronous-platform tier"). If you think a new string belongs in that tier,
|
||||
say why in the PR.
|
||||
|
||||
To move keys that already landed in Android `res/`, use
|
||||
`tools/strings-migrate/migrate.py <keys…>`. It moves every locale byte-for-byte,
|
||||
so Crowdin sees a pure move. Then repoint `R.string.x` → `Res.string.x`.
|
||||
|
||||
## Icons
|
||||
|
||||
The Material Symbols font bundled at
|
||||
|
||||
@@ -27,6 +27,9 @@ Repair with:
|
||||
idempotent, quote-unwrapping is not, and a second unwrap strips the real display
|
||||
quotes from values like `import_follows_tips`.
|
||||
|
||||
Raw line breaks and tabs inside a value are the whitespace half of the same
|
||||
mismatch: aapt collapsed them, Compose renders them (the same repair fixes them).
|
||||
|
||||
Only the Compose catalog is scanned. In an Android res tree the same escaping is
|
||||
correct and must be left alone.
|
||||
"""
|
||||
@@ -41,6 +44,10 @@ CATALOG = "*/src/*/composeResources/values*/strings.xml"
|
||||
# Compose resolves those itself.
|
||||
ANDROID_ESCAPE = re.compile(r"(?<!\\)\\(['\"?@])")
|
||||
TOOLS_ATTR = re.compile(r'tools:[\w.-]+="')
|
||||
# A value whose text holds a raw line break or tab. aapt collapsed that XML layout to
|
||||
# one space; Compose draws it, and a markdown value indented by it becomes a code block.
|
||||
STRING_TEXT = re.compile(r"<(string|item)\b[^>]*>(.*?)</\1>", re.S)
|
||||
LAYOUT_WS = re.compile(r"[\r\n\t]")
|
||||
|
||||
|
||||
def find_violations(root: Path):
|
||||
@@ -52,6 +59,13 @@ def find_violations(root: Path):
|
||||
n = len(TOOLS_ATTR.findall(text))
|
||||
if n:
|
||||
found[path]["tools: attribute"] += n
|
||||
n = sum(
|
||||
1
|
||||
for m in STRING_TEXT.finditer(text)
|
||||
if "<![CDATA[" not in m.group(2) and LAYOUT_WS.search(m.group(2))
|
||||
)
|
||||
if n:
|
||||
found[path]["raw line break/tab in a value"] += n
|
||||
return found
|
||||
|
||||
|
||||
|
||||
@@ -875,18 +875,33 @@ fun ProfileScreen(
|
||||
|
||||
### 3. Resource Access
|
||||
|
||||
**Strings do not go in `amethyst/src/main/res`.** New user-visible strings live in
|
||||
`commonsUI/src/commonMain/composeResources/values/strings.xml` and are read as
|
||||
`Res.string.x`, even on an Android-only screen. See "Strings" in `.claude/CLAUDE.md`
|
||||
for the rule and the small platform tier that is the only exception.
|
||||
|
||||
```kotlin
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.button_clicked
|
||||
import com.vitorpamplona.amethyst.commons.resources.button_label
|
||||
import com.vitorpamplona.amethyst.commons.ui.loadStringRes
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@Composable
|
||||
fun LocalizedButton() {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Button(
|
||||
onClick = {
|
||||
val message = context.getString(R.string.button_clicked)
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
||||
// No blocking accessor outside composition: read it from a coroutine,
|
||||
// or resolve it in composition and capture the String.
|
||||
scope.launch {
|
||||
Toast.makeText(context, loadStringRes(Res.string.button_clicked), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.button_label))
|
||||
Text(stringRes(Res.string.button_label))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -26,6 +26,13 @@ There are two separate `strings.xml` trees, each with its own default `values/`
|
||||
| **amethyst** (Android app) | `amethyst/src/main/res/values/strings.xml` | `amethyst/src/main/res/values-<locale>/strings.xml` |
|
||||
| **commonsUI** (KMP Compose resources, shared by Android + Desktop) | `commonsUI/src/commonMain/composeResources/values/strings.xml` | `commonsUI/src/commonMain/composeResources/values-<locale>/strings.xml` |
|
||||
|
||||
**New keys go in the `commonsUI` tree, always.** The amethyst tree is frozen at
|
||||
the small synchronous-platform tier (foreground-service and notification-channel
|
||||
text, PiP actions, napplet capability labels, manifest references). If you find
|
||||
a new feature key in it, it belongs in `commonsUI`. Move it with
|
||||
`tools/strings-migrate/migrate.py` rather than translating it where it is. See
|
||||
"Strings" in `.claude/CLAUDE.md`.
|
||||
|
||||
The `commonsUI` tree appeared when shared event-renderer composables were extracted out of `amethyst/` into `commons/` — now `commonsUI/` since the UI split (Compose Multiplatform `stringResource`). It is **not** a copy of the amethyst tree — the vast majority of its keys are commons-only; only a small handful overlap. Every diff/count/translate command below works on either tree by swapping the base path — **run the whole technique once per tree** and report them separately (each maps to its own Crowdin file, so the counts should reconcile against two different Crowdin UI numbers).
|
||||
|
||||
**Locale-qualifier caveat:** `commons` uses the same region-qualified locale dirs as amethyst for our four targets (`values-cs`, `values-de-rDE`, `values-sv-rSE`, `values-pt-rBR`), but the *full* set of locale dirs differs between trees. Enumerate `values-*` under each tree's own base rather than assuming they match.
|
||||
|
||||
@@ -1154,7 +1154,7 @@ class AppModules(
|
||||
// Local store for posts the user has scheduled to publish later. Backed by a
|
||||
// single JSON file under the app's private filesDir; read by ScheduledPostWorker.
|
||||
val scheduledPostStore =
|
||||
ScheduledPostStore(File(appContext.filesDir, ScheduledPostStore.FILE_NAME))
|
||||
ScheduledPostStore(File(appContext.filesDir, ScheduledPostStore.FILE_NAME).path)
|
||||
|
||||
// Organizes cache clearing
|
||||
val trimmingService by
|
||||
|
||||
@@ -78,6 +78,7 @@ import com.vitorpamplona.amethyst.commons.resources.lightning_create_and_add_inv
|
||||
import com.vitorpamplona.amethyst.commons.resources.lightning_invoice
|
||||
import com.vitorpamplona.amethyst.commons.resources.what_s_on_your_mind
|
||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.commons.ui.insets.imePaddingSafe
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.PostingTopBar
|
||||
@@ -98,7 +99,6 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromFiles
|
||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.components.BechLink
|
||||
import com.vitorpamplona.amethyst.ui.components.LoadUrlPreview
|
||||
import com.vitorpamplona.amethyst.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.invoice.InvoiceRequest
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
||||
|
||||
@@ -52,6 +52,12 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState
|
||||
import com.vitorpamplona.amethyst.commons.richtext.SecretEmoji
|
||||
import com.vitorpamplona.amethyst.commons.richtext.Segment
|
||||
import com.vitorpamplona.amethyst.commons.richtext.WithdrawSegment
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableBuzzInviteLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableConcordInviteLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableEmail
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickablePhone
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableRelayGroupLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableRelayUrl
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.NowhereLinkCard
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.richtext.LocalRichTextInteractions
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableTextPrimary
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
||||
@Composable
|
||||
fun ClickableEmail(email: String) {
|
||||
val stripped = email.replaceFirst("mailto:", "")
|
||||
val context = LocalContext.current
|
||||
|
||||
ClickableTextPrimary(
|
||||
text = stripped,
|
||||
onClick = { runCatching { context.sendMail(stripped) } },
|
||||
)
|
||||
}
|
||||
|
||||
fun Context.sendMail(
|
||||
to: String,
|
||||
subject: String? = null,
|
||||
) {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
intent.type = "vnd.android.cursor.item/email" // or "message/rfc822"
|
||||
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(to))
|
||||
if (subject != null) {
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
|
||||
}
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
// TODO: Handle case where no email app is available
|
||||
} catch (t: Throwable) {
|
||||
if (t is CancellationException) throw t
|
||||
// TODO: Handle potential other type of exceptions
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.concord_home_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.concord_invite_card_join
|
||||
import com.vitorpamplona.amethyst.commons.resources.concord_invite_card_subtitle
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableConcordInviteLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.screen.LocalDisplaySettings
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.vitorpamplona.amethyst.commons.resources.relay_group_badge_invite_onl
|
||||
import com.vitorpamplona.amethyst.commons.resources.relay_group_badge_private
|
||||
import com.vitorpamplona.amethyst.commons.resources.relay_group_member_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.relay_group_open
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableRelayGroupLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.pluralStringRes
|
||||
|
||||
@@ -102,6 +102,12 @@ import com.vitorpamplona.amethyst.commons.richtext.Segment
|
||||
import com.vitorpamplona.amethyst.commons.richtext.VideoSegment
|
||||
import com.vitorpamplona.amethyst.commons.richtext.WithdrawSegment
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.AnimatedBorderTextCornerRadius
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableBuzzInviteLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableConcordInviteLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableEmail
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickablePhone
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableRelayGroupLink
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableRelayUrl
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableTextPrimary
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.CrossfadeIfEnabled
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.NowhereLinkCard
|
||||
|
||||
@@ -35,6 +35,8 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedEmpty
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedError
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyGridState
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyListState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
|
||||
@@ -21,52 +21,11 @@
|
||||
package com.vitorpamplona.amethyst.ui.feeds
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.CardFeedContentState
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@Composable
|
||||
fun WatchScrollToTop(
|
||||
feedContentState: FeedContentState,
|
||||
listState: LazyListState,
|
||||
) {
|
||||
val scrollToTop by feedContentState.scrollToTop.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(scrollToTop) {
|
||||
if (scrollToTop > 0 && feedContentState.scrollToTopPending) {
|
||||
listState.scrollToItem(index = 0)
|
||||
feedContentState.sentToTop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchScrollToTop(
|
||||
feedContentState: FeedContentState,
|
||||
listState: LazyGridState,
|
||||
) {
|
||||
val scrollToTop by feedContentState.scrollToTop.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(scrollToTop) {
|
||||
if (scrollToTop > 0 && feedContentState.scrollToTopPending) {
|
||||
listState.scrollToItem(index = 0)
|
||||
feedContentState.sentToTop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchScrollToTop(
|
||||
@@ -82,166 +41,3 @@ fun WatchScrollToTop(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WatchScrollToTop(
|
||||
videoFeedContentState: FeedContentState,
|
||||
pagerState: PagerState,
|
||||
) {
|
||||
val scrollToTop by videoFeedContentState.scrollToTop.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(scrollToTop) {
|
||||
if (scrollToTop > 0 && videoFeedContentState.scrollToTopPending) {
|
||||
pagerState.scrollToPage(page = 0)
|
||||
videoFeedContentState.sentToTop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the user pinned to index 0 when new items prepend to a feed, but
|
||||
* only if they were already at the very top right before the update.
|
||||
*
|
||||
* Why this is non-trivial: every feed uses stable `key = item.idHex` in
|
||||
* its lazy list, which makes Compose preserve the visual anchor across
|
||||
* data changes. When N items prepend, the user's previously-visible
|
||||
* top item is still on screen but its index is now N — so
|
||||
* `firstVisibleItemIndex` shifts from 0 to N without any user gesture.
|
||||
* A naive `if (firstVisibleItemIndex <= 1) scrollToItem(0)` check inside
|
||||
* `LaunchedEffect(items.firstOrNull())` therefore fails as soon as more
|
||||
* than one item arrives in the same batch.
|
||||
*
|
||||
* The trick: track "was at top" continuously via [snapshotFlow], but
|
||||
* only flip it from true → false when [LazyListState.isScrollInProgress]
|
||||
* is true (i.e. the user is actively scrolling). Compose's keyed-item
|
||||
* shift after a data update does not set that flag — only real touch
|
||||
* gestures and `animate*` calls do — so data-driven index shifts can
|
||||
* never poison the cached value. When [firstItemKey] changes (head of
|
||||
* the list moved), if the cached value is still true, snap back to 0
|
||||
* with an instant (non-animated) scroll so the prepend appears as
|
||||
* in-place growth rather than a visible jump-then-scroll.
|
||||
*
|
||||
* Most callers should not invoke this directly: [SaveableFeedContentState],
|
||||
* [SaveableGridFeedContentState], and the analogous wrappers in
|
||||
* `ui/screen/FeedView.kt` already apply auto-stick to every feed they
|
||||
* own. Invoke the explicit overload only when the listState is
|
||||
* constructed outside one of those wrappers, or when the key that
|
||||
* should trigger the snap is not the default `items.list[0].idHex`
|
||||
* (e.g. notifications, chats, or feeds keyed on something other than a
|
||||
* Note's hex id).
|
||||
*/
|
||||
@Composable
|
||||
fun StickToTopOnPrepend(
|
||||
listState: LazyListState,
|
||||
firstItemKey: Any?,
|
||||
) {
|
||||
stickToTopOnPrepend(
|
||||
stateKey = listState,
|
||||
firstItemKey = firstItemKey,
|
||||
initialAtTop = {
|
||||
listState.firstVisibleItemIndex == 0 && listState.firstVisibleItemScrollOffset == 0
|
||||
},
|
||||
sampler = {
|
||||
snapshotFlow {
|
||||
listState.firstVisibleItemIndex == 0 && listState.firstVisibleItemScrollOffset == 0
|
||||
}
|
||||
},
|
||||
isScrollInProgress = { listState.isScrollInProgress },
|
||||
firstVisibleItemIndex = { listState.firstVisibleItemIndex },
|
||||
scrollToTop = { listState.scrollToItem(0) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StickToTopOnPrepend(
|
||||
gridState: LazyGridState,
|
||||
firstItemKey: Any?,
|
||||
) {
|
||||
stickToTopOnPrepend(
|
||||
stateKey = gridState,
|
||||
firstItemKey = firstItemKey,
|
||||
initialAtTop = {
|
||||
gridState.firstVisibleItemIndex == 0 && gridState.firstVisibleItemScrollOffset == 0
|
||||
},
|
||||
sampler = {
|
||||
snapshotFlow {
|
||||
gridState.firstVisibleItemIndex == 0 && gridState.firstVisibleItemScrollOffset == 0
|
||||
}
|
||||
},
|
||||
isScrollInProgress = { gridState.isScrollInProgress },
|
||||
firstVisibleItemIndex = { gridState.firstVisibleItemIndex },
|
||||
scrollToTop = { gridState.scrollToItem(0) },
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-stick wired straight to a [FeedContentState]: derives the head
|
||||
* key from `feedContent → Loaded.feed → list.firstOrNull()?.idHex` so
|
||||
* callers don't have to collect the inner feed flow themselves. Used
|
||||
* by the Saveable* wrappers; suitable for any Note-keyed feed.
|
||||
*/
|
||||
@Composable
|
||||
fun StickToTopOnPrepend(
|
||||
feedContentState: FeedContentState,
|
||||
listState: LazyListState,
|
||||
) {
|
||||
StickToTopOnPrepend(listState, rememberFirstItemIdHex(feedContentState))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StickToTopOnPrepend(
|
||||
feedContentState: FeedContentState,
|
||||
gridState: LazyGridState,
|
||||
) {
|
||||
StickToTopOnPrepend(gridState, rememberFirstItemIdHex(feedContentState))
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Composable
|
||||
private fun rememberFirstItemIdHex(feedContentState: FeedContentState): String? {
|
||||
val flow =
|
||||
remember(feedContentState) {
|
||||
feedContentState.feedContent.flatMapLatest { state ->
|
||||
when (state) {
|
||||
is FeedState.Loaded -> state.feed.map { it.list.firstOrNull()?.idHex }
|
||||
else -> flowOf(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
val key by flow.collectAsStateWithLifecycle(initialValue = null)
|
||||
return key
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun stickToTopOnPrepend(
|
||||
stateKey: Any,
|
||||
firstItemKey: Any?,
|
||||
initialAtTop: () -> Boolean,
|
||||
sampler: () -> Flow<Boolean>,
|
||||
isScrollInProgress: () -> Boolean,
|
||||
firstVisibleItemIndex: () -> Int,
|
||||
scrollToTop: suspend () -> Unit,
|
||||
) {
|
||||
// Plain holder instead of mutableStateOf — we only read this inside
|
||||
// effects, never in composition, so we don't need snapshot tracking.
|
||||
// Seed from the actual restored scroll position: when the user returns
|
||||
// to a feed via rememberForeverLazyListState, the saved offset is
|
||||
// already in place, and a hardcoded `true` would mis-snap them to 0.
|
||||
val wasAtTop = remember(stateKey) { booleanArrayOf(initialAtTop()) }
|
||||
|
||||
LaunchedEffect(stateKey) {
|
||||
sampler().collect { atTop ->
|
||||
if (atTop) {
|
||||
wasAtTop[0] = true
|
||||
} else if (isScrollInProgress()) {
|
||||
wasAtTop[0] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(firstItemKey) {
|
||||
if (firstItemKey != null && wasAtTop[0] && firstVisibleItemIndex() > 0) {
|
||||
scrollToTop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-50
@@ -20,16 +20,10 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.layouts
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.Text
|
||||
@@ -38,20 +32,19 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.profile_banner
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.NewItemsBubble
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.ChatHeaderLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DoubleHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Height4dpModifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55Modifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.ThemeComparisonColumn
|
||||
import com.vitorpamplona.amethyst.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||
import com.vitorpamplona.amethyst.ui.painterRes
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.NewItemsBubble
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
private const val PREVIEW_AUTHOR = "This is my author"
|
||||
@@ -136,43 +129,3 @@ fun ChannelNamePreview() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun ChatHeaderLayout(
|
||||
channelPicture: @Composable () -> Unit,
|
||||
firstRow: @Composable RowScope.() -> Unit,
|
||||
secondRow: @Composable RowScope.() -> Unit,
|
||||
onClick: () -> Unit,
|
||||
onLongClick: (() -> Unit)? = null,
|
||||
) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.combinedClickable(onClick = onClick, onLongClick = onLongClick)
|
||||
.padding(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Box(Size55Modifier) { channelPicture() }
|
||||
|
||||
Spacer(modifier = DoubleHorzSpacer)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
firstRow()
|
||||
}
|
||||
|
||||
Spacer(modifier = Height4dpModifier)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
secondRow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-52
@@ -21,18 +21,11 @@
|
||||
package com.vitorpamplona.amethyst.ui.layouts
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
@@ -43,10 +36,10 @@ import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.profile_banner
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.LikeIcon
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.ZappedIcon
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DoubleHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size16Modifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size20Modifier
|
||||
@@ -104,47 +97,3 @@ fun LeftPictureLayoutPreviewCard() {
|
||||
onBottomRow = { Text("This is my Moderator List") },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LeftPictureLayout(
|
||||
onImage: @Composable () -> Unit,
|
||||
onTitleRow: @Composable RowScope.() -> Unit,
|
||||
onDescription: @Composable () -> Unit,
|
||||
onBottomRow: @Composable RowScope.() -> Unit,
|
||||
imageFraction: Float = 0.25f,
|
||||
) {
|
||||
Row(Modifier.aspectRatio(ratio = 1 / imageFraction)) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(imageFraction).aspectRatio(ratio = 1f),
|
||||
) {
|
||||
onImage()
|
||||
}
|
||||
|
||||
Spacer(modifier = DoubleHorzSpacer)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
onTitleRow()
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().weight(1f),
|
||||
) {
|
||||
onDescription()
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
onBottomRow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.layouts.listItem
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.profile_banner
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.NewItemsBubble
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.ChatHeaderLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Height4dpModifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55Modifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.ThemeComparisonColumn
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||
import com.vitorpamplona.amethyst.ui.painterRes
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
private const val PREVIEW_AUTHOR = "This is my author"
|
||||
private const val PREVIEW_MESSAGE = "This is a message from this person"
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ChannelNamePreview() {
|
||||
ThemeComparisonColumn {
|
||||
Column {
|
||||
ChatHeaderLayout(
|
||||
channelPicture = {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.github, 1),
|
||||
contentDescription = stringRes(id = Res.string.profile_banner),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
)
|
||||
},
|
||||
firstRow = {
|
||||
Text(PREVIEW_AUTHOR, Modifier.weight(1f))
|
||||
TimeAgo(TimeUtils.now())
|
||||
},
|
||||
secondRow = {
|
||||
Text(PREVIEW_MESSAGE, Modifier.weight(1f))
|
||||
NewItemsBubble()
|
||||
},
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
HorizontalDivider(thickness = DividerThickness)
|
||||
|
||||
SlimListItem(
|
||||
headlineContent = {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
Text(PREVIEW_AUTHOR, Modifier.weight(1f))
|
||||
TimeAgo(TimeUtils.now())
|
||||
}
|
||||
},
|
||||
supportingContent = {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
Text(PREVIEW_MESSAGE, Modifier.weight(1f))
|
||||
Spacer(modifier = Height4dpModifier)
|
||||
NewItemsBubble()
|
||||
}
|
||||
},
|
||||
leadingContent = {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.github, 2),
|
||||
contentDescription = stringRes(id = Res.string.profile_banner),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Size55Modifier,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
HorizontalDivider(thickness = DividerThickness)
|
||||
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
Text(PREVIEW_AUTHOR, Modifier.weight(1f))
|
||||
TimeAgo(TimeUtils.now())
|
||||
}
|
||||
},
|
||||
supportingContent = {
|
||||
Row(verticalAlignment = CenterVertically) {
|
||||
Text(PREVIEW_MESSAGE, Modifier.weight(1f))
|
||||
Spacer(modifier = Height4dpModifier)
|
||||
NewItemsBubble()
|
||||
}
|
||||
},
|
||||
leadingContent = {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.github, 2),
|
||||
contentDescription = stringRes(id = Res.string.profile_banner),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier = Size55Modifier,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
HorizontalDivider(thickness = DividerThickness)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import com.vitorpamplona.amethyst.commons.resources.follow
|
||||
import com.vitorpamplona.amethyst.commons.resources.login_with_a_private_key_to_be_able_to_follow
|
||||
import com.vitorpamplona.amethyst.commons.resources.login_with_a_private_key_to_be_able_to_unfollow
|
||||
import com.vitorpamplona.amethyst.commons.resources.read_only_user
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.ShowUserButton
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55dp
|
||||
@@ -51,7 +52,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.account.observeAccountIsHiddenUser
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserAboutMe
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserIsFollowing
|
||||
import com.vitorpamplona.amethyst.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
|
||||
+1
-1
@@ -88,6 +88,7 @@ import com.vitorpamplona.amethyst.commons.resources.discover_follows
|
||||
import com.vitorpamplona.amethyst.commons.resources.follow_sets
|
||||
import com.vitorpamplona.amethyst.commons.resources.num_selected
|
||||
import com.vitorpamplona.amethyst.commons.resources.select_all
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.commons.ui.pluralStringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
@@ -95,7 +96,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.Size24dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.warningColor
|
||||
import com.vitorpamplona.amethyst.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
||||
|
||||
+1
-1
@@ -53,6 +53,7 @@ import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.Nip05State
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.user_suggestion_in_this_chat
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Font14SP
|
||||
@@ -60,7 +61,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.NIP05IconSize
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.nip05
|
||||
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.UserSearchDataSourceSubscription
|
||||
import com.vitorpamplona.amethyst.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.ObserveAndRenderNIP05VerifiedSymbol
|
||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
|
||||
+1
-1
@@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.commons.resources.zap_split_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.zap_split_search_and_add_user
|
||||
import com.vitorpamplona.amethyst.commons.resources.zap_split_search_and_add_user_placeholder
|
||||
import com.vitorpamplona.amethyst.commons.resources.zap_split_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.creators.zapsplits.IZapField
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.creators.zapsplits.ZapSplitIcon
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
@@ -55,7 +56,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.actions.MentionPreservingInputTransformation
|
||||
import com.vitorpamplona.amethyst.ui.actions.UrlUserTagOutputTransformation
|
||||
import com.vitorpamplona.amethyst.ui.components.OutlinedThinPaddingTextField
|
||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
@@ -35,14 +35,14 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedEmpty
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedError
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyGridState
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyListState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.viewmodels.FeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.feeds.FeedLoaded
|
||||
import com.vitorpamplona.amethyst.ui.feeds.PrefetchLoadedFeedMedia
|
||||
import com.vitorpamplona.amethyst.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -35,11 +35,11 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedEmpty
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedError
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
|
||||
+1
-1
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||
|
||||
import android.content.ComponentCallbacks2
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.commons.feeds.ChannelFeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.model.topNavFeeds.TopFilter
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.amethyst.ui.feeds.ChannelFeedContentState
|
||||
import com.vitorpamplona.amethyst.ui.screen.TopNavFilterState
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.articles.dal.ArticlesFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.dal.BadgesFeedFilter
|
||||
|
||||
+87
-44
@@ -43,17 +43,57 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
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.model.backups.BackupEventType
|
||||
import com.vitorpamplona.amethyst.commons.model.backups.ReplaceableBackupConflict
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_accept
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_and_added
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_and_blocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_and_followed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_and_joined
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_and_muted
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_app_settings
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_concord_emptied
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_concord_rewritten
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_dm_relays_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_feeds_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_follows_dropped
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_hashtags_unfollowed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_indexer_relays_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_key_package_relays_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_leave_chats
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_leave_communities
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_leave_groups
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_leave_rooms
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_mutes_visible
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_nip65_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_nutzap_key_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_nutzap_key_replaced
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_nutzap_mints_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_offers_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_payment_targets_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_places_unfollowed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_private_outbox_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_profile_lost_fields
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_relay_feeds_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_search_relays_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_trust_services_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_trusted_lost
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_unblocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_wallet_emptied
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_card_wallet_rewritten
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_count_added
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_count_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_count_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_changed_by_other_app
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.note.timeAgoNoDot
|
||||
@@ -79,6 +119,9 @@ import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListDiff
|
||||
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataDiff
|
||||
import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListDiff
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.offer.Bolt12OfferListDiff
|
||||
import org.jetbrains.compose.resources.PluralStringResource
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
|
||||
/**
|
||||
* Cards at the top of Home's feed, one per open [ReplaceableBackupConflict]: the user
|
||||
@@ -125,34 +168,34 @@ private fun headlineOf(
|
||||
when (diff) {
|
||||
// Counted, not "shrank": a version that drops 3 follows and adds 100 still raises
|
||||
// a conflict, and calling that a shrink contradicts the card's own bar.
|
||||
is ContactListDiff -> plural(R.plurals.backup_card_follows_dropped, diff.follows.removed.size)
|
||||
is MuteListDiff -> plural(R.plurals.backup_card_mutes_visible, diff.publicMutes.removed.size)
|
||||
is MetadataDiff -> plural(R.plurals.backup_card_profile_lost_fields, counts.removed)
|
||||
is AdvertisedRelayListDiff -> plural(R.plurals.backup_card_nip65_lost, diff.relays.removed.size)
|
||||
is ContactListDiff -> plural(Res.plurals.backup_card_follows_dropped, diff.follows.removed.size)
|
||||
is MuteListDiff -> plural(Res.plurals.backup_card_mutes_visible, diff.publicMutes.removed.size)
|
||||
is MetadataDiff -> plural(Res.plurals.backup_card_profile_lost_fields, counts.removed)
|
||||
is AdvertisedRelayListDiff -> plural(Res.plurals.backup_card_nip65_lost, diff.relays.removed.size)
|
||||
is RelayListDiff -> relayListHeadline(conflict.eventType, diff.relays.removed.size)
|
||||
is ChannelListDiff -> plural(R.plurals.backup_card_leave_chats, diff.channels.removed.size)
|
||||
is CommunityListDiff -> plural(R.plurals.backup_card_leave_communities, diff.communities.removed.size)
|
||||
is EphemeralChatListDiff -> plural(R.plurals.backup_card_leave_rooms, diff.rooms.removed.size)
|
||||
is SimpleGroupListDiff -> plural(R.plurals.backup_card_leave_groups, diff.groups.removed.size)
|
||||
is FavoriteAlgoFeedsListDiff -> plural(R.plurals.backup_card_feeds_removed, diff.feeds.removed.size)
|
||||
is HashtagListDiff -> plural(R.plurals.backup_card_hashtags_unfollowed, diff.hashtags.removed.size)
|
||||
is GeohashListDiff -> plural(R.plurals.backup_card_places_unfollowed, diff.geohashes.removed.size)
|
||||
is TrustProviderListDiff -> plural(R.plurals.backup_card_trust_services_changed, diff.providers.removed.size + diff.providers.changed.size)
|
||||
is ChannelListDiff -> plural(Res.plurals.backup_card_leave_chats, diff.channels.removed.size)
|
||||
is CommunityListDiff -> plural(Res.plurals.backup_card_leave_communities, diff.communities.removed.size)
|
||||
is EphemeralChatListDiff -> plural(Res.plurals.backup_card_leave_rooms, diff.rooms.removed.size)
|
||||
is SimpleGroupListDiff -> plural(Res.plurals.backup_card_leave_groups, diff.groups.removed.size)
|
||||
is FavoriteAlgoFeedsListDiff -> plural(Res.plurals.backup_card_feeds_removed, diff.feeds.removed.size)
|
||||
is HashtagListDiff -> plural(Res.plurals.backup_card_hashtags_unfollowed, diff.hashtags.removed.size)
|
||||
is GeohashListDiff -> plural(Res.plurals.backup_card_places_unfollowed, diff.geohashes.removed.size)
|
||||
is TrustProviderListDiff -> plural(Res.plurals.backup_card_trust_services_changed, diff.providers.removed.size + diff.providers.changed.size)
|
||||
is NutzapInfoDiff ->
|
||||
when {
|
||||
diff.p2pkPubkey?.after == null && diff.p2pkPubkey != null -> stringRes(R.string.backup_card_nutzap_key_removed)
|
||||
diff.p2pkPubkey != null -> stringRes(R.string.backup_card_nutzap_key_replaced)
|
||||
else -> plural(R.plurals.backup_card_nutzap_mints_removed, diff.mints.removed.size)
|
||||
diff.p2pkPubkey?.after == null && diff.p2pkPubkey != null -> stringRes(Res.string.backup_card_nutzap_key_removed)
|
||||
diff.p2pkPubkey != null -> stringRes(Res.string.backup_card_nutzap_key_replaced)
|
||||
else -> plural(Res.plurals.backup_card_nutzap_mints_removed, diff.mints.removed.size)
|
||||
}
|
||||
is PaymentTargetsDiff -> plural(R.plurals.backup_card_payment_targets_removed, diff.targets.removed.size)
|
||||
is Bolt12OfferListDiff -> plural(R.plurals.backup_card_offers_removed, diff.offers.removed.size)
|
||||
is CashuWalletDiff -> encryptedHeadline(R.string.backup_card_wallet_emptied, R.string.backup_card_wallet_rewritten, diff.wallet)
|
||||
is ConcordCommunityListDiff -> encryptedHeadline(R.string.backup_card_concord_emptied, R.string.backup_card_concord_rewritten, diff.communities)
|
||||
is AppSpecificDataDiff -> stringRes(R.string.backup_card_app_settings)
|
||||
is PaymentTargetsDiff -> plural(Res.plurals.backup_card_payment_targets_removed, diff.targets.removed.size)
|
||||
is Bolt12OfferListDiff -> plural(Res.plurals.backup_card_offers_removed, diff.offers.removed.size)
|
||||
is CashuWalletDiff -> encryptedHeadline(Res.string.backup_card_wallet_emptied, Res.string.backup_card_wallet_rewritten, diff.wallet)
|
||||
is ConcordCommunityListDiff -> encryptedHeadline(Res.string.backup_card_concord_emptied, Res.string.backup_card_concord_rewritten, diff.communities)
|
||||
is AppSpecificDataDiff -> stringRes(Res.string.backup_card_app_settings)
|
||||
else -> null
|
||||
}
|
||||
// A headline counting removed items reads wrong when only encrypted items were lost.
|
||||
if (specific.isNullOrEmpty()) return stringRes(R.string.backup_conflict_title, stringRes(eventTypeName(conflict.eventType)))
|
||||
if (specific.isNullOrEmpty()) return stringRes(Res.string.backup_conflict_title, stringRes(eventTypeName(conflict.eventType)))
|
||||
// Headlines lead with the loss; what the other app added to the same list is said too,
|
||||
// so a list that dropped 3 and gained 40 doesn't read as if it only shrank. The wording
|
||||
// follows the headline's: following people, muting, joining chats, blocking relays.
|
||||
@@ -160,11 +203,11 @@ private fun headlineOf(
|
||||
if (added <= 0) return specific
|
||||
val tail =
|
||||
when {
|
||||
diff is ContactListDiff -> R.plurals.backup_card_and_followed
|
||||
diff is MuteListDiff -> R.plurals.backup_card_and_muted
|
||||
diff is ChannelListDiff || diff is CommunityListDiff || diff is EphemeralChatListDiff || diff is SimpleGroupListDiff -> R.plurals.backup_card_and_joined
|
||||
conflict.eventType == BackupEventType.BLOCKED_RELAYS -> R.plurals.backup_card_and_blocked
|
||||
else -> R.plurals.backup_card_and_added
|
||||
diff is ContactListDiff -> Res.plurals.backup_card_and_followed
|
||||
diff is MuteListDiff -> Res.plurals.backup_card_and_muted
|
||||
diff is ChannelListDiff || diff is CommunityListDiff || diff is EphemeralChatListDiff || diff is SimpleGroupListDiff -> Res.plurals.backup_card_and_joined
|
||||
conflict.eventType == BackupEventType.BLOCKED_RELAYS -> Res.plurals.backup_card_and_blocked
|
||||
else -> Res.plurals.backup_card_and_added
|
||||
}
|
||||
return pluralStringResource(tail, added, specific, added)
|
||||
}
|
||||
@@ -208,7 +251,7 @@ private fun relayListHasHeadline(type: BackupEventType): Boolean =
|
||||
/** The count's plural, or "" when nothing of that kind was removed. */
|
||||
@Composable
|
||||
private fun plural(
|
||||
id: Int,
|
||||
id: PluralStringResource,
|
||||
count: Int,
|
||||
): String = if (count > 0) pluralStringResource(id, count, count) else ""
|
||||
|
||||
@@ -218,21 +261,21 @@ private fun relayListHeadline(
|
||||
removed: Int,
|
||||
): String =
|
||||
when (type) {
|
||||
BackupEventType.DM_RELAYS -> plural(R.plurals.backup_card_dm_relays_lost, removed)
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> plural(R.plurals.backup_card_key_package_relays_lost, removed)
|
||||
BackupEventType.SEARCH_RELAYS -> plural(R.plurals.backup_card_search_relays_lost, removed)
|
||||
BackupEventType.INDEXER_RELAYS -> plural(R.plurals.backup_card_indexer_relays_lost, removed)
|
||||
BackupEventType.RELAY_FEEDS -> plural(R.plurals.backup_card_relay_feeds_lost, removed)
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> plural(R.plurals.backup_card_private_outbox_lost, removed)
|
||||
BackupEventType.TRUSTED_RELAYS -> plural(R.plurals.backup_card_trusted_lost, removed)
|
||||
BackupEventType.BLOCKED_RELAYS -> plural(R.plurals.backup_card_unblocked, removed)
|
||||
BackupEventType.DM_RELAYS -> plural(Res.plurals.backup_card_dm_relays_lost, removed)
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> plural(Res.plurals.backup_card_key_package_relays_lost, removed)
|
||||
BackupEventType.SEARCH_RELAYS -> plural(Res.plurals.backup_card_search_relays_lost, removed)
|
||||
BackupEventType.INDEXER_RELAYS -> plural(Res.plurals.backup_card_indexer_relays_lost, removed)
|
||||
BackupEventType.RELAY_FEEDS -> plural(Res.plurals.backup_card_relay_feeds_lost, removed)
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> plural(Res.plurals.backup_card_private_outbox_lost, removed)
|
||||
BackupEventType.TRUSTED_RELAYS -> plural(Res.plurals.backup_card_trusted_lost, removed)
|
||||
BackupEventType.BLOCKED_RELAYS -> plural(Res.plurals.backup_card_unblocked, removed)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun encryptedHeadline(
|
||||
emptied: Int,
|
||||
rewritten: Int,
|
||||
emptied: StringResource,
|
||||
rewritten: StringResource,
|
||||
change: ContentChange,
|
||||
): String = if (change == ContentChange.CLEARED) stringRes(emptied) else stringRes(rewritten)
|
||||
|
||||
@@ -262,7 +305,7 @@ private fun LeadConflictCard(
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(headlineOf(conflict, counts), style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.Bold, maxLines = 3, overflow = TextOverflow.Ellipsis)
|
||||
Text(
|
||||
stringRes(R.string.backup_review_changed_by_other_app, timeAgoNoDot(conflict.cause.createdAt)),
|
||||
stringRes(Res.string.backup_review_changed_by_other_app, timeAgoNoDot(conflict.cause.createdAt)),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
@@ -296,9 +339,9 @@ private fun LeadConflictCard(
|
||||
private fun CountChips(counts: ConflictCounts) {
|
||||
val tones = conflictTones()
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
if (counts.removed > 0) StatusTag(stringRes(R.string.backup_conflict_count_removed, counts.removed.toString()), tones.removed)
|
||||
if (counts.added > 0) StatusTag(stringRes(R.string.backup_conflict_count_added, counts.added.toString()), tones.added)
|
||||
if (counts.changed > 0) StatusTag(stringRes(R.string.backup_conflict_count_changed, counts.changed.toString()), tones.changed)
|
||||
if (counts.removed > 0) StatusTag(stringRes(Res.string.backup_conflict_count_removed, counts.removed.toString()), tones.removed)
|
||||
if (counts.added > 0) StatusTag(stringRes(Res.string.backup_conflict_count_added, counts.added.toString()), tones.added)
|
||||
if (counts.changed > 0) StatusTag(stringRes(Res.string.backup_conflict_count_changed, counts.changed.toString()), tones.changed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +385,6 @@ private fun AcceptButton(onAccept: () -> Unit) {
|
||||
modifier = Modifier.height(36.dp),
|
||||
contentPadding = PaddingValues(horizontal = 14.dp),
|
||||
) {
|
||||
Text(stringRes(R.string.backup_card_accept), fontWeight = FontWeight.SemiBold)
|
||||
Text(stringRes(Res.string.backup_card_accept), fontWeight = FontWeight.SemiBold)
|
||||
}
|
||||
}
|
||||
|
||||
+129
-68
@@ -62,7 +62,6 @@ import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
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.model.backups.ReplaceableBackupConflict
|
||||
@@ -70,6 +69,67 @@ import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.routeFor
|
||||
import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_hashtag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_mint
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_nutzap_key
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_person
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_profile_field
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_thread
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_word
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_about
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_banner
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_birthday
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_bot
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_clink_offer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_display_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_lud06
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_lud16
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_nip05
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_picture
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_pronouns
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_website
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_demoted_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_dropped_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_dropped_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_gone
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_inbox
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_inbox_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_joined
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_kept_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_key_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_key_replaced
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_key_warning
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_left
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_left_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_names_and_more
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_newly_muted
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_not_set
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_nothing_here
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_outbox
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_outbox_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_added_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_added_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_changed_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_changed_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_wiped_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_private_wiped_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_renamed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_renamed_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_saved
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_search_people
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_tab_dropped
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_tab_edited
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_tab_new
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_units_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_unmuted
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_unmuted_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_was_named
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_words_and_hashtags
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.screen.LocalDisplaySettings
|
||||
@@ -111,6 +171,7 @@ import com.vitorpamplona.quartz.nip61Nutzaps.info.tags.NutzapMintTag
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListDiff
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayType
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
private const val GRID_COLUMNS = 4
|
||||
private const val PEOPLE_PREVIEW = 6
|
||||
@@ -168,7 +229,7 @@ private fun LazyListScope.followListItems(
|
||||
item(key = "follow-hero", contentType = "hero") {
|
||||
val tones = conflictTones()
|
||||
Column(Pad.padding(top = 8.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
HeroCounts(stringRes(R.string.backup_review_saved), saved, stringRes(R.string.backup_review_new), new)
|
||||
HeroCounts(stringRes(Res.string.backup_review_saved), saved, stringRes(Res.string.backup_review_new), new)
|
||||
SplitBar(
|
||||
listOf(
|
||||
BarSegment(saved - dropped, tones.kept),
|
||||
@@ -177,9 +238,9 @@ private fun LazyListScope.followListItems(
|
||||
),
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(14.dp)) {
|
||||
LegendItem(tones.kept, stringRes(R.string.backup_review_kept_count, (saved - dropped).toString()))
|
||||
LegendItem(tones.removed, stringRes(R.string.backup_review_dropped_count, dropped.toString()))
|
||||
LegendItem(tones.added, stringRes(R.string.backup_review_new_count, gained.toString()))
|
||||
LegendItem(tones.kept, stringRes(Res.string.backup_review_kept_count, (saved - dropped).toString()))
|
||||
LegendItem(tones.removed, stringRes(Res.string.backup_review_dropped_count, dropped.toString()))
|
||||
LegendItem(tones.added, stringRes(Res.string.backup_review_new_count, gained.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,9 +249,9 @@ private fun LazyListScope.followListItems(
|
||||
ReviewTabs(
|
||||
labels =
|
||||
listOf(
|
||||
stringRes(R.string.backup_review_tab_dropped, dropped.toString()),
|
||||
stringRes(R.string.backup_review_tab_new, gained.toString()),
|
||||
stringRes(R.string.backup_review_tab_edited, edited.toString()),
|
||||
stringRes(Res.string.backup_review_tab_dropped, dropped.toString()),
|
||||
stringRes(Res.string.backup_review_tab_new, gained.toString()),
|
||||
stringRes(Res.string.backup_review_tab_edited, edited.toString()),
|
||||
),
|
||||
selected = ui.tab,
|
||||
onSelect = {
|
||||
@@ -223,7 +284,7 @@ private fun LazyListScope.followListItems(
|
||||
|
||||
if (filtered.isEmpty()) {
|
||||
item(key = "follow-empty", contentType = "note") {
|
||||
DetailText(stringRes(R.string.backup_review_nothing_here), Pad.padding(vertical = 24.dp))
|
||||
DetailText(stringRes(Res.string.backup_review_nothing_here), Pad.padding(vertical = 24.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,7 +420,7 @@ private fun PeopleSearch(
|
||||
singleLine = true,
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
leadingIcon = { Icon(symbol = MaterialSymbols.Search, contentDescription = null) },
|
||||
placeholder = { Text(stringRes(R.string.backup_review_search_people, count.toString())) },
|
||||
placeholder = { Text(stringRes(Res.string.backup_review_search_people, count.toString())) },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -388,15 +449,15 @@ private fun LazyListScope.muteListItems(
|
||||
Icon(symbol = MaterialSymbols.Shield, contentDescription = null, tint = tones.removed, modifier = Modifier.size(44.dp))
|
||||
Column {
|
||||
Text(
|
||||
stringRes(R.string.backup_review_unmuted, removed.size.toString()),
|
||||
stringRes(Res.string.backup_review_unmuted, removed.size.toString()),
|
||||
fontSize = 30.sp,
|
||||
lineHeight = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = tones.removed,
|
||||
)
|
||||
Text(stringRes(R.string.backup_review_unmuted_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
Text(stringRes(Res.string.backup_review_unmuted_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
if (added.isNotEmpty()) {
|
||||
Text(stringRes(R.string.backup_review_newly_muted, added.size.toString()), style = MaterialTheme.typography.bodySmall, color = tones.added)
|
||||
Text(stringRes(Res.string.backup_review_newly_muted, added.size.toString()), style = MaterialTheme.typography.bodySmall, color = tones.added)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,17 +467,17 @@ private fun LazyListScope.muteListItems(
|
||||
item(key = "mute-tiles", contentType = "tiles") {
|
||||
val tones = conflictTones()
|
||||
Row(Pad.padding(top = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
StatTile("−${people.size}", stringRes(R.string.backup_entry_person), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${words.size}", stringRes(R.string.backup_entry_word), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${hashtags.size}", stringRes(R.string.backup_entry_hashtag), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${threads.size}", stringRes(R.string.backup_entry_thread), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${people.size}", stringRes(Res.string.backup_entry_person), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${words.size}", stringRes(Res.string.backup_entry_word), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${hashtags.size}", stringRes(Res.string.backup_entry_hashtag), tones.removed, Modifier.weight(1f))
|
||||
StatTile("−${threads.size}", stringRes(Res.string.backup_entry_thread), tones.removed, Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
|
||||
if (people.isNotEmpty()) {
|
||||
item(key = "mute-people", contentType = "facepile") {
|
||||
Column(Pad.padding(top = 18.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
SectionCaption(stringRes(R.string.backup_entry_person))
|
||||
SectionCaption(stringRes(Res.string.backup_entry_person))
|
||||
FacePile(people, accountViewModel) { ui.showAllPeople = !ui.showAllPeople }
|
||||
}
|
||||
}
|
||||
@@ -427,7 +488,7 @@ private fun LazyListScope.muteListItems(
|
||||
item(key = "mute-words", contentType = "pills") {
|
||||
val tones = conflictTones()
|
||||
Column(Pad.padding(top = 18.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
SectionCaption(stringRes(R.string.backup_review_words_and_hashtags))
|
||||
SectionCaption(stringRes(Res.string.backup_review_words_and_hashtags))
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
(words.map { "\"$it\"" } + hashtags).forEach { StruckPill(it, tones.removed) }
|
||||
}
|
||||
@@ -436,7 +497,7 @@ private fun LazyListScope.muteListItems(
|
||||
}
|
||||
|
||||
if (threads.isNotEmpty()) {
|
||||
item(key = "mute-threads-caption", contentType = "caption") { SectionCaption(stringRes(R.string.backup_entry_thread), Pad.padding(top = 18.dp)) }
|
||||
item(key = "mute-threads-caption", contentType = "caption") { SectionCaption(stringRes(Res.string.backup_entry_thread), Pad.padding(top = 18.dp)) }
|
||||
items(threads, key = { "mute-thread-$it" }, contentType = { "note" }) { id ->
|
||||
LoadNote(id) { note ->
|
||||
if (note != null) {
|
||||
@@ -463,7 +524,7 @@ private fun FacePile(
|
||||
val names = people.take(2).map { observedName(it, accountViewModel) }
|
||||
val summary =
|
||||
if (people.size > 2) {
|
||||
stringRes(R.string.backup_review_names_and_more, names.joinToString(", "), (people.size - 2).toString())
|
||||
stringRes(Res.string.backup_review_names_and_more, names.joinToString(", "), (people.size - 2).toString())
|
||||
} else {
|
||||
names.joinToString(", ")
|
||||
}
|
||||
@@ -564,9 +625,9 @@ internal fun PrivateItemsCard(
|
||||
val tones = conflictTones()
|
||||
val (title, body) =
|
||||
when (change) {
|
||||
ContentChange.CLEARED -> R.string.backup_review_private_wiped_title to R.string.backup_review_private_wiped_body
|
||||
ContentChange.ADDED -> R.string.backup_review_private_added_title to R.string.backup_review_private_added_body
|
||||
else -> R.string.backup_review_private_changed_title to R.string.backup_review_private_changed_body
|
||||
ContentChange.CLEARED -> Res.string.backup_review_private_wiped_title to Res.string.backup_review_private_wiped_body
|
||||
ContentChange.ADDED -> Res.string.backup_review_private_added_title to Res.string.backup_review_private_added_body
|
||||
else -> Res.string.backup_review_private_changed_title to Res.string.backup_review_private_changed_body
|
||||
}
|
||||
Row(
|
||||
modifier
|
||||
@@ -592,28 +653,28 @@ internal fun PrivateItemsCard(
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
private class ProfileField(
|
||||
val labelRes: Int,
|
||||
val labelRes: StringResource,
|
||||
val change: ValueChange<String>,
|
||||
val isImage: Boolean = false,
|
||||
)
|
||||
|
||||
private fun profileFields(diff: MetadataDiff): List<ProfileField> =
|
||||
listOfNotNull(
|
||||
diff.picture?.let { ProfileField(R.string.backup_profile_field_picture, it, isImage = true) },
|
||||
diff.banner?.let { ProfileField(R.string.backup_profile_field_banner, it, isImage = true) },
|
||||
diff.name?.let { ProfileField(R.string.backup_profile_field_name, it) },
|
||||
diff.displayName?.let { ProfileField(R.string.backup_profile_field_display_name, it) },
|
||||
diff.about?.let { ProfileField(R.string.backup_profile_field_about, it) },
|
||||
diff.nip05?.let { ProfileField(R.string.backup_profile_field_nip05, it) },
|
||||
diff.website?.let { ProfileField(R.string.backup_profile_field_website, it) },
|
||||
diff.lud16?.let { ProfileField(R.string.backup_profile_field_lud16, it) },
|
||||
diff.lud06?.let { ProfileField(R.string.backup_profile_field_lud06, it) },
|
||||
diff.clinkOffer?.let { ProfileField(R.string.backup_profile_field_clink_offer, it) },
|
||||
diff.pronouns?.let { ProfileField(R.string.backup_profile_field_pronouns, it) },
|
||||
diff.bot?.let { ProfileField(R.string.backup_profile_field_bot, ValueChange(it.before?.toString(), it.after?.toString())) },
|
||||
diff.picture?.let { ProfileField(Res.string.backup_profile_field_picture, it, isImage = true) },
|
||||
diff.banner?.let { ProfileField(Res.string.backup_profile_field_banner, it, isImage = true) },
|
||||
diff.name?.let { ProfileField(Res.string.backup_profile_field_name, it) },
|
||||
diff.displayName?.let { ProfileField(Res.string.backup_profile_field_display_name, it) },
|
||||
diff.about?.let { ProfileField(Res.string.backup_profile_field_about, it) },
|
||||
diff.nip05?.let { ProfileField(Res.string.backup_profile_field_nip05, it) },
|
||||
diff.website?.let { ProfileField(Res.string.backup_profile_field_website, it) },
|
||||
diff.lud16?.let { ProfileField(Res.string.backup_profile_field_lud16, it) },
|
||||
diff.lud06?.let { ProfileField(Res.string.backup_profile_field_lud06, it) },
|
||||
diff.clinkOffer?.let { ProfileField(Res.string.backup_profile_field_clink_offer, it) },
|
||||
diff.pronouns?.let { ProfileField(Res.string.backup_profile_field_pronouns, it) },
|
||||
diff.bot?.let { ProfileField(Res.string.backup_profile_field_bot, ValueChange(it.before?.toString(), it.after?.toString())) },
|
||||
diff.birthday?.let {
|
||||
ProfileField(
|
||||
R.string.backup_profile_field_birthday,
|
||||
Res.string.backup_profile_field_birthday,
|
||||
ValueChange(
|
||||
it.before?.let { b -> listOfNotNull(b.year, b.month, b.day).joinToString("-") },
|
||||
it.after?.let { a -> listOfNotNull(a.year, a.month, a.day).joinToString("-") },
|
||||
@@ -636,8 +697,8 @@ private fun LazyListScope.profileItems(
|
||||
item(key = "profile-cards", contentType = "profile-cards") {
|
||||
val tones = conflictTones()
|
||||
Row(Pad.padding(top = 8.dp), horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
MiniProfileCard(saved, pubKey, stringRes(R.string.backup_review_saved), MaterialTheme.colorScheme.outlineVariant, accountViewModel, Modifier.weight(1f))
|
||||
MiniProfileCard(incoming, pubKey, stringRes(R.string.backup_review_new), tones.removed.copy(alpha = 0.5f), accountViewModel, Modifier.weight(1f))
|
||||
MiniProfileCard(saved, pubKey, stringRes(Res.string.backup_review_saved), MaterialTheme.colorScheme.outlineVariant, accountViewModel, Modifier.weight(1f))
|
||||
MiniProfileCard(incoming, pubKey, stringRes(Res.string.backup_review_new), tones.removed.copy(alpha = 0.5f), accountViewModel, Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,7 +717,7 @@ private fun LazyListScope.profileItems(
|
||||
}
|
||||
}
|
||||
// Linked identities and fields this app doesn't model use the generic sections.
|
||||
genericDiffItems(buildRows(presentation, skipGroups = setOf(R.string.backup_entry_profile_field)), accountViewModel, nav)
|
||||
genericDiffItems(buildRows(presentation, skipGroups = setOf(Res.string.backup_entry_profile_field)), accountViewModel, nav)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -735,10 +796,10 @@ private fun FlowRowDiff(
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(6.dp), itemVerticalAlignment = Alignment.CenterVertically) {
|
||||
if (before != null) DiffChip(clip(before), tones.removed, struck = true)
|
||||
when {
|
||||
after == null -> StatusTag(stringRes(R.string.backup_review_gone), tones.removed)
|
||||
after == null -> StatusTag(stringRes(Res.string.backup_review_gone), tones.removed)
|
||||
before == null -> {
|
||||
DiffChip(clip(after), tones.added, struck = false)
|
||||
StatusTag(stringRes(R.string.backup_review_new_tag), tones.added)
|
||||
StatusTag(stringRes(Res.string.backup_review_new_tag), tones.added)
|
||||
}
|
||||
else -> {
|
||||
Text("→", color = MaterialTheme.colorScheme.placeholderText)
|
||||
@@ -779,7 +840,7 @@ private fun ImageThumb(
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (url == null) {
|
||||
Text(stringRes(R.string.backup_review_not_set), style = MaterialTheme.typography.labelSmall, color = color)
|
||||
Text(stringRes(Res.string.backup_review_not_set), style = MaterialTheme.typography.labelSmall, color = color)
|
||||
} else {
|
||||
MyAsyncImage(
|
||||
imageUrl = url,
|
||||
@@ -843,14 +904,14 @@ private fun LazyListScope.nip65Items(
|
||||
val outbox = lane(saved, new, writes)
|
||||
val inbox = lane(saved, new, reads)
|
||||
|
||||
laneItems("outbox", stringRes = R.string.backup_review_outbox, subRes = R.string.backup_review_outbox_explainer, rows = outbox, nav = nav)
|
||||
laneItems("inbox", stringRes = R.string.backup_review_inbox, subRes = R.string.backup_review_inbox_explainer, rows = inbox, nav = nav)
|
||||
laneItems("outbox", stringRes = Res.string.backup_review_outbox, subRes = Res.string.backup_review_outbox_explainer, rows = outbox, nav = nav)
|
||||
laneItems("inbox", stringRes = Res.string.backup_review_inbox, subRes = Res.string.backup_review_inbox_explainer, rows = inbox, nav = nav)
|
||||
}
|
||||
|
||||
private fun LazyListScope.laneItems(
|
||||
key: String,
|
||||
stringRes: Int,
|
||||
subRes: Int,
|
||||
stringRes: StringResource,
|
||||
subRes: StringResource,
|
||||
rows: List<LaneRow>,
|
||||
nav: INav,
|
||||
) {
|
||||
@@ -873,9 +934,9 @@ private fun LaneRelayRow(
|
||||
val (color, tag) =
|
||||
when (row.state) {
|
||||
LaneState.KEPT -> tones.kept to null
|
||||
LaneState.DROPPED -> tones.removed to R.string.backup_review_dropped_tag
|
||||
LaneState.ADDED -> tones.added to R.string.backup_review_new_tag
|
||||
LaneState.DEMOTED -> tones.changed to R.string.backup_review_demoted_tag
|
||||
LaneState.DROPPED -> tones.removed to Res.string.backup_review_dropped_tag
|
||||
LaneState.ADDED -> tones.added to Res.string.backup_review_new_tag
|
||||
LaneState.DEMOTED -> tones.changed to Res.string.backup_review_demoted_tag
|
||||
}
|
||||
Row(
|
||||
Pad
|
||||
@@ -933,12 +994,12 @@ private fun LazyListScope.nutzapItems(
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Icon(symbol = MaterialSymbols.Key, contentDescription = null, tint = tones.changed)
|
||||
Text(stringRes(if (key.after == null) R.string.backup_review_key_removed else R.string.backup_review_key_replaced), style = MaterialTheme.typography.titleSmall)
|
||||
Text(stringRes(if (key.after == null) Res.string.backup_review_key_removed else Res.string.backup_review_key_replaced), style = MaterialTheme.typography.titleSmall)
|
||||
}
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
|
||||
KeyColumn(key.before, stringRes(R.string.backup_review_saved), tones.kept)
|
||||
KeyColumn(key.before, stringRes(Res.string.backup_review_saved), tones.kept)
|
||||
Text("→", fontSize = 24.sp, color = MaterialTheme.colorScheme.placeholderText, modifier = Modifier.padding(horizontal = 18.dp))
|
||||
KeyColumn(key.after, stringRes(R.string.backup_review_new), tones.changed)
|
||||
KeyColumn(key.after, stringRes(Res.string.backup_review_new), tones.changed)
|
||||
}
|
||||
if (key.after != null) {
|
||||
Row(
|
||||
@@ -950,7 +1011,7 @@ private fun LazyListScope.nutzapItems(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(symbol = MaterialSymbols.Warning, contentDescription = null, tint = tones.changed, modifier = Modifier.size(18.dp))
|
||||
Text(stringRes(R.string.backup_review_key_warning), style = MaterialTheme.typography.bodySmall, color = tones.changed)
|
||||
Text(stringRes(Res.string.backup_review_key_warning), style = MaterialTheme.typography.bodySmall, color = tones.changed)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -976,10 +1037,10 @@ private fun LazyListScope.nutzapItems(
|
||||
} + diff.mints.added.map { Triple(it.mintUrl, it.units.joinToString(), LaneState.ADDED) }
|
||||
|
||||
if (mintRows.isNotEmpty()) {
|
||||
item(key = "nutzap-mints", contentType = "caption") { SectionCaption(stringRes(R.string.backup_entry_mint), Pad.padding(top = 18.dp, bottom = 6.dp)) }
|
||||
item(key = "nutzap-mints", contentType = "caption") { SectionCaption(stringRes(Res.string.backup_entry_mint), Pad.padding(top = 18.dp, bottom = 6.dp)) }
|
||||
items(mintRows, key = { "mint-" + it.first }, contentType = { "mint" }) { (url, units, state) -> MintRow(url, units, state) }
|
||||
}
|
||||
genericDiffItems(buildRows(presentation, skipGroups = setOf(R.string.backup_entry_mint, R.string.backup_entry_nutzap_key)), accountViewModel, nav)
|
||||
genericDiffItems(buildRows(presentation, skipGroups = setOf(Res.string.backup_entry_mint, Res.string.backup_entry_nutzap_key)), accountViewModel, nav)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -993,7 +1054,7 @@ private fun KeyColumn(
|
||||
KeyFingerprint(hex, color)
|
||||
} else {
|
||||
Box(Modifier.size(96.dp).clip(RoundedCornerShape(18.dp)).border(2.dp, color, RoundedCornerShape(18.dp)), contentAlignment = Alignment.Center) {
|
||||
Text(stringRes(R.string.backup_review_not_set), style = MaterialTheme.typography.labelSmall, color = color)
|
||||
Text(stringRes(Res.string.backup_review_not_set), style = MaterialTheme.typography.labelSmall, color = color)
|
||||
}
|
||||
}
|
||||
StatusTag(label, color)
|
||||
@@ -1010,9 +1071,9 @@ private fun MintRow(
|
||||
val (color, tag) =
|
||||
when (state) {
|
||||
LaneState.KEPT -> MaterialTheme.colorScheme.onSurface to null
|
||||
LaneState.DROPPED -> tones.removed to R.string.backup_review_dropped_tag
|
||||
LaneState.ADDED -> tones.added to R.string.backup_review_new_tag
|
||||
LaneState.DEMOTED -> tones.changed to R.string.backup_review_units_tag
|
||||
LaneState.DROPPED -> tones.removed to Res.string.backup_review_dropped_tag
|
||||
LaneState.ADDED -> tones.added to Res.string.backup_review_new_tag
|
||||
LaneState.DEMOTED -> tones.changed to Res.string.backup_review_units_tag
|
||||
}
|
||||
Row(
|
||||
Pad
|
||||
@@ -1083,21 +1144,21 @@ private fun LazyListScope.groupItems(
|
||||
StatTile(
|
||||
diff.groups.removed.size
|
||||
.toString(),
|
||||
stringRes(R.string.backup_review_left),
|
||||
stringRes(Res.string.backup_review_left),
|
||||
tones.removed,
|
||||
Modifier.weight(1f),
|
||||
)
|
||||
StatTile(
|
||||
diff.groups.added.size
|
||||
.toString(),
|
||||
stringRes(R.string.backup_review_joined),
|
||||
stringRes(Res.string.backup_review_joined),
|
||||
tones.added,
|
||||
Modifier.weight(1f),
|
||||
)
|
||||
StatTile(
|
||||
diff.groups.changed.size
|
||||
.toString(),
|
||||
stringRes(R.string.backup_review_renamed),
|
||||
stringRes(Res.string.backup_review_renamed),
|
||||
tones.changed,
|
||||
Modifier.weight(1f),
|
||||
)
|
||||
@@ -1165,7 +1226,7 @@ private fun GroupTileContent(
|
||||
Column {
|
||||
Text(name, style = MaterialTheme.typography.titleSmall, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
Text(
|
||||
tile.oldName?.let { stringRes(R.string.backup_review_was_named, it) } ?: tile.group.relayUrl
|
||||
tile.oldName?.let { stringRes(Res.string.backup_review_was_named, it) } ?: tile.group.relayUrl
|
||||
.removePrefix("wss://")
|
||||
.removeSuffix("/"),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
@@ -1176,9 +1237,9 @@ private fun GroupTileContent(
|
||||
}
|
||||
}
|
||||
when (tile.state) {
|
||||
LaneState.DROPPED -> StatusTag(stringRes(R.string.backup_review_left_tag), tones.removed, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.ADDED -> StatusTag(stringRes(R.string.backup_review_new_tag), tones.added, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.DEMOTED -> StatusTag(stringRes(R.string.backup_review_renamed_tag), tones.changed, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.DROPPED -> StatusTag(stringRes(Res.string.backup_review_left_tag), tones.removed, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.ADDED -> StatusTag(stringRes(Res.string.backup_review_new_tag), tones.added, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.DEMOTED -> StatusTag(stringRes(Res.string.backup_review_renamed_tag), tones.changed, Modifier.align(Alignment.TopEnd))
|
||||
LaneState.KEPT -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+102
-54
@@ -48,13 +48,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
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.MaterialSymbol
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
@@ -63,6 +61,53 @@ import com.vitorpamplona.amethyst.commons.model.backups.ReplaceableBackupConflic
|
||||
import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.routeFor
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_allowed_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_concord_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_demoted_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_dropped_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_encrypted_added
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_encrypted_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_encrypted_cleared
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_feed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_hashtags_you_follow
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_joined
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_kept
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_left
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_left_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_listed_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_moved_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new_count_caption
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_new_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_newly_blocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_no_longer_blocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_offer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_offers_gone
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_payment_targets_gone
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_payments_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_places_gone
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_places_you_follow
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_receiving_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_saved
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_searching_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_service
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_service_followers
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_service_rank
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_service_topics
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_services_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_services_changed_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_still_blocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_storing_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_topics_gone
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_trust_warning
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_trusted_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_unblocked
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_unblocked_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_untrusted_tag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_wallet_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_communities
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_public_chats
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.screen.LocalDisplaySettings
|
||||
@@ -118,6 +163,9 @@ import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListEve
|
||||
import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.offer.Bolt12OfferListDiff
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.offer.Bolt12OfferListEvent
|
||||
import org.jetbrains.compose.resources.PluralStringResource
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
|
||||
/**
|
||||
* Per-event layouts for the account's other lists: each relay list framed by what it is
|
||||
@@ -142,8 +190,8 @@ internal fun LazyListScope.listDiffItems(
|
||||
is TrustProviderListDiff -> trustProviderItems(diff, conflict, accountViewModel, nav)
|
||||
is PaymentTargetsDiff -> paymentTargetItems(diff, conflict)
|
||||
is Bolt12OfferListDiff -> offerItems(diff, conflict)
|
||||
is CashuWalletDiff -> encryptedOnlyItems(MaterialSymbols.AccountBalanceWallet, diff.wallet, R.string.backup_review_wallet_body)
|
||||
is ConcordCommunityListDiff -> encryptedOnlyItems(MaterialSymbols.Groups, diff.communities, R.string.backup_review_concord_body)
|
||||
is CashuWalletDiff -> encryptedOnlyItems(MaterialSymbols.AccountBalanceWallet, diff.wallet, Res.string.backup_review_wallet_body)
|
||||
is ConcordCommunityListDiff -> encryptedOnlyItems(MaterialSymbols.Groups, diff.communities, Res.string.backup_review_concord_body)
|
||||
else -> return false
|
||||
}
|
||||
return true
|
||||
@@ -193,15 +241,15 @@ private fun fateColor(fate: ItemFate): Color {
|
||||
|
||||
private fun <T> LazyListScope.countTiles(
|
||||
items: List<Pair<T, ItemFate>>,
|
||||
removedCaption: Int,
|
||||
addedCaption: Int,
|
||||
removedCaption: StringResource,
|
||||
addedCaption: StringResource,
|
||||
) {
|
||||
item(key = "count-tiles", contentType = "tiles") {
|
||||
val tones = conflictTones()
|
||||
Row(Pad.padding(top = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
StatTile(items.count { it.second == ItemFate.DROPPED }.toString(), stringRes(removedCaption), tones.removed, Modifier.weight(1f))
|
||||
StatTile(items.count { it.second == ItemFate.ADDED }.toString(), stringRes(addedCaption), tones.added, Modifier.weight(1f))
|
||||
StatTile(items.count { it.second == ItemFate.KEPT || it.second == ItemFate.CHANGED }.toString(), stringRes(R.string.backup_review_kept), tones.kept, Modifier.weight(1f))
|
||||
StatTile(items.count { it.second == ItemFate.KEPT || it.second == ItemFate.CHANGED }.toString(), stringRes(Res.string.backup_review_kept), tones.kept, Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,20 +266,20 @@ private fun LazyListScope.privateItemsCard(change: ContentChange) {
|
||||
/** How a relay list's rows are presented: its icon and what a kept or dropped relay is called. */
|
||||
private class RelayFraming(
|
||||
val icon: MaterialSymbol,
|
||||
val keptTag: Int,
|
||||
val droppedTag: Int = R.string.backup_review_dropped_tag,
|
||||
val keptTag: StringResource,
|
||||
val droppedTag: StringResource = Res.string.backup_review_dropped_tag,
|
||||
)
|
||||
|
||||
private fun framingOf(type: BackupEventType): RelayFraming =
|
||||
when (type) {
|
||||
BackupEventType.DM_RELAYS -> RelayFraming(MaterialSymbols.Mail, R.string.backup_review_receiving_tag)
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> RelayFraming(MaterialSymbols.Key, R.string.backup_review_listed_tag)
|
||||
BackupEventType.SEARCH_RELAYS -> RelayFraming(MaterialSymbols.Search, R.string.backup_review_searching_tag)
|
||||
BackupEventType.INDEXER_RELAYS -> RelayFraming(MaterialSymbols.Dns, R.string.backup_review_listed_tag)
|
||||
BackupEventType.RELAY_FEEDS -> RelayFraming(MaterialSymbols.CellTower, R.string.backup_review_listed_tag)
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> RelayFraming(MaterialSymbols.Lock, R.string.backup_review_storing_tag)
|
||||
BackupEventType.TRUSTED_RELAYS -> RelayFraming(MaterialSymbols.Shield, R.string.backup_review_trusted_tag, R.string.backup_review_untrusted_tag)
|
||||
else -> RelayFraming(MaterialSymbols.Dns, R.string.backup_review_listed_tag)
|
||||
BackupEventType.DM_RELAYS -> RelayFraming(MaterialSymbols.Mail, Res.string.backup_review_receiving_tag)
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> RelayFraming(MaterialSymbols.Key, Res.string.backup_review_listed_tag)
|
||||
BackupEventType.SEARCH_RELAYS -> RelayFraming(MaterialSymbols.Search, Res.string.backup_review_searching_tag)
|
||||
BackupEventType.INDEXER_RELAYS -> RelayFraming(MaterialSymbols.Dns, Res.string.backup_review_listed_tag)
|
||||
BackupEventType.RELAY_FEEDS -> RelayFraming(MaterialSymbols.CellTower, Res.string.backup_review_listed_tag)
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> RelayFraming(MaterialSymbols.Lock, Res.string.backup_review_storing_tag)
|
||||
BackupEventType.TRUSTED_RELAYS -> RelayFraming(MaterialSymbols.Shield, Res.string.backup_review_trusted_tag, Res.string.backup_review_untrusted_tag)
|
||||
else -> RelayFraming(MaterialSymbols.Dns, Res.string.backup_review_listed_tag)
|
||||
}
|
||||
|
||||
private fun savedRelaysOf(event: Event): List<NormalizedRelayUrl> =
|
||||
@@ -277,8 +325,8 @@ private fun RelayFateRow(
|
||||
when (fate) {
|
||||
ItemFate.KEPT -> framing.keptTag
|
||||
ItemFate.DROPPED -> framing.droppedTag
|
||||
ItemFate.ADDED -> R.string.backup_review_new_tag
|
||||
ItemFate.CHANGED -> R.string.backup_review_demoted_tag
|
||||
ItemFate.ADDED -> Res.string.backup_review_new_tag
|
||||
ItemFate.CHANGED -> Res.string.backup_review_demoted_tag
|
||||
}
|
||||
Row(
|
||||
Pad
|
||||
@@ -320,14 +368,14 @@ private fun LazyListScope.blockedRelayItems(
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
Icon(symbol = MaterialSymbols.LockOpen, contentDescription = null, tint = tones.changed, modifier = Modifier.size(44.dp))
|
||||
Column {
|
||||
Text(stringRes(R.string.backup_review_unblocked, unblocked.size.toString()), fontSize = 30.sp, lineHeight = 32.sp, fontWeight = FontWeight.Bold, color = tones.changed)
|
||||
Text(stringRes(R.string.backup_review_unblocked_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
Text(stringRes(Res.string.backup_review_unblocked, unblocked.size.toString()), fontSize = 30.sp, lineHeight = 32.sp, fontWeight = FontWeight.Bold, color = tones.changed)
|
||||
Text(stringRes(Res.string.backup_review_unblocked_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unblocked.isNotEmpty()) {
|
||||
item(key = "unblocked-caption", contentType = "caption") { SectionCaption(stringRes(R.string.backup_review_no_longer_blocked), Pad.padding(top = 18.dp)) }
|
||||
item(key = "unblocked-caption", contentType = "caption") { SectionCaption(stringRes(Res.string.backup_review_no_longer_blocked), Pad.padding(top = 18.dp)) }
|
||||
items(unblocked, key = { "unblocked-" + it.url }, contentType = { "relay-row" }) { url ->
|
||||
val tones = conflictTones()
|
||||
Row(
|
||||
@@ -346,12 +394,12 @@ private fun LazyListScope.blockedRelayItems(
|
||||
Icon(symbol = MaterialSymbols.LockOpen, contentDescription = null, tint = tones.changed, modifier = Modifier.size(18.dp))
|
||||
}
|
||||
Text(url.url.removePrefix("wss://").removeSuffix("/"), modifier = Modifier.weight(1f), style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.SemiBold, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
StatusTag(stringRes(R.string.backup_review_allowed_tag), tones.changed)
|
||||
StatusTag(stringRes(Res.string.backup_review_allowed_tag), tones.changed)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newlyBlocked.isNotEmpty()) {
|
||||
item(key = "newly-blocked-caption", contentType = "caption") { SectionCaption(stringRes(R.string.backup_review_newly_blocked), Pad.padding(top = 18.dp)) }
|
||||
item(key = "newly-blocked-caption", contentType = "caption") { SectionCaption(stringRes(Res.string.backup_review_newly_blocked), Pad.padding(top = 18.dp)) }
|
||||
items(newlyBlocked, key = { "newly-blocked-" + it.url }, contentType = { "relay-row" }) { url ->
|
||||
RelayFateRow(url, ItemFate.ADDED, framingOf(BackupEventType.BLOCKED_RELAYS), nav)
|
||||
}
|
||||
@@ -359,7 +407,7 @@ private fun LazyListScope.blockedRelayItems(
|
||||
if (stillBlocked.isNotEmpty()) {
|
||||
item(key = "still-blocked", contentType = "chips") {
|
||||
Column(Pad.padding(top = 18.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
SectionCaption(stringRes(R.string.backup_review_still_blocked))
|
||||
SectionCaption(stringRes(Res.string.backup_review_still_blocked))
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
stillBlocked.forEach { url ->
|
||||
Row(
|
||||
@@ -392,7 +440,7 @@ private fun <T> LazyListScope.spaceGrid(
|
||||
key: (T) -> String,
|
||||
content: @Composable (T, ItemFate, Modifier) -> Unit,
|
||||
) {
|
||||
countTiles(items, R.string.backup_review_left, R.string.backup_review_joined)
|
||||
countTiles(items, Res.string.backup_review_left, Res.string.backup_review_joined)
|
||||
items(items.chunked(2), key = { keyPrefix + key(it.first().first) }, contentType = { "space-row" }) { row ->
|
||||
Row(Pad.padding(top = 10.dp).fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
row.forEach { (item, fate) -> content(item, fate, Modifier.weight(1f)) }
|
||||
@@ -436,9 +484,9 @@ private fun SpaceTile(
|
||||
}
|
||||
val tag =
|
||||
when (fate) {
|
||||
ItemFate.DROPPED -> R.string.backup_review_left_tag to tones.removed
|
||||
ItemFate.ADDED -> R.string.backup_review_new_tag to tones.added
|
||||
ItemFate.CHANGED -> R.string.backup_review_moved_tag to tones.changed
|
||||
ItemFate.DROPPED -> Res.string.backup_review_left_tag to tones.removed
|
||||
ItemFate.ADDED -> Res.string.backup_review_new_tag to tones.added
|
||||
ItemFate.CHANGED -> Res.string.backup_review_moved_tag to tones.changed
|
||||
ItemFate.KEPT -> null
|
||||
}
|
||||
tag?.let { (res, color) -> StatusTag(stringRes(res), color, Modifier.align(Alignment.TopEnd)) }
|
||||
@@ -459,7 +507,7 @@ private fun LazyListScope.publicChatItems(
|
||||
val current = state?.channel ?: channel
|
||||
SpaceTile(
|
||||
name = current.toBestDisplayName(),
|
||||
subtitle = stringRes(R.string.backup_type_public_chats),
|
||||
subtitle = stringRes(Res.string.backup_type_public_chats),
|
||||
robot = tag.eventId,
|
||||
picture = channel.profilePicture(),
|
||||
fate = fate,
|
||||
@@ -525,7 +573,7 @@ private fun AddressableSpaceTile(
|
||||
}
|
||||
SpaceTile(
|
||||
name = name ?: address.dTag.ifBlank { address.toValue().toShortDisplay() },
|
||||
subtitle = stringRes(if (address.kind == AppDefinitionEvent.KIND) R.string.backup_review_feed else R.string.backup_type_communities),
|
||||
subtitle = stringRes(if (address.kind == AppDefinitionEvent.KIND) Res.string.backup_review_feed else Res.string.backup_type_communities),
|
||||
robot = address.toValue(),
|
||||
picture = picture,
|
||||
fate = fate,
|
||||
@@ -543,7 +591,7 @@ private fun LazyListScope.ephemeralRoomItems(
|
||||
) {
|
||||
val saved = (conflict.saved as? EphemeralChatListEvent)?.publicRooms().orEmpty()
|
||||
val rooms = fates(saved, diff.rooms) { it }
|
||||
countTiles(rooms, R.string.backup_review_left, R.string.backup_review_joined)
|
||||
countTiles(rooms, Res.string.backup_review_left, Res.string.backup_review_joined)
|
||||
items(rooms, key = { "room-" + it.first.toKey() }, contentType = { "room-row" }) { (room, fate) -> RoomRow(room, fate, nav) }
|
||||
privateItemsCard(diff.privateItems)
|
||||
}
|
||||
@@ -582,8 +630,8 @@ private fun RoomRow(
|
||||
)
|
||||
}
|
||||
when (fate) {
|
||||
ItemFate.DROPPED -> StatusTag(stringRes(R.string.backup_review_left_tag), color)
|
||||
ItemFate.ADDED -> StatusTag(stringRes(R.string.backup_review_new_tag), color)
|
||||
ItemFate.DROPPED -> StatusTag(stringRes(Res.string.backup_review_left_tag), color)
|
||||
ItemFate.ADDED -> StatusTag(stringRes(Res.string.backup_review_new_tag), color)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -602,11 +650,11 @@ private fun LazyListScope.topicItems(
|
||||
nav: INav,
|
||||
) {
|
||||
val topics = fates(saved, diff) { it.lowercase() }
|
||||
countTiles(topics, if (isPlace) R.string.backup_review_places_gone else R.string.backup_review_topics_gone, R.string.backup_review_new_count_caption)
|
||||
countTiles(topics, if (isPlace) Res.string.backup_review_places_gone else Res.string.backup_review_topics_gone, Res.string.backup_review_new_count_caption)
|
||||
item(key = "topic-cloud", contentType = "cloud") {
|
||||
val tones = conflictTones()
|
||||
Column(Pad.padding(top = 18.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
SectionCaption(stringRes(if (isPlace) R.string.backup_review_places_you_follow else R.string.backup_review_hashtags_you_follow))
|
||||
SectionCaption(stringRes(if (isPlace) Res.string.backup_review_places_you_follow else Res.string.backup_review_hashtags_you_follow))
|
||||
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), itemVerticalAlignment = Alignment.CenterVertically) {
|
||||
topics.forEach { (topic, fate) ->
|
||||
val color = fateColor(fate)
|
||||
@@ -706,15 +754,15 @@ private fun LazyListScope.trustProviderItems(
|
||||
Icon(symbol = MaterialSymbols.Group, contentDescription = null, tint = tones.changed)
|
||||
}
|
||||
Column {
|
||||
Text(stringRes(R.string.backup_review_services_changed, affected.toString(), services.size.toString()), fontSize = 24.sp, lineHeight = 28.sp, fontWeight = FontWeight.Bold)
|
||||
Text(stringRes(R.string.backup_review_services_changed_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
Text(stringRes(Res.string.backup_review_services_changed, affected.toString(), services.size.toString()), fontSize = 24.sp, lineHeight = 28.sp, fontWeight = FontWeight.Bold)
|
||||
Text(stringRes(Res.string.backup_review_services_changed_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
item(key = "trust-header", contentType = "table-header") {
|
||||
Row(Pad.padding(top = 16.dp, bottom = 4.dp).padding(horizontal = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
listOf(R.string.backup_review_service, R.string.backup_review_saved, R.string.backup_review_new).forEachIndexed { index, res ->
|
||||
listOf(Res.string.backup_review_service, Res.string.backup_review_saved, Res.string.backup_review_new).forEachIndexed { index, res ->
|
||||
Text(stringRes(res).uppercase(), Modifier.weight(if (index == 0) 1.1f else 1f), style = MaterialTheme.typography.labelSmall, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.placeholderText)
|
||||
}
|
||||
}
|
||||
@@ -732,7 +780,7 @@ private fun LazyListScope.trustProviderItems(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(symbol = MaterialSymbols.Warning, contentDescription = null, tint = tones.changed, modifier = Modifier.size(18.dp))
|
||||
Text(stringRes(R.string.backup_review_trust_warning), style = MaterialTheme.typography.bodySmall, color = tones.changed)
|
||||
Text(stringRes(Res.string.backup_review_trust_warning), style = MaterialTheme.typography.bodySmall, color = tones.changed)
|
||||
}
|
||||
}
|
||||
privateItemsCard(diff.privateItems)
|
||||
@@ -771,9 +819,9 @@ private fun ServiceTableRow(
|
||||
@Composable
|
||||
private fun serviceLabel(type: String): String =
|
||||
when (type) {
|
||||
"rank" -> stringRes(R.string.backup_review_service_rank)
|
||||
"followers" -> stringRes(R.string.backup_review_service_followers)
|
||||
"t" -> stringRes(R.string.backup_review_service_topics)
|
||||
"rank" -> stringRes(Res.string.backup_review_service_rank)
|
||||
"followers" -> stringRes(Res.string.backup_review_service_followers)
|
||||
"t" -> stringRes(Res.string.backup_review_service_topics)
|
||||
else -> type.replace('_', ' ').replaceFirstChar { it.uppercase() }
|
||||
}
|
||||
|
||||
@@ -826,7 +874,7 @@ private fun LazyListScope.paymentTargetItems(
|
||||
) {
|
||||
val saved = (conflict.saved as? PaymentTargetsEvent)?.paymentTargets().orEmpty()
|
||||
val targets = fates(saved, diff.targets) { it }
|
||||
moneyHero(targets.count { it.second == ItemFate.DROPPED }, R.plurals.backup_review_payment_targets_gone)
|
||||
moneyHero(targets.count { it.second == ItemFate.DROPPED }, Res.plurals.backup_review_payment_targets_gone)
|
||||
items(targets, key = { "target-" + it.first.type + ":" + it.first.authority }, contentType = { "money-row" }) { (target, fate) -> PaymentTargetRow(target, fate) }
|
||||
}
|
||||
|
||||
@@ -836,15 +884,15 @@ private fun LazyListScope.offerItems(
|
||||
) {
|
||||
val saved = (conflict.saved as? Bolt12OfferListEvent)?.offers().orEmpty()
|
||||
val offers = fates(saved, diff.offers) { it }
|
||||
moneyHero(offers.count { it.second == ItemFate.DROPPED }, R.plurals.backup_review_offers_gone)
|
||||
moneyHero(offers.count { it.second == ItemFate.DROPPED }, Res.plurals.backup_review_offers_gone)
|
||||
items(offers, key = { "offer-" + it.first }, contentType = { "money-row" }) { (offer, fate) ->
|
||||
MoneyRow(stringRes(R.string.backup_review_offer), offer.toShortDisplay(prefixSize = 4), fate)
|
||||
MoneyRow(stringRes(Res.string.backup_review_offer), offer.toShortDisplay(prefixSize = 4), fate)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.moneyHero(
|
||||
dropped: Int,
|
||||
headline: Int,
|
||||
headline: PluralStringResource,
|
||||
) {
|
||||
item(key = "money-hero", contentType = "hero") {
|
||||
val tones = conflictTones()
|
||||
@@ -856,7 +904,7 @@ private fun LazyListScope.moneyHero(
|
||||
}
|
||||
Column {
|
||||
Text(pluralStringResource(headline, dropped, dropped), fontSize = 24.sp, lineHeight = 28.sp, fontWeight = FontWeight.Bold, color = color)
|
||||
Text(stringRes(R.string.backup_review_payments_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
Text(stringRes(Res.string.backup_review_payments_explainer), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.placeholderText)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -902,8 +950,8 @@ private fun MoneyRow(
|
||||
)
|
||||
}
|
||||
when (fate) {
|
||||
ItemFate.DROPPED -> StatusTag(stringRes(R.string.backup_review_dropped_tag), color)
|
||||
ItemFate.ADDED -> StatusTag(stringRes(R.string.backup_review_new_tag), color)
|
||||
ItemFate.DROPPED -> StatusTag(stringRes(Res.string.backup_review_dropped_tag), color)
|
||||
ItemFate.ADDED -> StatusTag(stringRes(Res.string.backup_review_new_tag), color)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -916,15 +964,15 @@ private fun MoneyRow(
|
||||
private fun LazyListScope.encryptedOnlyItems(
|
||||
icon: MaterialSymbol,
|
||||
change: ContentChange,
|
||||
body: Int,
|
||||
body: StringResource,
|
||||
) {
|
||||
item(key = "encrypted-hero", contentType = "hero") {
|
||||
val tones = conflictTones()
|
||||
val (color, headline) =
|
||||
when (change) {
|
||||
ContentChange.CLEARED -> tones.removed to R.string.backup_review_encrypted_cleared
|
||||
ContentChange.ADDED -> tones.added to R.string.backup_review_encrypted_added
|
||||
else -> tones.changed to R.string.backup_review_encrypted_changed
|
||||
ContentChange.CLEARED -> tones.removed to Res.string.backup_review_encrypted_cleared
|
||||
ContentChange.ADDED -> tones.added to Res.string.backup_review_encrypted_added
|
||||
else -> tones.changed to Res.string.backup_review_encrypted_changed
|
||||
}
|
||||
Column(Pad.padding(top = 8.dp), verticalArrangement = Arrangement.spacedBy(14.dp)) {
|
||||
TintedPanel(color.copy(alpha = 0.12f)) {
|
||||
|
||||
+237
-108
@@ -23,9 +23,98 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.backups
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.model.backups.BackupEventType
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_relay_read_only
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_relay_read_write
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_relay_write_only
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_algo_feed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_chat_room
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_community
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_hashtag
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_identity_claim
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_location
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_mint
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_nutzap_key
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_offer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_other
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_payment_target
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_person
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_profile_field
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_public_chat
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_relay
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_relay_group
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_thread
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_trust_provider
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_entry_word
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_about
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_banner
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_birthday
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_bot
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_clink_offer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_display_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_lud06
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_lud16
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_nip05
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_picture
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_pronouns
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_profile_field_website
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_app_settings
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_app_settings_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_blocked_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_blocked_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_bolt12_offers
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_bolt12_offers_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_cashu_wallet
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_cashu_wallet_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_communities
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_communities_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_concord_communities
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_concord_communities_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_dm_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_dm_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_ephemeral_chats
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_ephemeral_chats_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_favorite_algo_feeds
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_favorite_algo_feeds_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_follow_list
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_follow_list_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_geohashes
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_geohashes_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_hashtags
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_hashtags_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_indexer_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_indexer_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_key_package_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_key_package_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_mute_list
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_mute_list_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_nutzap_info
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_nutzap_info_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_other
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_other_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_outbox_inbox_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_outbox_inbox_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_payment_targets
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_payment_targets_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_private_outbox_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_private_outbox_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_profile
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_profile_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_public_chats
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_public_chats_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_relay_feeds
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_relay_feeds_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_relay_groups
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_relay_groups_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_search_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_search_relays_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_trust_providers
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_trust_providers_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_trusted_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_type_trusted_relays_explainer
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.concord.cord02Community.ConcordCommunityListDiff
|
||||
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
|
||||
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListDiff
|
||||
@@ -61,6 +150,7 @@ import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListDiff
|
||||
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataDiff
|
||||
import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListDiff
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.offer.Bolt12OfferListDiff
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
private const val MAX_VALUE_LENGTH = 80
|
||||
|
||||
@@ -168,7 +258,7 @@ sealed interface ReviewItem {
|
||||
/** One labelled group of differences (people, relays, profile fields…) of a conflict. */
|
||||
@Immutable
|
||||
class DiffGroup(
|
||||
val label: Int,
|
||||
val label: StringResource,
|
||||
val removed: List<ReviewItem>,
|
||||
val added: List<ReviewItem>,
|
||||
val changed: List<ReviewItem>,
|
||||
@@ -189,7 +279,7 @@ class DiffPresentation(
|
||||
|
||||
/** A group from a [ListDiff] of an event's parsed items. */
|
||||
private fun <T> listGroup(
|
||||
label: Int,
|
||||
label: StringResource,
|
||||
diff: ListDiff<T>,
|
||||
item: (T) -> ReviewItem,
|
||||
change: (ItemChange<T>) -> ReviewItem,
|
||||
@@ -197,7 +287,7 @@ private fun <T> listGroup(
|
||||
|
||||
/** A group whose items can't change, only be added or removed (hashtags, plain relays…). */
|
||||
private fun <T> listGroup(
|
||||
label: Int,
|
||||
label: StringResource,
|
||||
diff: ListDiff<T>,
|
||||
item: (T) -> ReviewItem,
|
||||
) = listGroup(label, diff, item) { item(it.after) }
|
||||
@@ -212,7 +302,7 @@ private inline fun <reified T> ListDiff<*>.only() =
|
||||
|
||||
/** A group from single-valued fields: a field set only after is added, only before is removed. */
|
||||
private fun fieldGroup(
|
||||
label: Int,
|
||||
label: StringResource,
|
||||
fields: List<Pair<String, ValueChange<String>?>>,
|
||||
): DiffGroup {
|
||||
val removed = mutableListOf<ReviewItem>()
|
||||
@@ -242,14 +332,53 @@ private fun arrow(
|
||||
*/
|
||||
@Composable
|
||||
fun rememberPresentation(diff: EventDiff): DiffPresentation {
|
||||
val resources = LocalResources.current
|
||||
return remember(diff, resources) { presentationOf(diff) { resources.getString(it) } }
|
||||
// Compose resources resolve only in composition (or suspended), so the labels
|
||||
// [presentationOf] writes into item text are resolved here and handed in. Only the
|
||||
// diff types that write labels get any, so the rest pay for no resource reads. The
|
||||
// map compares by value: a recomposition with the same locale keeps the cached result.
|
||||
val labels = labelsWrittenBy(diff).associateWith { stringRes(it) }
|
||||
return remember(diff, labels) { presentationOf(diff) { labels.getValue(it) } }
|
||||
}
|
||||
|
||||
/** Turns each event's own diff into typed, labelled groups. [str] resolves the labels. */
|
||||
/** Every label [presentationOf] resolves through its `str` parameter for [diff]. */
|
||||
internal fun labelsWrittenBy(diff: EventDiff): List<StringResource> =
|
||||
when (diff) {
|
||||
is MetadataDiff -> PROFILE_FIELD_LABELS
|
||||
is AdvertisedRelayListDiff -> RELAY_MARKER_LABELS
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
private val PROFILE_FIELD_LABELS =
|
||||
listOf(
|
||||
Res.string.backup_profile_field_name,
|
||||
Res.string.backup_profile_field_display_name,
|
||||
Res.string.backup_profile_field_about,
|
||||
Res.string.backup_profile_field_picture,
|
||||
Res.string.backup_profile_field_banner,
|
||||
Res.string.backup_profile_field_website,
|
||||
Res.string.backup_profile_field_nip05,
|
||||
Res.string.backup_profile_field_lud16,
|
||||
Res.string.backup_profile_field_lud06,
|
||||
Res.string.backup_profile_field_clink_offer,
|
||||
Res.string.backup_profile_field_pronouns,
|
||||
Res.string.backup_profile_field_birthday,
|
||||
Res.string.backup_profile_field_bot,
|
||||
)
|
||||
|
||||
private val RELAY_MARKER_LABELS =
|
||||
listOf(
|
||||
Res.string.backup_conflict_relay_read_write,
|
||||
Res.string.backup_conflict_relay_read_only,
|
||||
Res.string.backup_conflict_relay_write_only,
|
||||
)
|
||||
|
||||
/**
|
||||
* Turns each event's own diff into typed, labelled groups. [str] resolves the labels; a
|
||||
* label it asks for must be in [labelsWrittenBy] for that diff type.
|
||||
*/
|
||||
fun presentationOf(
|
||||
diff: EventDiff,
|
||||
str: (Int) -> String,
|
||||
str: (StringResource) -> String,
|
||||
): DiffPresentation {
|
||||
val (groups, content) =
|
||||
when (diff) {
|
||||
@@ -258,31 +387,31 @@ fun presentationOf(
|
||||
val bot = diff.bot?.let { ValueChange(it.before?.toString(), it.after?.toString()) }
|
||||
listOf(
|
||||
fieldGroup(
|
||||
R.string.backup_entry_profile_field,
|
||||
Res.string.backup_entry_profile_field,
|
||||
listOf(
|
||||
str(R.string.backup_profile_field_name) to diff.name,
|
||||
str(R.string.backup_profile_field_display_name) to diff.displayName,
|
||||
str(R.string.backup_profile_field_about) to diff.about,
|
||||
str(R.string.backup_profile_field_picture) to diff.picture,
|
||||
str(R.string.backup_profile_field_banner) to diff.banner,
|
||||
str(R.string.backup_profile_field_website) to diff.website,
|
||||
str(R.string.backup_profile_field_nip05) to diff.nip05,
|
||||
str(R.string.backup_profile_field_lud16) to diff.lud16,
|
||||
str(R.string.backup_profile_field_lud06) to diff.lud06,
|
||||
str(R.string.backup_profile_field_clink_offer) to diff.clinkOffer,
|
||||
str(R.string.backup_profile_field_pronouns) to diff.pronouns,
|
||||
str(R.string.backup_profile_field_birthday) to birthday,
|
||||
str(R.string.backup_profile_field_bot) to bot,
|
||||
str(Res.string.backup_profile_field_name) to diff.name,
|
||||
str(Res.string.backup_profile_field_display_name) to diff.displayName,
|
||||
str(Res.string.backup_profile_field_about) to diff.about,
|
||||
str(Res.string.backup_profile_field_picture) to diff.picture,
|
||||
str(Res.string.backup_profile_field_banner) to diff.banner,
|
||||
str(Res.string.backup_profile_field_website) to diff.website,
|
||||
str(Res.string.backup_profile_field_nip05) to diff.nip05,
|
||||
str(Res.string.backup_profile_field_lud16) to diff.lud16,
|
||||
str(Res.string.backup_profile_field_lud06) to diff.lud06,
|
||||
str(Res.string.backup_profile_field_clink_offer) to diff.clinkOffer,
|
||||
str(Res.string.backup_profile_field_pronouns) to diff.pronouns,
|
||||
str(Res.string.backup_profile_field_birthday) to birthday,
|
||||
str(Res.string.backup_profile_field_bot) to bot,
|
||||
),
|
||||
),
|
||||
listGroup(
|
||||
R.string.backup_entry_identity_claim,
|
||||
Res.string.backup_entry_identity_claim,
|
||||
diff.identityClaims,
|
||||
{ ReviewItem.Text(it.platformIdentity()) },
|
||||
{ ReviewItem.Text(it.after.platformIdentity(), arrow(it.before.proof, it.after.proof)) },
|
||||
),
|
||||
listGroup(
|
||||
R.string.backup_entry_other,
|
||||
Res.string.backup_entry_other,
|
||||
diff.otherFields,
|
||||
{ ReviewItem.Text(it.first, clip(it.second)) },
|
||||
{ ReviewItem.Text(it.after.first, clip(it.before.second) + " → " + clip(it.after.second)) },
|
||||
@@ -292,7 +421,7 @@ fun presentationOf(
|
||||
is ContactListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_person,
|
||||
Res.string.backup_entry_person,
|
||||
diff.follows,
|
||||
{ ReviewItem.Person(it.pubKey, it.petname) },
|
||||
{
|
||||
@@ -308,32 +437,32 @@ fun presentationOf(
|
||||
) to ContentChange.NONE
|
||||
is MuteListDiff ->
|
||||
listOf(
|
||||
listGroup(R.string.backup_entry_person, diff.publicMutes.only<UserTag>(), { ReviewItem.Person(it.pubKey) }),
|
||||
listGroup(R.string.backup_entry_word, diff.publicMutes.only<WordTag>(), { ReviewItem.Text("\"" + it.word + "\"") }),
|
||||
listGroup(R.string.backup_entry_hashtag, diff.publicMutes.only<HashtagTag>(), { ReviewItem.Text("#" + it.hashtag) }),
|
||||
listGroup(R.string.backup_entry_thread, diff.publicMutes.only<EventTag>(), { ReviewItem.Thread(it.eventId) }),
|
||||
listGroup(Res.string.backup_entry_person, diff.publicMutes.only<UserTag>(), { ReviewItem.Person(it.pubKey) }),
|
||||
listGroup(Res.string.backup_entry_word, diff.publicMutes.only<WordTag>(), { ReviewItem.Text("\"" + it.word + "\"") }),
|
||||
listGroup(Res.string.backup_entry_hashtag, diff.publicMutes.only<HashtagTag>(), { ReviewItem.Text("#" + it.hashtag) }),
|
||||
listGroup(Res.string.backup_entry_thread, diff.publicMutes.only<EventTag>(), { ReviewItem.Thread(it.eventId) }),
|
||||
) to diff.privateItems
|
||||
is AdvertisedRelayListDiff -> {
|
||||
val types =
|
||||
mapOf(
|
||||
AdvertisedRelayType.BOTH to str(R.string.backup_conflict_relay_read_write),
|
||||
AdvertisedRelayType.READ to str(R.string.backup_conflict_relay_read_only),
|
||||
AdvertisedRelayType.WRITE to str(R.string.backup_conflict_relay_write_only),
|
||||
AdvertisedRelayType.BOTH to str(Res.string.backup_conflict_relay_read_write),
|
||||
AdvertisedRelayType.READ to str(Res.string.backup_conflict_relay_read_only),
|
||||
AdvertisedRelayType.WRITE to str(Res.string.backup_conflict_relay_write_only),
|
||||
)
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_relay,
|
||||
Res.string.backup_entry_relay,
|
||||
diff.relays,
|
||||
{ ReviewItem.Relay(it.relayUrl, types[it.type]) },
|
||||
{ ReviewItem.Relay(it.after.relayUrl, arrow(types[it.before.type], types[it.after.type])) },
|
||||
),
|
||||
) to ContentChange.NONE
|
||||
}
|
||||
is RelayListDiff -> listOf(listGroup(R.string.backup_entry_relay, diff.relays, { ReviewItem.Relay(it) })) to diff.privateRelays
|
||||
is RelayListDiff -> listOf(listGroup(Res.string.backup_entry_relay, diff.relays, { ReviewItem.Relay(it) })) to diff.privateRelays
|
||||
is ChannelListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_public_chat,
|
||||
Res.string.backup_entry_public_chat,
|
||||
diff.channels,
|
||||
{ ReviewItem.PublicChat(it.eventId) },
|
||||
{ ReviewItem.PublicChat(it.after.eventId, arrow(it.before.relay?.url, it.after.relay?.url)) },
|
||||
@@ -342,28 +471,28 @@ fun presentationOf(
|
||||
is CommunityListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_community,
|
||||
Res.string.backup_entry_community,
|
||||
diff.communities,
|
||||
{ ReviewItem.Addressable(it.address) },
|
||||
{ ReviewItem.Addressable(it.after.address, arrow(it.before.relayHint?.url, it.after.relayHint?.url)) },
|
||||
),
|
||||
) to diff.privateItems
|
||||
is HashtagListDiff -> listOf(listGroup(R.string.backup_entry_hashtag, diff.hashtags, { ReviewItem.Text("#$it") })) to diff.privateItems
|
||||
is GeohashListDiff -> listOf(listGroup(R.string.backup_entry_location, diff.geohashes, { ReviewItem.Text(it) })) to diff.privateItems
|
||||
is HashtagListDiff -> listOf(listGroup(Res.string.backup_entry_hashtag, diff.hashtags, { ReviewItem.Text("#$it") })) to diff.privateItems
|
||||
is GeohashListDiff -> listOf(listGroup(Res.string.backup_entry_location, diff.geohashes, { ReviewItem.Text(it) })) to diff.privateItems
|
||||
is FavoriteAlgoFeedsListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_algo_feed,
|
||||
Res.string.backup_entry_algo_feed,
|
||||
diff.feeds,
|
||||
{ ReviewItem.Addressable(it.address) },
|
||||
{ ReviewItem.Addressable(it.after.address, arrow(it.before.relayHint?.url, it.after.relayHint?.url)) },
|
||||
),
|
||||
) to diff.privateItems
|
||||
is EphemeralChatListDiff -> listOf(listGroup(R.string.backup_entry_chat_room, diff.rooms, { ReviewItem.ChatRoom(it) })) to diff.privateItems
|
||||
is EphemeralChatListDiff -> listOf(listGroup(Res.string.backup_entry_chat_room, diff.rooms, { ReviewItem.ChatRoom(it) })) to diff.privateItems
|
||||
is SimpleGroupListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_relay_group,
|
||||
Res.string.backup_entry_relay_group,
|
||||
diff.groups,
|
||||
{ ReviewItem.Text(it.name ?: it.groupId, it.relayUrl) },
|
||||
{ ReviewItem.Text(it.after.name ?: it.after.groupId, arrow(it.before.name, it.after.name)) },
|
||||
@@ -372,7 +501,7 @@ fun presentationOf(
|
||||
is TrustProviderListDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_trust_provider,
|
||||
Res.string.backup_entry_trust_provider,
|
||||
diff.providers,
|
||||
{ ReviewItem.Person(it.pubkey, it.service.type) },
|
||||
{ ReviewItem.Person(it.after.pubkey, it.after.service.type + ": " + arrow(it.before.relayUrl.url, it.after.relayUrl.url)) },
|
||||
@@ -381,19 +510,19 @@ fun presentationOf(
|
||||
is NutzapInfoDiff ->
|
||||
listOf(
|
||||
listGroup(
|
||||
R.string.backup_entry_mint,
|
||||
Res.string.backup_entry_mint,
|
||||
diff.mints,
|
||||
{ ReviewItem.Text(it.mintUrl, it.units.joinToString().ifEmpty { null }) },
|
||||
{ ReviewItem.Text(it.after.mintUrl, arrow(it.before.units.joinToString(), it.after.units.joinToString())) },
|
||||
),
|
||||
listGroup(R.string.backup_entry_relay, diff.relays, { ReviewItem.Relay(it) }),
|
||||
listGroup(Res.string.backup_entry_relay, diff.relays, { ReviewItem.Relay(it) }),
|
||||
nutzapKeyGroup(diff.p2pkPubkey),
|
||||
) to ContentChange.NONE
|
||||
is PaymentTargetsDiff ->
|
||||
listOf(
|
||||
listGroup(R.string.backup_entry_payment_target, diff.targets, { ReviewItem.Text(it.type, clip(it.authority)) }),
|
||||
listGroup(Res.string.backup_entry_payment_target, diff.targets, { ReviewItem.Text(it.type, clip(it.authority)) }),
|
||||
) to ContentChange.NONE
|
||||
is Bolt12OfferListDiff -> listOf(listGroup(R.string.backup_entry_offer, diff.offers, { ReviewItem.Text(clip(it)) })) to ContentChange.NONE
|
||||
is Bolt12OfferListDiff -> listOf(listGroup(Res.string.backup_entry_offer, diff.offers, { ReviewItem.Text(clip(it)) })) to ContentChange.NONE
|
||||
is CashuWalletDiff -> emptyList<DiffGroup>() to diff.wallet
|
||||
is ConcordCommunityListDiff -> emptyList<DiffGroup>() to diff.communities
|
||||
is AppSpecificDataDiff -> emptyList<DiffGroup>() to diff.data
|
||||
@@ -404,13 +533,13 @@ fun presentationOf(
|
||||
|
||||
private fun nutzapKeyGroup(change: ValueChange<HexKey>?): DiffGroup {
|
||||
val none = emptyList<ReviewItem>()
|
||||
if (change == null) return DiffGroup(R.string.backup_entry_nutzap_key, none, none, none)
|
||||
if (change == null) return DiffGroup(Res.string.backup_entry_nutzap_key, none, none, none)
|
||||
val before = change.before
|
||||
val after = change.after
|
||||
return when {
|
||||
before != null && after == null -> DiffGroup(R.string.backup_entry_nutzap_key, listOf(ReviewItem.Text(before)), none, none)
|
||||
before == null && after != null -> DiffGroup(R.string.backup_entry_nutzap_key, none, listOf(ReviewItem.Text(after)), none)
|
||||
else -> DiffGroup(R.string.backup_entry_nutzap_key, none, none, listOf(ReviewItem.Text(arrow(before, after))))
|
||||
before != null && after == null -> DiffGroup(Res.string.backup_entry_nutzap_key, listOf(ReviewItem.Text(before)), none, none)
|
||||
before == null && after != null -> DiffGroup(Res.string.backup_entry_nutzap_key, none, listOf(ReviewItem.Text(after)), none)
|
||||
else -> DiffGroup(Res.string.backup_entry_nutzap_key, none, none, listOf(ReviewItem.Text(arrow(before, after))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,64 +551,64 @@ fun clip(text: String?): String {
|
||||
return if (oneLine.length > MAX_VALUE_LENGTH) oneLine.take(MAX_VALUE_LENGTH) + "…" else oneLine
|
||||
}
|
||||
|
||||
fun eventTypeName(type: BackupEventType): Int =
|
||||
fun eventTypeName(type: BackupEventType): StringResource =
|
||||
when (type) {
|
||||
BackupEventType.PROFILE -> R.string.backup_type_profile
|
||||
BackupEventType.FOLLOW_LIST -> R.string.backup_type_follow_list
|
||||
BackupEventType.MUTE_LIST -> R.string.backup_type_mute_list
|
||||
BackupEventType.OUTBOX_INBOX_RELAYS -> R.string.backup_type_outbox_inbox_relays
|
||||
BackupEventType.DM_RELAYS -> R.string.backup_type_dm_relays
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> R.string.backup_type_key_package_relays
|
||||
BackupEventType.SEARCH_RELAYS -> R.string.backup_type_search_relays
|
||||
BackupEventType.INDEXER_RELAYS -> R.string.backup_type_indexer_relays
|
||||
BackupEventType.RELAY_FEEDS -> R.string.backup_type_relay_feeds
|
||||
BackupEventType.BLOCKED_RELAYS -> R.string.backup_type_blocked_relays
|
||||
BackupEventType.TRUSTED_RELAYS -> R.string.backup_type_trusted_relays
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> R.string.backup_type_private_outbox_relays
|
||||
BackupEventType.APP_SETTINGS -> R.string.backup_type_app_settings
|
||||
BackupEventType.PUBLIC_CHATS -> R.string.backup_type_public_chats
|
||||
BackupEventType.COMMUNITIES -> R.string.backup_type_communities
|
||||
BackupEventType.HASHTAGS -> R.string.backup_type_hashtags
|
||||
BackupEventType.GEOHASHES -> R.string.backup_type_geohashes
|
||||
BackupEventType.FAVORITE_ALGO_FEEDS -> R.string.backup_type_favorite_algo_feeds
|
||||
BackupEventType.EPHEMERAL_CHATS -> R.string.backup_type_ephemeral_chats
|
||||
BackupEventType.RELAY_GROUPS -> R.string.backup_type_relay_groups
|
||||
BackupEventType.CONCORD_COMMUNITIES -> R.string.backup_type_concord_communities
|
||||
BackupEventType.TRUST_PROVIDERS -> R.string.backup_type_trust_providers
|
||||
BackupEventType.CASHU_WALLET -> R.string.backup_type_cashu_wallet
|
||||
BackupEventType.NUTZAP_INFO -> R.string.backup_type_nutzap_info
|
||||
BackupEventType.PAYMENT_TARGETS -> R.string.backup_type_payment_targets
|
||||
BackupEventType.BOLT12_OFFERS -> R.string.backup_type_bolt12_offers
|
||||
BackupEventType.OTHER -> R.string.backup_type_other
|
||||
BackupEventType.PROFILE -> Res.string.backup_type_profile
|
||||
BackupEventType.FOLLOW_LIST -> Res.string.backup_type_follow_list
|
||||
BackupEventType.MUTE_LIST -> Res.string.backup_type_mute_list
|
||||
BackupEventType.OUTBOX_INBOX_RELAYS -> Res.string.backup_type_outbox_inbox_relays
|
||||
BackupEventType.DM_RELAYS -> Res.string.backup_type_dm_relays
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> Res.string.backup_type_key_package_relays
|
||||
BackupEventType.SEARCH_RELAYS -> Res.string.backup_type_search_relays
|
||||
BackupEventType.INDEXER_RELAYS -> Res.string.backup_type_indexer_relays
|
||||
BackupEventType.RELAY_FEEDS -> Res.string.backup_type_relay_feeds
|
||||
BackupEventType.BLOCKED_RELAYS -> Res.string.backup_type_blocked_relays
|
||||
BackupEventType.TRUSTED_RELAYS -> Res.string.backup_type_trusted_relays
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> Res.string.backup_type_private_outbox_relays
|
||||
BackupEventType.APP_SETTINGS -> Res.string.backup_type_app_settings
|
||||
BackupEventType.PUBLIC_CHATS -> Res.string.backup_type_public_chats
|
||||
BackupEventType.COMMUNITIES -> Res.string.backup_type_communities
|
||||
BackupEventType.HASHTAGS -> Res.string.backup_type_hashtags
|
||||
BackupEventType.GEOHASHES -> Res.string.backup_type_geohashes
|
||||
BackupEventType.FAVORITE_ALGO_FEEDS -> Res.string.backup_type_favorite_algo_feeds
|
||||
BackupEventType.EPHEMERAL_CHATS -> Res.string.backup_type_ephemeral_chats
|
||||
BackupEventType.RELAY_GROUPS -> Res.string.backup_type_relay_groups
|
||||
BackupEventType.CONCORD_COMMUNITIES -> Res.string.backup_type_concord_communities
|
||||
BackupEventType.TRUST_PROVIDERS -> Res.string.backup_type_trust_providers
|
||||
BackupEventType.CASHU_WALLET -> Res.string.backup_type_cashu_wallet
|
||||
BackupEventType.NUTZAP_INFO -> Res.string.backup_type_nutzap_info
|
||||
BackupEventType.PAYMENT_TARGETS -> Res.string.backup_type_payment_targets
|
||||
BackupEventType.BOLT12_OFFERS -> Res.string.backup_type_bolt12_offers
|
||||
BackupEventType.OTHER -> Res.string.backup_type_other
|
||||
}
|
||||
|
||||
fun eventTypeExplainer(type: BackupEventType): Int =
|
||||
fun eventTypeExplainer(type: BackupEventType): StringResource =
|
||||
when (type) {
|
||||
BackupEventType.PROFILE -> R.string.backup_type_profile_explainer
|
||||
BackupEventType.FOLLOW_LIST -> R.string.backup_type_follow_list_explainer
|
||||
BackupEventType.MUTE_LIST -> R.string.backup_type_mute_list_explainer
|
||||
BackupEventType.OUTBOX_INBOX_RELAYS -> R.string.backup_type_outbox_inbox_relays_explainer
|
||||
BackupEventType.DM_RELAYS -> R.string.backup_type_dm_relays_explainer
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> R.string.backup_type_key_package_relays_explainer
|
||||
BackupEventType.SEARCH_RELAYS -> R.string.backup_type_search_relays_explainer
|
||||
BackupEventType.INDEXER_RELAYS -> R.string.backup_type_indexer_relays_explainer
|
||||
BackupEventType.RELAY_FEEDS -> R.string.backup_type_relay_feeds_explainer
|
||||
BackupEventType.BLOCKED_RELAYS -> R.string.backup_type_blocked_relays_explainer
|
||||
BackupEventType.TRUSTED_RELAYS -> R.string.backup_type_trusted_relays_explainer
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> R.string.backup_type_private_outbox_relays_explainer
|
||||
BackupEventType.APP_SETTINGS -> R.string.backup_type_app_settings_explainer
|
||||
BackupEventType.PUBLIC_CHATS -> R.string.backup_type_public_chats_explainer
|
||||
BackupEventType.COMMUNITIES -> R.string.backup_type_communities_explainer
|
||||
BackupEventType.HASHTAGS -> R.string.backup_type_hashtags_explainer
|
||||
BackupEventType.GEOHASHES -> R.string.backup_type_geohashes_explainer
|
||||
BackupEventType.FAVORITE_ALGO_FEEDS -> R.string.backup_type_favorite_algo_feeds_explainer
|
||||
BackupEventType.EPHEMERAL_CHATS -> R.string.backup_type_ephemeral_chats_explainer
|
||||
BackupEventType.RELAY_GROUPS -> R.string.backup_type_relay_groups_explainer
|
||||
BackupEventType.CONCORD_COMMUNITIES -> R.string.backup_type_concord_communities_explainer
|
||||
BackupEventType.TRUST_PROVIDERS -> R.string.backup_type_trust_providers_explainer
|
||||
BackupEventType.CASHU_WALLET -> R.string.backup_type_cashu_wallet_explainer
|
||||
BackupEventType.NUTZAP_INFO -> R.string.backup_type_nutzap_info_explainer
|
||||
BackupEventType.PAYMENT_TARGETS -> R.string.backup_type_payment_targets_explainer
|
||||
BackupEventType.BOLT12_OFFERS -> R.string.backup_type_bolt12_offers_explainer
|
||||
BackupEventType.OTHER -> R.string.backup_type_other_explainer
|
||||
BackupEventType.PROFILE -> Res.string.backup_type_profile_explainer
|
||||
BackupEventType.FOLLOW_LIST -> Res.string.backup_type_follow_list_explainer
|
||||
BackupEventType.MUTE_LIST -> Res.string.backup_type_mute_list_explainer
|
||||
BackupEventType.OUTBOX_INBOX_RELAYS -> Res.string.backup_type_outbox_inbox_relays_explainer
|
||||
BackupEventType.DM_RELAYS -> Res.string.backup_type_dm_relays_explainer
|
||||
BackupEventType.KEY_PACKAGE_RELAYS -> Res.string.backup_type_key_package_relays_explainer
|
||||
BackupEventType.SEARCH_RELAYS -> Res.string.backup_type_search_relays_explainer
|
||||
BackupEventType.INDEXER_RELAYS -> Res.string.backup_type_indexer_relays_explainer
|
||||
BackupEventType.RELAY_FEEDS -> Res.string.backup_type_relay_feeds_explainer
|
||||
BackupEventType.BLOCKED_RELAYS -> Res.string.backup_type_blocked_relays_explainer
|
||||
BackupEventType.TRUSTED_RELAYS -> Res.string.backup_type_trusted_relays_explainer
|
||||
BackupEventType.PRIVATE_OUTBOX_RELAYS -> Res.string.backup_type_private_outbox_relays_explainer
|
||||
BackupEventType.APP_SETTINGS -> Res.string.backup_type_app_settings_explainer
|
||||
BackupEventType.PUBLIC_CHATS -> Res.string.backup_type_public_chats_explainer
|
||||
BackupEventType.COMMUNITIES -> Res.string.backup_type_communities_explainer
|
||||
BackupEventType.HASHTAGS -> Res.string.backup_type_hashtags_explainer
|
||||
BackupEventType.GEOHASHES -> Res.string.backup_type_geohashes_explainer
|
||||
BackupEventType.FAVORITE_ALGO_FEEDS -> Res.string.backup_type_favorite_algo_feeds_explainer
|
||||
BackupEventType.EPHEMERAL_CHATS -> Res.string.backup_type_ephemeral_chats_explainer
|
||||
BackupEventType.RELAY_GROUPS -> Res.string.backup_type_relay_groups_explainer
|
||||
BackupEventType.CONCORD_COMMUNITIES -> Res.string.backup_type_concord_communities_explainer
|
||||
BackupEventType.TRUST_PROVIDERS -> Res.string.backup_type_trust_providers_explainer
|
||||
BackupEventType.CASHU_WALLET -> Res.string.backup_type_cashu_wallet_explainer
|
||||
BackupEventType.NUTZAP_INFO -> Res.string.backup_type_nutzap_info_explainer
|
||||
BackupEventType.PAYMENT_TARGETS -> Res.string.backup_type_payment_targets_explainer
|
||||
BackupEventType.BOLT12_OFFERS -> Res.string.backup_type_bolt12_offers_explainer
|
||||
BackupEventType.OTHER -> Res.string.backup_type_other_explainer
|
||||
}
|
||||
|
||||
+55
-31
@@ -59,11 +59,34 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
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.model.backups.BackupEventType
|
||||
import com.vitorpamplona.amethyst.commons.model.backups.ReplaceableBackupConflict
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.routeFor
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_block_again
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_keep_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_rejoin
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_remute
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_feeds
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_places
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_profile
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_providers
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_topics
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_action_restore_wallet
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_added
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_keep_new
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_private_added
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_private_changed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_private_cleared
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_removed
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_conflict_restore_mine
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_changed_by_other_app
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_title_cleared
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_review_title_updated
|
||||
import com.vitorpamplona.amethyst.commons.ui.insets.imePaddingSafe
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarWithBackButton
|
||||
@@ -97,22 +120,23 @@ import com.vitorpamplona.quartz.nip60Cashu.wallet.CashuWalletDiff
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListDiff
|
||||
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListDiff
|
||||
import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListDiff
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
/** A row of the review list, flattened so hundreds of entries scroll lazily. */
|
||||
@Immutable
|
||||
internal sealed interface ReviewRow {
|
||||
class Section(
|
||||
val titleRes: Int,
|
||||
val titleRes: StringResource,
|
||||
val count: Int,
|
||||
val tone: Tone,
|
||||
) : ReviewRow
|
||||
|
||||
class Note(
|
||||
val textRes: Int,
|
||||
val textRes: StringResource,
|
||||
) : ReviewRow
|
||||
|
||||
class Group(
|
||||
val labelRes: Int,
|
||||
val labelRes: StringResource,
|
||||
) : ReviewRow
|
||||
|
||||
class Entry(
|
||||
@@ -124,15 +148,15 @@ internal enum class Tone { REMOVED, ADDED, CHANGED }
|
||||
|
||||
internal fun buildRows(
|
||||
presentation: DiffPresentation,
|
||||
skipGroups: Set<Int> = emptySet(),
|
||||
skipGroups: Set<StringResource> = emptySet(),
|
||||
): List<ReviewRow> {
|
||||
val rows = mutableListOf<ReviewRow>()
|
||||
|
||||
fun section(
|
||||
titleRes: Int,
|
||||
titleRes: StringResource,
|
||||
count: Int,
|
||||
tone: Tone,
|
||||
contentNote: Int?,
|
||||
contentNote: StringResource?,
|
||||
items: (DiffGroup) -> List<ReviewItem>,
|
||||
) {
|
||||
if (count == 0 && contentNote == null) return
|
||||
@@ -149,9 +173,9 @@ internal fun buildRows(
|
||||
}
|
||||
|
||||
val content = presentation.content
|
||||
section(R.string.backup_conflict_removed, presentation.removedCount, Tone.REMOVED, R.string.backup_conflict_private_cleared.takeIf { content == ContentChange.CLEARED }) { it.removed }
|
||||
section(R.string.backup_conflict_added, presentation.addedCount, Tone.ADDED, R.string.backup_conflict_private_added.takeIf { content == ContentChange.ADDED }) { it.added }
|
||||
section(R.string.backup_conflict_changed, presentation.changedCount, Tone.CHANGED, R.string.backup_conflict_private_changed.takeIf { content == ContentChange.CHANGED }) { it.changed }
|
||||
section(Res.string.backup_conflict_removed, presentation.removedCount, Tone.REMOVED, Res.string.backup_conflict_private_cleared.takeIf { content == ContentChange.CLEARED }) { it.removed }
|
||||
section(Res.string.backup_conflict_added, presentation.addedCount, Tone.ADDED, Res.string.backup_conflict_private_added.takeIf { content == ContentChange.ADDED }) { it.added }
|
||||
section(Res.string.backup_conflict_changed, presentation.changedCount, Tone.CHANGED, Res.string.backup_conflict_private_changed.takeIf { content == ContentChange.CHANGED }) { it.changed }
|
||||
return rows
|
||||
}
|
||||
|
||||
@@ -268,7 +292,7 @@ internal fun LazyListScope.genericDiffItems(
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun GroupLabel(labelRes: Int) {
|
||||
internal fun GroupLabel(labelRes: StringResource) {
|
||||
Text(
|
||||
text = stringRes(labelRes),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
@@ -339,7 +363,7 @@ internal fun eventTitle(conflict: ReplaceableBackupConflict): String {
|
||||
val name = stringRes(eventTypeName(conflict.eventType)).replaceFirstChar { it.uppercase() }
|
||||
// Says what happened to it, not just what it is: "Community list updated".
|
||||
val emptied = conflict.incoming.tags.isEmpty() && conflict.incoming.content.isEmpty()
|
||||
return stringRes(if (emptied) R.string.backup_review_title_cleared else R.string.backup_review_title_updated, name)
|
||||
return stringRes(if (emptied) Res.string.backup_review_title_cleared else Res.string.backup_review_title_updated, name)
|
||||
}
|
||||
|
||||
/** The two choices, worded for what they do to this event: "Keep 120" / "Restore 523". */
|
||||
@@ -348,48 +372,48 @@ private fun actionLabels(conflict: ReplaceableBackupConflict): Pair<String, Stri
|
||||
when (val diff = conflict.diff) {
|
||||
is ContactListDiff -> {
|
||||
val (saved, new) = conflict.followCounts
|
||||
stringRes(R.string.backup_action_keep_count, new.toString()) to stringRes(R.string.backup_action_restore_count, saved.toString())
|
||||
stringRes(Res.string.backup_action_keep_count, new.toString()) to stringRes(Res.string.backup_action_restore_count, saved.toString())
|
||||
}
|
||||
is MuteListDiff -> {
|
||||
val removed = diff.publicMutes.removed.size
|
||||
stringRes(R.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(R.string.backup_action_remute, removed.toString()) else stringRes(R.string.backup_conflict_restore_mine)
|
||||
stringRes(Res.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(Res.string.backup_action_remute, removed.toString()) else stringRes(Res.string.backup_conflict_restore_mine)
|
||||
}
|
||||
is SimpleGroupListDiff -> {
|
||||
val removed = diff.groups.removed.size
|
||||
stringRes(R.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(R.string.backup_action_rejoin, removed.toString()) else stringRes(R.string.backup_conflict_restore_mine)
|
||||
stringRes(Res.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(Res.string.backup_action_rejoin, removed.toString()) else stringRes(Res.string.backup_conflict_restore_mine)
|
||||
}
|
||||
is MetadataDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_profile)
|
||||
is MetadataDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_profile)
|
||||
is RelayListDiff ->
|
||||
if (conflict.eventType == BackupEventType.BLOCKED_RELAYS && diff.relays.removed.isNotEmpty()) {
|
||||
stringRes(R.string.backup_conflict_keep_new) to
|
||||
stringRes(Res.string.backup_conflict_keep_new) to
|
||||
stringRes(
|
||||
R.string.backup_action_block_again,
|
||||
Res.string.backup_action_block_again,
|
||||
diff.relays.removed.size
|
||||
.toString(),
|
||||
)
|
||||
} else {
|
||||
stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_relays)
|
||||
stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_relays)
|
||||
}
|
||||
is AdvertisedRelayListDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_relays)
|
||||
is AdvertisedRelayListDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_relays)
|
||||
is ChannelListDiff -> rejoinLabels(diff.channels.removed.size)
|
||||
is CommunityListDiff -> rejoinLabels(diff.communities.removed.size)
|
||||
is EphemeralChatListDiff -> rejoinLabels(diff.rooms.removed.size)
|
||||
is FavoriteAlgoFeedsListDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_feeds)
|
||||
is HashtagListDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_topics)
|
||||
is FavoriteAlgoFeedsListDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_feeds)
|
||||
is HashtagListDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_topics)
|
||||
// Geohashes are places, not topics: the screen counts "places gone" under "Followed
|
||||
// locations", so the button has to agree with the page it sits on.
|
||||
is GeohashListDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_places)
|
||||
is TrustProviderListDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_providers)
|
||||
is CashuWalletDiff -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_action_restore_wallet)
|
||||
else -> stringRes(R.string.backup_conflict_keep_new) to stringRes(R.string.backup_conflict_restore_mine)
|
||||
is GeohashListDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_places)
|
||||
is TrustProviderListDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_providers)
|
||||
is CashuWalletDiff -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_action_restore_wallet)
|
||||
else -> stringRes(Res.string.backup_conflict_keep_new) to stringRes(Res.string.backup_conflict_restore_mine)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rejoinLabels(removed: Int): Pair<String, String> =
|
||||
stringRes(R.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(R.string.backup_action_rejoin, removed.toString()) else stringRes(R.string.backup_conflict_restore_mine)
|
||||
stringRes(Res.string.backup_conflict_keep_new) to
|
||||
if (removed > 0) stringRes(Res.string.backup_action_rejoin, removed.toString()) else stringRes(Res.string.backup_conflict_restore_mine)
|
||||
|
||||
/** When the other app changed it, and what the event is for. */
|
||||
@Composable
|
||||
@@ -399,7 +423,7 @@ private fun BackupConflictIntro(
|
||||
) {
|
||||
Column(modifier, verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
Text(
|
||||
text = stringRes(R.string.backup_review_changed_by_other_app, timeAgoNoDot(conflict.cause.createdAt)),
|
||||
text = stringRes(Res.string.backup_review_changed_by_other_app, timeAgoNoDot(conflict.cause.createdAt)),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = conflictTones().removed,
|
||||
)
|
||||
|
||||
+1
-1
@@ -64,13 +64,13 @@ import com.vitorpamplona.amethyst.commons.resources.calendar_export_event
|
||||
import com.vitorpamplona.amethyst.commons.resources.calendar_export_share_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.ScrollStateKeys
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyListState
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.pluralStringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.UserCardHeader
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||
|
||||
+1
-1
@@ -47,11 +47,11 @@ import com.vitorpamplona.amethyst.commons.resources.calendar_empty_feed_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.calendar_section_past
|
||||
import com.vitorpamplona.amethyst.commons.resources.calendar_section_upcoming
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
|
||||
+3
-2
@@ -42,12 +42,13 @@ 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.chats.ui.ThinSendButton
|
||||
import com.vitorpamplona.amethyst.commons.model.cordnGroups.CordnGroupChatroom
|
||||
import com.vitorpamplona.amethyst.commons.model.nip30CustomEmojis.EmojiPackState
|
||||
import com.vitorpamplona.amethyst.commons.model.nip30CustomEmojis.EmojiSuggestionState
|
||||
import com.vitorpamplona.amethyst.commons.nip30CustomEmojis.ui.ShowEmojiSuggestionList
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_composer_hint
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.EditFieldBorder
|
||||
@@ -233,7 +234,7 @@ internal fun CordnComposer(
|
||||
shape = EditFieldBorder,
|
||||
placeholder = {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_composer_hint),
|
||||
text = stringRes(Res.string.cordn_composer_hint),
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
},
|
||||
|
||||
+98
-51
@@ -55,11 +55,9 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CoordinatorConfig
|
||||
import com.vitorpamplona.amethyst.commons.cordn.DiscoveredCoordinator
|
||||
import com.vitorpamplona.amethyst.commons.cordn.GroupExposure
|
||||
@@ -69,6 +67,55 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.back
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_seen
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_seen_on
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_unheard
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_hide_older
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_relays_more
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_show_all
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_show_fewer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_show_older
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_stale_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_action
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_action_invite
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_admin_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_admin_only_me_on
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_change
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_discover
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_hide
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_new
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_pubkey
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coverage_all
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coverage_partial
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coverage_unknown
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_description
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_egalitarian
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_egalitarian_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_no_coordinator
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_link
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_no_welcome
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_open
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_skipped
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_outcome_waiting
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_people_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_step_admins
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_step_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_step_people
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_step_where
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_unreachable_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_member_count
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.model.cordn.CordnCoverage
|
||||
@@ -131,7 +178,7 @@ fun CordnCreateGroupScreen(
|
||||
Icon(MaterialSymbols.AutoMirrored.ArrowBack, contentDescription = stringRes(Res.string.back))
|
||||
}
|
||||
},
|
||||
title = { Text(stringRes(R.string.cordn_create_title)) },
|
||||
title = { Text(stringRes(Res.string.cordn_create_title)) },
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
@@ -139,8 +186,8 @@ fun CordnCreateGroupScreen(
|
||||
// The app's own empty state, centred and titled, rather than a
|
||||
// sentence stranded in the top-left corner.
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -164,14 +211,14 @@ fun CordnCreateGroupScreen(
|
||||
val draft = rememberCordnGroupDraft(accountViewModel)
|
||||
var creation by remember { mutableStateOf<CordnGroupCreation?>(null) }
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
val failureFallback = stringRes(R.string.cordn_create_failed)
|
||||
val failureFallback = stringRes(Res.string.cordn_create_failed)
|
||||
var busy by remember { mutableStateOf(false) }
|
||||
|
||||
// Coordinators this account has never used, from their CEP-6
|
||||
// announcements. Not added to the account by looking: picking one here
|
||||
// is what commits to it, and `createGroup` opens the session.
|
||||
var discovering by remember { mutableStateOf(false) }
|
||||
val discoverFailed = stringRes(R.string.cordn_coordinators_discover_failed)
|
||||
val discoverFailed = stringRes(Res.string.cordn_coordinators_discover_failed)
|
||||
|
||||
// Offers this account already holds are not offers; they are the choices
|
||||
// above, and listing them twice would let the same coordinator be picked
|
||||
@@ -222,29 +269,29 @@ fun CordnCreateGroupScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_explainer),
|
||||
text = stringRes(Res.string.cordn_create_explainer),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
StepHeading(1, stringRes(R.string.cordn_create_step_name))
|
||||
StepHeading(1, stringRes(Res.string.cordn_create_step_name))
|
||||
|
||||
OutlinedTextField(
|
||||
value = draft.name,
|
||||
onValueChange = { draft.name = it },
|
||||
label = { Text(stringRes(R.string.cordn_create_name)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_name)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = draft.description,
|
||||
onValueChange = { draft.description = it },
|
||||
label = { Text(stringRes(R.string.cordn_create_description)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_description)) },
|
||||
singleLine = false,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
StepHeading(2, stringRes(R.string.cordn_create_step_people))
|
||||
StepHeading(2, stringRes(Res.string.cordn_create_step_people))
|
||||
|
||||
RosterSummary(
|
||||
roster = draft.roster,
|
||||
@@ -254,7 +301,7 @@ fun CordnCreateGroupScreen(
|
||||
nav = nav,
|
||||
)
|
||||
|
||||
StepHeading(3, stringRes(R.string.cordn_create_step_where))
|
||||
StepHeading(3, stringRes(Res.string.cordn_create_step_where))
|
||||
|
||||
// Collapsed to the one coordinator that will be used, because with a
|
||||
// draft.roster in hand there is usually nothing left to decide. The whole
|
||||
@@ -326,9 +373,9 @@ fun CordnCreateGroupScreen(
|
||||
TextButton(onClick = { draft.showAllLive = !draft.showAllLive }) {
|
||||
Text(
|
||||
if (draft.showAllLive) {
|
||||
stringRes(R.string.cordn_coordinators_show_fewer)
|
||||
stringRes(Res.string.cordn_coordinators_show_fewer)
|
||||
} else {
|
||||
stringRes(R.string.cordn_coordinators_show_all, live.size)
|
||||
stringRes(Res.string.cordn_coordinators_show_all, live.size)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -338,9 +385,9 @@ fun CordnCreateGroupScreen(
|
||||
TextButton(onClick = { draft.showStale = !draft.showStale }) {
|
||||
Text(
|
||||
if (draft.showStale) {
|
||||
stringRes(R.string.cordn_coordinators_hide_older)
|
||||
stringRes(Res.string.cordn_coordinators_hide_older)
|
||||
} else {
|
||||
stringRes(R.string.cordn_coordinators_show_older, stale.size)
|
||||
stringRes(Res.string.cordn_coordinators_show_older, stale.size)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -348,7 +395,7 @@ fun CordnCreateGroupScreen(
|
||||
|
||||
if (draft.showStale && stale.isNotEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_stale_note),
|
||||
text = stringRes(Res.string.cordn_coordinators_stale_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -372,7 +419,7 @@ fun CordnCreateGroupScreen(
|
||||
}
|
||||
|
||||
CoordinatorChoice(
|
||||
label = stringRes(R.string.cordn_create_coordinator_new),
|
||||
label = stringRes(Res.string.cordn_create_coordinator_new),
|
||||
pubKey = null,
|
||||
selected = draft.selected == null,
|
||||
onSelect = {
|
||||
@@ -402,20 +449,20 @@ fun CordnCreateGroupScreen(
|
||||
},
|
||||
enabled = !discovering && !busy,
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_create_coordinator_discover))
|
||||
Text(stringRes(Res.string.cordn_create_coordinator_discover))
|
||||
}
|
||||
|
||||
draft.discovered?.takeIf { offers.isEmpty() }?.let { result ->
|
||||
Text(
|
||||
text =
|
||||
if (result.unreachable.isEmpty()) {
|
||||
stringRes(R.string.cordn_coordinators_discover_none)
|
||||
stringRes(Res.string.cordn_coordinators_discover_none)
|
||||
} else {
|
||||
// "Nobody is announcing" and "we were not told" are
|
||||
// different answers and only one of them is final.
|
||||
// Reporting the first for the second sends someone
|
||||
// off to paste a pubkey by hand over a timeout.
|
||||
stringRes(R.string.cordn_coordinators_discover_unheard, result.unreachable.size)
|
||||
stringRes(Res.string.cordn_coordinators_discover_unheard, result.unreachable.size)
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -433,7 +480,7 @@ fun CordnCreateGroupScreen(
|
||||
draft.userPicked = true
|
||||
error = null
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_create_coordinator_pubkey)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_coordinator_pubkey)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
@@ -444,7 +491,7 @@ fun CordnCreateGroupScreen(
|
||||
draft.userPicked = true
|
||||
error = null
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_create_coordinator_relays)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_coordinator_relays)) },
|
||||
// A coordinator has no address beyond its pubkey (§8.5), so
|
||||
// the relays are how it is reached and more than one is
|
||||
// ordinary. One per line rather than comma-separated,
|
||||
@@ -456,7 +503,7 @@ fun CordnCreateGroupScreen(
|
||||
}
|
||||
}
|
||||
|
||||
StepHeading(4, stringRes(R.string.cordn_create_step_admins))
|
||||
StepHeading(4, stringRes(Res.string.cordn_create_step_admins))
|
||||
|
||||
// spec/01.md §5.3: leaving the admin list empty is not "set it up
|
||||
// later", it is choosing draft.egalitarian permanently -- so it is offered
|
||||
@@ -472,15 +519,15 @@ fun CordnCreateGroupScreen(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(stringRes(R.string.cordn_create_egalitarian), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(stringRes(Res.string.cordn_create_egalitarian), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
text =
|
||||
if (draft.egalitarian) {
|
||||
stringRes(R.string.cordn_create_egalitarian_note)
|
||||
stringRes(Res.string.cordn_create_egalitarian_note)
|
||||
} else if (draft.coAdmins.isEmpty()) {
|
||||
stringRes(R.string.cordn_create_admin_only_me_on)
|
||||
stringRes(Res.string.cordn_create_admin_only_me_on)
|
||||
} else {
|
||||
pluralStringRes(LocalContext.current, R.plurals.cordn_create_admin_count, draft.coAdmins.size + 1, draft.coAdmins.size + 1)
|
||||
pluralStringRes(Res.plurals.cordn_create_admin_count, draft.coAdmins.size + 1, draft.coAdmins.size + 1)
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -561,9 +608,9 @@ fun CordnCreateGroupScreen(
|
||||
) {
|
||||
Text(
|
||||
if (draft.roster.isEmpty()) {
|
||||
stringRes(R.string.cordn_create_action)
|
||||
stringRes(Res.string.cordn_create_action)
|
||||
} else {
|
||||
pluralStringRes(LocalContext.current, R.plurals.cordn_create_action_invite, draft.roster.size, draft.roster.size)
|
||||
pluralStringRes(Res.plurals.cordn_create_action_invite, draft.roster.size, draft.roster.size)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -691,9 +738,9 @@ private fun resolvedName(
|
||||
@Composable
|
||||
private fun announcedLabel(announcedAt: Long): String =
|
||||
if (TimeUtils.now() - announcedAt > TimeUtils.ONE_MONTH) {
|
||||
stringRes(R.string.cordn_coordinators_discover_seen_on, timeAgoNoDot(announcedAt).trim())
|
||||
stringRes(Res.string.cordn_coordinators_discover_seen_on, timeAgoNoDot(announcedAt).trim())
|
||||
} else {
|
||||
stringRes(R.string.cordn_coordinators_discover_seen, timeAgoNoDot(announcedAt).trim())
|
||||
stringRes(Res.string.cordn_coordinators_discover_seen, timeAgoNoDot(announcedAt).trim())
|
||||
}
|
||||
|
||||
/** The hosts it answers on, the first two and a count of the rest. */
|
||||
@@ -705,7 +752,7 @@ private fun relayLabel(relays: List<NormalizedRelayUrl>): String? {
|
||||
return if (hosts.size <= 2) {
|
||||
shown
|
||||
} else {
|
||||
stringRes(R.string.cordn_coordinators_relays_more, shown, hosts.size - 2)
|
||||
stringRes(Res.string.cordn_coordinators_relays_more, shown, hosts.size - 2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,7 +838,7 @@ private fun RosterSummary(
|
||||
) {
|
||||
if (roster.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_people_none),
|
||||
text = stringRes(Res.string.cordn_create_people_none),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.weight(1f),
|
||||
@@ -804,7 +851,7 @@ private fun RosterSummary(
|
||||
}
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_member_count, roster.size + 1, roster.size + 1),
|
||||
text = pluralStringRes(Res.plurals.cordn_member_count, roster.size + 1, roster.size + 1),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
// Counted over coordinators that answered, so an unreachable one
|
||||
@@ -812,7 +859,7 @@ private fun RosterSummary(
|
||||
val unreachable = roster.count { member -> coverage.values.none { it.answered && member in it.reachable } }
|
||||
if (unreachable > 0 && coverage.values.any { it.answered }) {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_create_unreachable_count, unreachable, unreachable),
|
||||
text = pluralStringRes(Res.plurals.cordn_create_unreachable_count, unreachable, unreachable),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
@@ -855,7 +902,7 @@ private fun CoordinatorSummary(
|
||||
) {
|
||||
if (config == null) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_no_coordinator),
|
||||
text = stringRes(Res.string.cordn_create_no_coordinator),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.weight(1f),
|
||||
@@ -879,9 +926,9 @@ private fun CoordinatorSummary(
|
||||
Text(
|
||||
text =
|
||||
when {
|
||||
coverage == null || !coverage.answered -> stringRes(R.string.cordn_create_coverage_unknown)
|
||||
reached == rosterSize -> stringRes(R.string.cordn_create_coverage_all, rosterSize)
|
||||
else -> stringRes(R.string.cordn_create_coverage_partial, reached ?: 0, rosterSize)
|
||||
coverage == null || !coverage.answered -> stringRes(Res.string.cordn_create_coverage_unknown)
|
||||
reached == rosterSize -> stringRes(Res.string.cordn_create_coverage_all, rosterSize)
|
||||
else -> stringRes(Res.string.cordn_create_coverage_partial, reached ?: 0, rosterSize)
|
||||
},
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color =
|
||||
@@ -899,9 +946,9 @@ private fun CoordinatorSummary(
|
||||
TextButton(onClick = onToggle) {
|
||||
Text(
|
||||
if (expanded) {
|
||||
stringRes(R.string.cordn_create_coordinator_hide)
|
||||
stringRes(Res.string.cordn_create_coordinator_hide)
|
||||
} else {
|
||||
stringRes(R.string.cordn_create_coordinator_change)
|
||||
stringRes(Res.string.cordn_create_coordinator_change)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -934,11 +981,11 @@ private fun CordnCreationOutcome(
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringRes(R.string.cordn_create_outcome_title)) },
|
||||
title = { Text(stringRes(Res.string.cordn_create_outcome_title)) },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_outcome_explainer),
|
||||
text = stringRes(Res.string.cordn_create_outcome_explainer),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -960,10 +1007,10 @@ private fun CordnCreationOutcome(
|
||||
Text(
|
||||
text =
|
||||
when {
|
||||
outcome == null -> stringRes(R.string.cordn_create_outcome_skipped)
|
||||
outcome.sent -> stringRes(R.string.cordn_create_outcome_waiting)
|
||||
outcome.joinedWithoutWelcome -> stringRes(R.string.cordn_create_outcome_no_welcome)
|
||||
else -> outcome.failure?.message ?: stringRes(R.string.cordn_create_outcome_failed)
|
||||
outcome == null -> stringRes(Res.string.cordn_create_outcome_skipped)
|
||||
outcome.sent -> stringRes(Res.string.cordn_create_outcome_waiting)
|
||||
outcome.joinedWithoutWelcome -> stringRes(Res.string.cordn_create_outcome_no_welcome)
|
||||
else -> outcome.failure?.message ?: stringRes(Res.string.cordn_create_outcome_failed)
|
||||
},
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color =
|
||||
@@ -979,12 +1026,12 @@ private fun CordnCreationOutcome(
|
||||
// open themselves -- which needs the group to exist,
|
||||
// and now it does.
|
||||
if (outcome == null) {
|
||||
TextButton(onClick = open) { Text(stringRes(R.string.cordn_create_outcome_link)) }
|
||||
TextButton(onClick = open) { Text(stringRes(Res.string.cordn_create_outcome_link)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = { TextButton(onClick = open) { Text(stringRes(R.string.cordn_create_outcome_open)) } },
|
||||
confirmButton = { TextButton(onClick = open) { Text(stringRes(Res.string.cordn_create_outcome_open)) } },
|
||||
)
|
||||
}
|
||||
|
||||
+37
-21
@@ -47,15 +47,31 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
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.model.User
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_add_member
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_admin
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_people_done
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_people_empty
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_people_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_reach_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_reach_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_reach_unknown
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_step_people
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_you
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member_placeholder
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_has_key_package
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_remove_member
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_member_count
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarWithBackButton
|
||||
@@ -101,12 +117,12 @@ fun CordnCreateMembersScreen(
|
||||
val draft = rememberCordnGroupDraft(accountViewModel)
|
||||
|
||||
Scaffold(
|
||||
topBar = { TopBarWithBackButton(stringRes(R.string.cordn_create_step_people), nav) },
|
||||
topBar = { TopBarWithBackButton(stringRes(Res.string.cordn_create_step_people), nav) },
|
||||
) { padding ->
|
||||
if (runtime == null) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -137,7 +153,7 @@ fun CordnCreateMembersScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_people_note),
|
||||
text = stringRes(Res.string.cordn_create_people_note),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -148,8 +164,8 @@ fun CordnCreateMembersScreen(
|
||||
search = it
|
||||
if (it.length > 2) userSuggestions.processCurrentWord(it) else userSuggestions.reset()
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_create_add_member)) },
|
||||
placeholder = { Text(stringRes(R.string.cordn_info_add_member_placeholder)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_add_member)) },
|
||||
placeholder = { Text(stringRes(Res.string.cordn_info_add_member_placeholder)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
@@ -168,7 +184,7 @@ fun CordnCreateMembersScreen(
|
||||
modifier = SuggestionListDefaultHeightChat,
|
||||
onEmpty = {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_add_member_none),
|
||||
text = stringRes(Res.string.cordn_info_add_member_none),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
@@ -182,7 +198,7 @@ fun CordnCreateMembersScreen(
|
||||
if (user.pubkeyHex in reachable) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Key,
|
||||
contentDescription = stringRes(R.string.cordn_info_has_key_package),
|
||||
contentDescription = stringRes(Res.string.cordn_info_has_key_package),
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -194,7 +210,7 @@ fun CordnCreateMembersScreen(
|
||||
}) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.PersonAdd,
|
||||
contentDescription = stringRes(R.string.cordn_create_add_member),
|
||||
contentDescription = stringRes(Res.string.cordn_create_add_member),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
@@ -206,7 +222,7 @@ fun CordnCreateMembersScreen(
|
||||
HorizontalDivider()
|
||||
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_member_count, draft.roster.size + 1, draft.roster.size + 1),
|
||||
text = pluralStringRes(Res.plurals.cordn_member_count, draft.roster.size + 1, draft.roster.size + 1),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
|
||||
@@ -230,7 +246,7 @@ fun CordnCreateMembersScreen(
|
||||
|
||||
if (draft.roster.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_people_empty),
|
||||
text = stringRes(Res.string.cordn_create_people_empty),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -240,7 +256,7 @@ fun CordnCreateMembersScreen(
|
||||
onClick = { nav.popBack() },
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp),
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_create_people_done))
|
||||
Text(stringRes(Res.string.cordn_create_people_done))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,14 +279,14 @@ private fun CreatorRow(
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(observeUserNameByHex(me, accountViewModel), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_you),
|
||||
text = stringRes(Res.string.cordn_create_you),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
if (!egalitarian) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_admin),
|
||||
text = stringRes(Res.string.cordn_create_admin),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -304,9 +320,9 @@ private fun MemberRow(
|
||||
Text(
|
||||
text =
|
||||
when {
|
||||
answered == 0 -> stringRes(R.string.cordn_create_reach_unknown)
|
||||
reaching > 0 -> pluralStringRes(LocalContext.current, R.plurals.cordn_create_reach_count, reaching, reaching)
|
||||
else -> stringRes(R.string.cordn_create_reach_none)
|
||||
answered == 0 -> stringRes(Res.string.cordn_create_reach_unknown)
|
||||
reaching > 0 -> pluralStringRes(Res.plurals.cordn_create_reach_count, reaching, reaching)
|
||||
else -> stringRes(Res.string.cordn_create_reach_none)
|
||||
},
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color =
|
||||
@@ -323,7 +339,7 @@ private fun MemberRow(
|
||||
if (!egalitarian) {
|
||||
TextButton(onClick = onToggleAdmin) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_create_admin),
|
||||
text = stringRes(Res.string.cordn_create_admin),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = if (isAdmin) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -333,7 +349,7 @@ private fun MemberRow(
|
||||
IconButton(onClick = onRemove) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.PersonRemove,
|
||||
contentDescription = stringRes(R.string.cordn_info_remove_member),
|
||||
contentDescription = stringRes(Res.string.cordn_info_remove_member),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
+50
-28
@@ -69,7 +69,6 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnGroupManager
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
@@ -78,10 +77,33 @@ import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.back
|
||||
import com.vitorpamplona.amethyst.commons.resources.cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_editing
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_unpin
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_chat_empty_description
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_chat_empty_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_info
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_untitled
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_media_download_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_media_no_server
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_media_unreadable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_media_upload_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_member_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_deleted
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_by
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_next
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_previous
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_show_all
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_pinned_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_send_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_send_no_session
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_voice_record
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_voice_stop
|
||||
import com.vitorpamplona.amethyst.commons.richtext.EncryptedMediaUrlImage
|
||||
import com.vitorpamplona.amethyst.commons.richtext.EncryptedMediaUrlVideo
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.loadStringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
@@ -152,7 +174,7 @@ fun CordnGroupChatScreen(
|
||||
// (it was forgotten, or never opened) and not an error to throw at the
|
||||
// user as a blank screen.
|
||||
Column(Modifier.fillMaxSize().padding(24.dp), verticalArrangement = Arrangement.Center) {
|
||||
Text(stringRes(R.string.cordn_group_unavailable), style = MaterialTheme.typography.bodyLarge)
|
||||
Text(stringRes(Res.string.cordn_group_unavailable), style = MaterialTheme.typography.bodyLarge)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -209,9 +231,9 @@ private fun CordnGroupChat(
|
||||
// and simply never arrived.
|
||||
var sendError by remember { mutableStateOf<String?>(null) }
|
||||
val context = LocalContext.current
|
||||
val uploadFailed = stringRes(R.string.cordn_media_upload_failed)
|
||||
val sendFailed = stringRes(R.string.cordn_send_failed)
|
||||
val noSession = stringRes(R.string.cordn_send_no_session)
|
||||
val uploadFailed = stringRes(Res.string.cordn_media_upload_failed)
|
||||
val sendFailed = stringRes(Res.string.cordn_send_failed)
|
||||
val noSession = stringRes(Res.string.cordn_send_no_session)
|
||||
|
||||
fun manager() =
|
||||
accountViewModel.account.cordnRuntime
|
||||
@@ -359,8 +381,8 @@ private fun CordnGroupChat(
|
||||
// action that actually needed it.
|
||||
if (rows.isEmpty()) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_chat_empty_title),
|
||||
description = stringRes(R.string.cordn_chat_empty_description),
|
||||
title = stringRes(Res.string.cordn_chat_empty_title),
|
||||
description = stringRes(Res.string.cordn_chat_empty_description),
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
@@ -548,7 +570,7 @@ private fun CordnGroupChat(
|
||||
}
|
||||
if (editing != null) {
|
||||
ComposerBanner(
|
||||
label = stringRes(R.string.cordn_action_editing),
|
||||
label = stringRes(Res.string.cordn_action_editing),
|
||||
onCancel = {
|
||||
editing = null
|
||||
room.draft.value = ""
|
||||
@@ -712,7 +734,7 @@ private fun PinnedRibbon(
|
||||
IconButton(onClick = { index = (at - 1 + pinned.size) % pinned.size }, modifier = Modifier.size(28.dp)) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.AutoMirrored.KeyboardArrowLeft,
|
||||
contentDescription = stringRes(R.string.cordn_pinned_previous),
|
||||
contentDescription = stringRes(Res.string.cordn_pinned_previous),
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
}
|
||||
@@ -724,7 +746,7 @@ private fun PinnedRibbon(
|
||||
IconButton(onClick = { index = (at + 1) % pinned.size }, modifier = Modifier.size(28.dp)) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.AutoMirrored.KeyboardArrowRight,
|
||||
contentDescription = stringRes(R.string.cordn_pinned_next),
|
||||
contentDescription = stringRes(Res.string.cordn_pinned_next),
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
}
|
||||
@@ -733,7 +755,7 @@ private fun PinnedRibbon(
|
||||
IconButton(onClick = { showingAll = true }, modifier = Modifier.size(28.dp)) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.AutoMirrored.List,
|
||||
contentDescription = stringRes(R.string.cordn_pinned_show_all),
|
||||
contentDescription = stringRes(Res.string.cordn_pinned_show_all),
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
}
|
||||
@@ -786,7 +808,7 @@ private fun PinnedLine(
|
||||
// points at.
|
||||
text =
|
||||
if (annotations.isDeleted(message.envelope.id)) {
|
||||
stringRes(R.string.cordn_message_deleted)
|
||||
stringRes(Res.string.cordn_message_deleted)
|
||||
} else {
|
||||
annotations.contentOf(message.envelope.id).orEmpty()
|
||||
},
|
||||
@@ -822,7 +844,7 @@ private fun AllPinnedDialog(
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(MaterialSymbols.PushPin, contentDescription = null, modifier = Modifier.size(18.dp))
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_pinned_title),
|
||||
text = stringRes(Res.string.cordn_pinned_title),
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
}
|
||||
@@ -830,7 +852,7 @@ private fun AllPinnedDialog(
|
||||
text = {
|
||||
Column {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_pinned_count, pinned.size, pinned.size),
|
||||
text = pluralStringRes(Res.plurals.cordn_pinned_count, pinned.size, pinned.size),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -861,7 +883,7 @@ private fun AllPinnedDialog(
|
||||
modifier = Modifier.weight(1f).padding(start = 8.dp),
|
||||
)
|
||||
TextButton(onClick = { onUnpin(message) }) {
|
||||
Text(stringRes(R.string.cordn_action_unpin), style = MaterialTheme.typography.labelSmall)
|
||||
Text(stringRes(Res.string.cordn_action_unpin), style = MaterialTheme.typography.labelSmall)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,7 +891,7 @@ private fun AllPinnedDialog(
|
||||
Text(
|
||||
text =
|
||||
stringRes(
|
||||
R.string.cordn_pinned_by,
|
||||
Res.string.cordn_pinned_by,
|
||||
observeUserNameByHex(pinnedBy, accountViewModel),
|
||||
),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
@@ -880,7 +902,7 @@ private fun AllPinnedDialog(
|
||||
Text(
|
||||
text =
|
||||
if (annotations.isDeleted(message.envelope.id)) {
|
||||
stringRes(R.string.cordn_message_deleted)
|
||||
stringRes(Res.string.cordn_message_deleted)
|
||||
} else {
|
||||
annotations.contentOf(message.envelope.id).orEmpty()
|
||||
},
|
||||
@@ -944,7 +966,7 @@ private fun CordnChatTopBar(
|
||||
Text(title, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
if (members.isNotEmpty()) {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_member_count, members.size, members.size),
|
||||
text = pluralStringRes(Res.plurals.cordn_member_count, members.size, members.size),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
@@ -963,7 +985,7 @@ private fun CordnChatTopBar(
|
||||
// GroupAdd rather than Info, as in Marmot: the same screen, and the thing
|
||||
// people come to it for is adding someone.
|
||||
IconButton(onClick = onInfo) {
|
||||
Icon(MaterialSymbols.GroupAdd, contentDescription = stringRes(R.string.cordn_group_info))
|
||||
Icon(MaterialSymbols.GroupAdd, contentDescription = stringRes(Res.string.cordn_group_info))
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -995,10 +1017,10 @@ private suspend fun sendAttachment(
|
||||
// a reason a person can act on.
|
||||
val session =
|
||||
accountViewModel.account.cordnRuntime?.sessionOrNull(room.coordinatorPubKey)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_send_no_session))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_send_no_session))
|
||||
val group =
|
||||
session.manager.group(room.gid)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_send_no_session))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_send_no_session))
|
||||
|
||||
// The gallery inside the dialog can delete what was picked, which leaves an empty
|
||||
// orchestrator rather than a null one. canPost() now refuses that, but indexing it
|
||||
@@ -1052,14 +1074,14 @@ private suspend fun sendAttachment(
|
||||
val name = withContext(Dispatchers.IO) { resolveDisplayName(context, uri) }
|
||||
val bytes =
|
||||
withContext(Dispatchers.IO) { context.contentResolver.openInputStream(finalUri)?.use { it.readBytes() } }
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_media_unreadable))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_media_unreadable))
|
||||
|
||||
// Null means the chosen host has no base URL, which is a setting the person can
|
||||
// change — the one failure here that is entirely actionable.
|
||||
val tag =
|
||||
CordnMediaService(accountViewModel.account)
|
||||
.upload(group, bytes, mime, name, context, state.selectedServer.baseUrl)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_media_no_server))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_media_no_server))
|
||||
|
||||
// Into the room as well, for the same reason every other send is: an
|
||||
// attachment of your own echoes back as an Echo and would otherwise be
|
||||
@@ -1140,7 +1162,7 @@ internal fun CordnAttachment(
|
||||
|
||||
if (mediaKey == null) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_media_download_failed),
|
||||
text = stringRes(Res.string.cordn_media_download_failed),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
@@ -1254,7 +1276,7 @@ internal fun VoiceNoteButton(
|
||||
) {
|
||||
Icon(
|
||||
symbol = if (recording) MaterialSymbols.Stop else MaterialSymbols.Mic,
|
||||
contentDescription = stringRes(if (recording) R.string.cordn_voice_stop else R.string.cordn_voice_record),
|
||||
contentDescription = stringRes(if (recording) Res.string.cordn_voice_stop else Res.string.cordn_voice_record),
|
||||
// Matches the attach icon beside it; red only while recording,
|
||||
// which is the one state worth pulling the eye.
|
||||
tint = if (recording) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.placeholderText,
|
||||
@@ -1284,10 +1306,10 @@ private suspend fun sendVoiceNote(
|
||||
// note that goes nowhere and says nothing is the same bug twice.
|
||||
val session =
|
||||
accountViewModel.account.cordnRuntime?.sessionOrNull(room.coordinatorPubKey)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_send_no_session))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_send_no_session))
|
||||
val group =
|
||||
session.manager.group(room.gid)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_send_no_session))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_send_no_session))
|
||||
|
||||
try {
|
||||
val bytes = withContext(Dispatchers.IO) { recording.file.readBytes() }
|
||||
@@ -1304,7 +1326,7 @@ private suspend fun sendVoiceNote(
|
||||
// is what makes the bubble match the preview.
|
||||
waveform = recording.amplitudes,
|
||||
)
|
||||
?: throw CordnAttachmentException(stringRes(context, R.string.cordn_media_no_server))
|
||||
?: throw CordnAttachmentException(loadStringRes(Res.string.cordn_media_no_server))
|
||||
// Into the room as well, for the same reason every other send is: an
|
||||
// attachment of your own echoes back as an Echo and would otherwise be
|
||||
// invisible to the person who sent it.
|
||||
|
||||
+103
-59
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.cordnGroup
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -58,12 +57,10 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnGroupException
|
||||
import com.vitorpamplona.amethyst.commons.cordn.GroupExposure
|
||||
import com.vitorpamplona.amethyst.commons.cordn.ui.CordnExposureCard
|
||||
@@ -76,8 +73,58 @@ import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.back
|
||||
import com.vitorpamplona.amethyst.commons.resources.cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.copy_npub_to_clipboard
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_action_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_coordinator_silent
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_no_key_package
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_no_self_remove
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_no_welcome
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_not_a_member
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_someone
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_admin_wrong_key_package
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_description
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_name
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_exposure_close
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_exposure_open
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_info
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_untitled
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_add_member_placeholder
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_admin_badge
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_admins_kept
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_coordinator
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_coordinator_key
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_coordinator_nprofile
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_copy_nprofile
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_edit_details
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_egalitarian
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_epoch
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_gid
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_has_key_package
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_members
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_remove_confirm_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_remove_confirm_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_remove_member
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_save
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_technical
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_member_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_accept
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_admin_only
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_check
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_decline
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_requests_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_send_no_session
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_share_copied
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_share_copy
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_share_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_share_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.loadStringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.SuggestionListDefaultHeightChat
|
||||
import com.vitorpamplona.amethyst.commons.util.toShortDisplay
|
||||
@@ -124,8 +171,8 @@ fun CordnGroupInfoScreen(
|
||||
// The app's own empty state, centred and titled, rather than a
|
||||
// sentence stranded in the top-left corner.
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
}
|
||||
@@ -151,7 +198,7 @@ private fun InfoTopBar(
|
||||
Icon(MaterialSymbols.AutoMirrored.ArrowBack, contentDescription = stringRes(Res.string.back))
|
||||
}
|
||||
},
|
||||
title = { Text(stringRes(R.string.cordn_group_info)) },
|
||||
title = { Text(stringRes(Res.string.cordn_group_info)) },
|
||||
actions = actions,
|
||||
)
|
||||
}
|
||||
@@ -208,8 +255,8 @@ private fun CordnGroupInfo(
|
||||
DisposableEffect(Unit) {
|
||||
onDispose { userSuggestions.reset() }
|
||||
}
|
||||
val failed = stringRes(R.string.cordn_admin_action_failed)
|
||||
val noSession = stringRes(R.string.cordn_send_no_session)
|
||||
val failed = stringRes(Res.string.cordn_admin_action_failed)
|
||||
val noSession = stringRes(Res.string.cordn_send_no_session)
|
||||
|
||||
// Computed, never asserted: hardcoding these made the card look like a
|
||||
// disclosure while reporting the same four values for every group.
|
||||
@@ -236,8 +283,6 @@ private fun CordnGroupInfo(
|
||||
* roster, and a rename stayed the old name. The runtime's own methods pair
|
||||
* each commit with that refresh.
|
||||
*/
|
||||
val context = LocalContext.current
|
||||
|
||||
fun runAdmin(
|
||||
who: String? = null,
|
||||
block: suspend (CordnRuntime) -> Unit,
|
||||
@@ -257,7 +302,7 @@ private fun CordnGroupInfo(
|
||||
// and gids in full, so the screen that had just shown a face
|
||||
// answered with 64 hex characters.
|
||||
Log.w("CordnGroupInfo", "admin action failed in ${room.gid}: ${e.message}", e)
|
||||
adminError = adminFailureText(context, e, who, failed)
|
||||
adminError = adminFailureText(e, who, failed)
|
||||
} finally {
|
||||
busy = false
|
||||
}
|
||||
@@ -274,7 +319,7 @@ private fun CordnGroupInfo(
|
||||
IconButton(onClick = { renaming = true }, enabled = !busy) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Edit,
|
||||
contentDescription = stringRes(R.string.cordn_info_edit_details),
|
||||
contentDescription = stringRes(Res.string.cordn_info_edit_details),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -303,7 +348,7 @@ private fun CordnGroupInfo(
|
||||
}
|
||||
// A subtitle, not a labelled row above a list that is itself the count.
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_member_count, members.size, members.size),
|
||||
text = pluralStringRes(Res.plurals.cordn_member_count, members.size, members.size),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
@@ -321,7 +366,7 @@ private fun CordnGroupInfo(
|
||||
// ContextVM addresses it with ordinary p-tags, so it has a kind 0 like
|
||||
// anyone else and the app can already resolve it to a name, an avatar
|
||||
// and a profile to tap through to.
|
||||
Text(stringRes(R.string.cordn_info_coordinator), style = MaterialTheme.typography.titleMedium)
|
||||
Text(stringRes(Res.string.cordn_info_coordinator), style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
Row(
|
||||
Modifier.fillMaxWidth().padding(top = 8.dp),
|
||||
@@ -347,7 +392,7 @@ private fun CordnGroupInfo(
|
||||
IconButton(onClick = { showExposure = true }, enabled = exposure != null) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Info,
|
||||
contentDescription = stringRes(R.string.cordn_exposure_open),
|
||||
contentDescription = stringRes(Res.string.cordn_exposure_open),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
@@ -355,7 +400,7 @@ private fun CordnGroupInfo(
|
||||
|
||||
HorizontalDivider(Modifier.padding(vertical = 16.dp))
|
||||
|
||||
Text(stringRes(R.string.cordn_info_members), style = MaterialTheme.typography.titleMedium)
|
||||
Text(stringRes(Res.string.cordn_info_members), style = MaterialTheme.typography.titleMedium)
|
||||
|
||||
// Said once, and only when it is true. An empty admin set is not "none
|
||||
// configured" -- spec/01.md makes it permanently egalitarian, so the
|
||||
@@ -364,7 +409,7 @@ private fun CordnGroupInfo(
|
||||
// a count of them adds nothing.
|
||||
if (admins.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_egalitarian),
|
||||
text = stringRes(Res.string.cordn_info_egalitarian),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(top = 2.dp, bottom = 4.dp),
|
||||
@@ -385,7 +430,7 @@ private fun CordnGroupInfo(
|
||||
)
|
||||
if (member in admins) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_admin_badge),
|
||||
text = stringRes(Res.string.cordn_info_admin_badge),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -398,7 +443,7 @@ private fun CordnGroupInfo(
|
||||
IconButton(onClick = { removing = member }, enabled = !busy) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.PersonRemove,
|
||||
contentDescription = stringRes(R.string.cordn_info_remove_member),
|
||||
contentDescription = stringRes(Res.string.cordn_info_remove_member),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
@@ -476,9 +521,9 @@ private fun CordnGroupInfo(
|
||||
// would be a setting nobody should be nudged into.
|
||||
AlertDialog(
|
||||
onDismissRequest = { removing = null },
|
||||
title = { Text(stringRes(R.string.cordn_info_remove_confirm_title)) },
|
||||
title = { Text(stringRes(Res.string.cordn_info_remove_confirm_title)) },
|
||||
text = {
|
||||
Text(stringRes(R.string.cordn_info_remove_confirm_body, removingName))
|
||||
Text(stringRes(Res.string.cordn_info_remove_confirm_body, removingName))
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
@@ -486,7 +531,7 @@ private fun CordnGroupInfo(
|
||||
runAdmin(removingName) { it.removeMember(coordinatorPubKey, room.gid, target) }
|
||||
}) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_remove_member),
|
||||
text = stringRes(Res.string.cordn_info_remove_member),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
@@ -518,7 +563,7 @@ private fun CordnGroupInfo(
|
||||
text = { CordnExposureCard(it) },
|
||||
confirmButton = {
|
||||
TextButton(onClick = { showExposure = false }) {
|
||||
Text(stringRes(R.string.cordn_exposure_close))
|
||||
Text(stringRes(Res.string.cordn_exposure_close))
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -577,15 +622,15 @@ private fun CordnAddMember(
|
||||
OutlinedTextField(
|
||||
value = search,
|
||||
onValueChange = onSearchChange,
|
||||
label = { Text(stringRes(R.string.cordn_info_add_member)) },
|
||||
placeholder = { Text(stringRes(R.string.cordn_info_add_member_placeholder)) },
|
||||
label = { Text(stringRes(Res.string.cordn_info_add_member)) },
|
||||
placeholder = { Text(stringRes(Res.string.cordn_info_add_member_placeholder)) },
|
||||
singleLine = true,
|
||||
enabled = !busy,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_add_member_note),
|
||||
text = stringRes(Res.string.cordn_info_add_member_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
@@ -601,7 +646,7 @@ private fun CordnAddMember(
|
||||
modifier = SuggestionListDefaultHeightChat,
|
||||
onEmpty = {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_add_member_none),
|
||||
text = stringRes(Res.string.cordn_info_add_member_none),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
@@ -612,7 +657,7 @@ private fun CordnAddMember(
|
||||
if (reachable?.contains(user.pubkeyHex) == true) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Key,
|
||||
contentDescription = stringRes(R.string.cordn_info_has_key_package),
|
||||
contentDescription = stringRes(Res.string.cordn_info_has_key_package),
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -620,7 +665,7 @@ private fun CordnAddMember(
|
||||
IconButton(onClick = { onInvite(user) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.PersonAdd,
|
||||
contentDescription = stringRes(R.string.cordn_info_add_member),
|
||||
contentDescription = stringRes(Res.string.cordn_info_add_member),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
@@ -643,20 +688,19 @@ private fun CordnAddMember(
|
||||
* better than silence — and the caller has logged the throwable in full either
|
||||
* way.
|
||||
*/
|
||||
private fun adminFailureText(
|
||||
context: Context,
|
||||
private suspend fun adminFailureText(
|
||||
e: Throwable,
|
||||
who: String?,
|
||||
fallback: String,
|
||||
): String {
|
||||
val name = who ?: stringRes(context, R.string.cordn_admin_someone)
|
||||
val name = who ?: loadStringRes(Res.string.cordn_admin_someone)
|
||||
return when (e) {
|
||||
is CordnGroupException ->
|
||||
when (e.reason) {
|
||||
CordnGroupException.Reason.NO_KEY_PACKAGE -> stringRes(context, R.string.cordn_admin_no_key_package, name)
|
||||
CordnGroupException.Reason.WRONG_KEY_PACKAGE_OWNER -> stringRes(context, R.string.cordn_admin_wrong_key_package, name)
|
||||
CordnGroupException.Reason.NO_WELCOME -> stringRes(context, R.string.cordn_admin_no_welcome, name)
|
||||
CordnGroupException.Reason.NOT_A_MEMBER -> stringRes(context, R.string.cordn_admin_not_a_member, name)
|
||||
CordnGroupException.Reason.NO_KEY_PACKAGE -> loadStringRes(Res.string.cordn_admin_no_key_package, name)
|
||||
CordnGroupException.Reason.WRONG_KEY_PACKAGE_OWNER -> loadStringRes(Res.string.cordn_admin_wrong_key_package, name)
|
||||
CordnGroupException.Reason.NO_WELCOME -> loadStringRes(Res.string.cordn_admin_no_welcome, name)
|
||||
CordnGroupException.Reason.NOT_A_MEMBER -> loadStringRes(Res.string.cordn_admin_not_a_member, name)
|
||||
CordnGroupException.Reason.OTHER -> e.message ?: fallback
|
||||
}
|
||||
|
||||
@@ -664,14 +708,14 @@ private fun adminFailureText(
|
||||
// roster and the button disagreed rather than that anyone tried.
|
||||
is IllegalArgumentException ->
|
||||
if (e.message?.contains("self-removal") == true) {
|
||||
stringRes(context, R.string.cordn_admin_no_self_remove)
|
||||
loadStringRes(Res.string.cordn_admin_no_self_remove)
|
||||
} else {
|
||||
e.message ?: fallback
|
||||
}
|
||||
|
||||
// A coordinator that does not answer is the single commonest failure
|
||||
// here and says nothing useful in its own words.
|
||||
is TimeoutCancellationException -> stringRes(context, R.string.cordn_admin_coordinator_silent)
|
||||
is TimeoutCancellationException -> loadStringRes(Res.string.cordn_admin_coordinator_silent)
|
||||
|
||||
else -> e.message ?: fallback
|
||||
}
|
||||
@@ -701,7 +745,7 @@ private fun TechnicalDetails(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_info_technical),
|
||||
text = stringRes(Res.string.cordn_info_technical),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
@@ -725,22 +769,22 @@ private fun TechnicalDetails(
|
||||
val coordinator = remember(coordinatorPubKey) { LocalCache.getOrCreateUser(coordinatorPubKey) }
|
||||
|
||||
CopyableKeyRow(
|
||||
label = stringRes(R.string.cordn_info_coordinator_key),
|
||||
label = stringRes(Res.string.cordn_info_coordinator_key),
|
||||
shown = coordinator.pubkeyDisplayHex(),
|
||||
copied = coordinator.pubkeyNpub(),
|
||||
copyDescription = stringRes(Res.string.copy_npub_to_clipboard),
|
||||
)
|
||||
CopyableKeyRow(
|
||||
label = stringRes(R.string.cordn_info_coordinator_nprofile),
|
||||
label = stringRes(Res.string.cordn_info_coordinator_nprofile),
|
||||
shown = coordinator.toNProfile().toShortDisplay(6),
|
||||
copied = coordinator.toNProfile(),
|
||||
copyDescription = stringRes(R.string.cordn_info_copy_nprofile),
|
||||
copyDescription = stringRes(Res.string.cordn_info_copy_nprofile),
|
||||
)
|
||||
|
||||
SelectionContainer {
|
||||
Column {
|
||||
InfoRow(stringRes(R.string.cordn_info_gid), gid)
|
||||
InfoRow(stringRes(R.string.cordn_info_epoch), epoch.toString())
|
||||
InfoRow(stringRes(Res.string.cordn_info_gid), gid)
|
||||
InfoRow(stringRes(Res.string.cordn_info_epoch), epoch.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -835,7 +879,7 @@ private fun JoinRequests(
|
||||
) {
|
||||
val runtime = accountViewModel.account.cordnRuntime ?: return
|
||||
val scope = rememberCoroutineScope()
|
||||
val failed = stringRes(R.string.cordn_requests_failed)
|
||||
val failed = stringRes(Res.string.cordn_requests_failed)
|
||||
|
||||
var requests by remember { mutableStateOf<List<JoinRequest>?>(null) }
|
||||
var busy by remember { mutableStateOf(false) }
|
||||
@@ -853,15 +897,15 @@ private fun JoinRequests(
|
||||
}
|
||||
}
|
||||
|
||||
Text(stringRes(R.string.cordn_requests_title), style = MaterialTheme.typography.titleMedium)
|
||||
Text(stringRes(Res.string.cordn_requests_title), style = MaterialTheme.typography.titleMedium)
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_requests_admin_only),
|
||||
text = stringRes(Res.string.cordn_requests_admin_only),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
OutlinedButton(onClick = { scope.launch { reload() } }, enabled = !busy) {
|
||||
Text(stringRes(R.string.cordn_requests_check))
|
||||
Text(stringRes(Res.string.cordn_requests_check))
|
||||
}
|
||||
|
||||
error?.let { Text(it, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.error) }
|
||||
@@ -870,7 +914,7 @@ private fun JoinRequests(
|
||||
if (loaded != null && !busy) {
|
||||
if (loaded.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_requests_none),
|
||||
text = stringRes(Res.string.cordn_requests_none),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -899,7 +943,7 @@ private fun JoinRequests(
|
||||
reload()
|
||||
}
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_requests_accept))
|
||||
Text(stringRes(Res.string.cordn_requests_accept))
|
||||
}
|
||||
TextButton(onClick = {
|
||||
scope.launch {
|
||||
@@ -911,7 +955,7 @@ private fun JoinRequests(
|
||||
reload()
|
||||
}
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_requests_decline))
|
||||
Text(stringRes(Res.string.cordn_requests_decline))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -949,9 +993,9 @@ private fun ShareGroup(
|
||||
val clipboard = LocalClipboardManager.current
|
||||
var copied by remember { mutableStateOf(false) }
|
||||
|
||||
Text(stringRes(R.string.cordn_share_title), style = MaterialTheme.typography.titleMedium)
|
||||
Text(stringRes(Res.string.cordn_share_title), style = MaterialTheme.typography.titleMedium)
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_share_explainer),
|
||||
text = stringRes(Res.string.cordn_share_explainer),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -968,7 +1012,7 @@ private fun ShareGroup(
|
||||
},
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
) {
|
||||
Text(stringRes(if (copied) R.string.cordn_share_copied else R.string.cordn_share_copy))
|
||||
Text(stringRes(if (copied) Res.string.cordn_share_copied else Res.string.cordn_share_copy))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -993,26 +1037,26 @@ private fun EditGroupDetailsDialog(
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringRes(R.string.cordn_info_edit_details)) },
|
||||
title = { Text(stringRes(Res.string.cordn_info_edit_details)) },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
OutlinedTextField(
|
||||
value = draftName,
|
||||
onValueChange = { draftName = it },
|
||||
label = { Text(stringRes(R.string.cordn_create_name)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_name)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = draftDescription,
|
||||
onValueChange = { draftDescription = it },
|
||||
label = { Text(stringRes(R.string.cordn_create_description)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_description)) },
|
||||
singleLine = false,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
if (admins.isNotEmpty()) {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_info_admins_kept, admins.size, admins.size),
|
||||
text = pluralStringRes(Res.plurals.cordn_info_admins_kept, admins.size, admins.size),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -1024,7 +1068,7 @@ private fun EditGroupDetailsDialog(
|
||||
onClick = { onSave(draftName.trim(), draftDescription.trim()) },
|
||||
enabled = draftName.isNotBlank(),
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_info_save))
|
||||
Text(stringRes(Res.string.cordn_info_save))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
|
||||
+16
-10
@@ -41,10 +41,8 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CoordinatorHealth
|
||||
import com.vitorpamplona.amethyst.commons.cordn.ui.CoordinatorHealthRow
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
@@ -52,6 +50,14 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.cordnGroups.CordnGroupChatroom
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_count
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_down_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_manage
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_none_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_start
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_groups_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
@@ -106,14 +112,14 @@ fun CordnGroupListScreen(
|
||||
IconButton(onClick = { nav.nav(Route.CordnCoordinators) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Dns,
|
||||
contentDescription = stringRes(R.string.cordn_groups_manage),
|
||||
contentDescription = stringRes(Res.string.cordn_groups_manage),
|
||||
modifier = Modifier.size(22.dp),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { nav.nav(Route.CordnCreateGroup) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Add,
|
||||
contentDescription = stringRes(R.string.cordn_groups_start),
|
||||
contentDescription = stringRes(Res.string.cordn_groups_start),
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
}
|
||||
@@ -122,8 +128,8 @@ fun CordnGroupListScreen(
|
||||
) { padding ->
|
||||
if (runtime == null) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -148,8 +154,8 @@ fun CordnGroupListScreen(
|
||||
|
||||
if (sections.isEmpty()) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_groups_none),
|
||||
description = stringRes(R.string.cordn_groups_none_detail),
|
||||
title = stringRes(Res.string.cordn_groups_none),
|
||||
description = stringRes(Res.string.cordn_groups_none_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -230,7 +236,7 @@ private fun CoordinatorSection(
|
||||
},
|
||||
)
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_groups_count, groupCount, groupCount),
|
||||
text = pluralStringRes(Res.plurals.cordn_groups_count, groupCount, groupCount),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -248,7 +254,7 @@ private fun CoordinatorSection(
|
||||
verticalAlignment = Alignment.Top,
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_groups_down_note),
|
||||
text = stringRes(Res.string.cordn_groups_down_note),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
|
||||
+33
-18
@@ -48,16 +48,30 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
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.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.back
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_untitled
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_accept
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_decline
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_decline_warning
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_load_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_members
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_members_more
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_no_coordinators
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_refresh
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_skipped
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_unreachable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_invitations_via
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.model.cordn.CordnInvitation
|
||||
@@ -69,6 +83,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.cordn.CoordinatorI
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.cordn.coordinatorDisplayName
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.pluralStringResource
|
||||
|
||||
/**
|
||||
* Invitations to cordn groups, waiting to be answered.
|
||||
@@ -106,7 +121,7 @@ fun CordnInvitationsScreen(
|
||||
var invitations by remember { mutableStateOf<CordnInvitations?>(null) }
|
||||
var busy by remember { mutableStateOf(false) }
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
val loadFailed = stringRes(R.string.cordn_invitations_load_failed)
|
||||
val loadFailed = stringRes(Res.string.cordn_invitations_load_failed)
|
||||
|
||||
suspend fun reload() {
|
||||
busy = true
|
||||
@@ -130,10 +145,10 @@ fun CordnInvitationsScreen(
|
||||
Icon(MaterialSymbols.AutoMirrored.ArrowBack, contentDescription = stringRes(Res.string.back))
|
||||
}
|
||||
},
|
||||
title = { Text(stringRes(R.string.cordn_invitations_title)) },
|
||||
title = { Text(stringRes(Res.string.cordn_invitations_title)) },
|
||||
actions = {
|
||||
IconButton(onClick = { scope.launch { reload() } }, enabled = !busy) {
|
||||
Icon(MaterialSymbols.Refresh, contentDescription = stringRes(R.string.cordn_invitations_refresh))
|
||||
Icon(MaterialSymbols.Refresh, contentDescription = stringRes(Res.string.cordn_invitations_refresh))
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -150,8 +165,8 @@ fun CordnInvitationsScreen(
|
||||
) {
|
||||
if (runtime == null) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
)
|
||||
return@Column
|
||||
}
|
||||
@@ -163,7 +178,7 @@ fun CordnInvitationsScreen(
|
||||
val coordinators by runtime.coordinators.collectAsStateWithLifecycle()
|
||||
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_invitations_explainer),
|
||||
text = stringRes(Res.string.cordn_invitations_explainer),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -212,7 +227,7 @@ fun CordnInvitationsScreen(
|
||||
NoticeCard(
|
||||
title =
|
||||
stringRes(
|
||||
R.string.cordn_invitations_unreachable,
|
||||
Res.string.cordn_invitations_unreachable,
|
||||
coordinatorDisplayName(it.coordinator.pubKey, it.coordinator.label, accountViewModel),
|
||||
),
|
||||
detail = it.reason,
|
||||
@@ -225,7 +240,7 @@ fun CordnInvitationsScreen(
|
||||
// friend swears they sent simply does not exist here.
|
||||
loaded.skipped.forEach {
|
||||
NoticeCard(
|
||||
title = stringRes(R.string.cordn_invitations_skipped),
|
||||
title = stringRes(Res.string.cordn_invitations_skipped),
|
||||
detail = it.reason,
|
||||
isError = false,
|
||||
)
|
||||
@@ -235,9 +250,9 @@ fun CordnInvitationsScreen(
|
||||
Text(
|
||||
text =
|
||||
if (coordinators.isEmpty()) {
|
||||
stringRes(R.string.cordn_invitations_no_coordinators)
|
||||
stringRes(Res.string.cordn_invitations_no_coordinators)
|
||||
} else {
|
||||
stringRes(R.string.cordn_invitations_none)
|
||||
stringRes(Res.string.cordn_invitations_none)
|
||||
},
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -276,7 +291,7 @@ private fun InvitationCard(
|
||||
|
||||
// "Already in it", never "invited you" — see the screen KDoc.
|
||||
Text(
|
||||
text = pluralStringResource(R.plurals.cordn_invitations_members, welcome.members.size, welcome.members.size),
|
||||
text = pluralStringResource(Res.plurals.cordn_invitations_members, welcome.members.size, welcome.members.size),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -300,7 +315,7 @@ private fun InvitationCard(
|
||||
}
|
||||
if (welcome.members.size > MEMBER_FACES) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_invitations_members_more, welcome.members.size - MEMBER_FACES),
|
||||
text = stringRes(Res.string.cordn_invitations_members_more, welcome.members.size - MEMBER_FACES),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -329,7 +344,7 @@ private fun InvitationCard(
|
||||
size = 20.dp,
|
||||
) { name ->
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_invitations_via, name),
|
||||
text = stringRes(Res.string.cordn_invitations_via, name),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -340,11 +355,11 @@ private fun InvitationCard(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Button(onClick = onAccept) { Text(stringRes(R.string.cordn_invitations_accept)) }
|
||||
TextButton(onClick = onDecline) { Text(stringRes(R.string.cordn_invitations_decline)) }
|
||||
Button(onClick = onAccept) { Text(stringRes(Res.string.cordn_invitations_accept)) }
|
||||
TextButton(onClick = onDecline) { Text(stringRes(Res.string.cordn_invitations_decline)) }
|
||||
}
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_invitations_decline_warning),
|
||||
text = stringRes(Res.string.cordn_invitations_decline_warning),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
+39
-22
@@ -55,7 +55,6 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
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.chats.ui.ChatDivisor
|
||||
import com.vitorpamplona.amethyst.commons.chats.ui.UserDisplayNameLayout
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnMentions
|
||||
@@ -67,6 +66,24 @@ import com.vitorpamplona.amethyst.commons.model.navigation.Route
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.copied_to_clipboard
|
||||
import com.vitorpamplona.amethyst.commons.resources.copy_text
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_delete
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_edit
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_go_to_message
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_pin
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_reply
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_action_unpin
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_chat_unread_divider
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_chat_yesterday
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_delete_confirm_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_delete_confirm_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_delivery_accepted
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_deleted
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_details_coordinator
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_details_cursor
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_details_sent_at
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_details_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_message_edited
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_reactions_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.quick_action_share
|
||||
import com.vitorpamplona.amethyst.commons.resources.today
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.ClickableBox
|
||||
@@ -292,7 +309,7 @@ private fun CordnBubbleContents(
|
||||
when {
|
||||
text == null ->
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_message_deleted),
|
||||
text = stringRes(Res.string.cordn_message_deleted),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -448,7 +465,7 @@ private fun CordnReactionDetailSheet(
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).padding(bottom = 24.dp)) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_reactions_title),
|
||||
text = stringRes(Res.string.cordn_reactions_title),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(horizontal = 20.dp, vertical = 12.dp),
|
||||
)
|
||||
@@ -519,7 +536,7 @@ internal fun CordnQuotedMessage(
|
||||
|
||||
val body =
|
||||
if (annotations.isDeleted(parent.envelope.id)) {
|
||||
stringRes(R.string.cordn_message_deleted)
|
||||
stringRes(Res.string.cordn_message_deleted)
|
||||
} else {
|
||||
annotations.contentOf(parent.envelope.id).orEmpty()
|
||||
}
|
||||
@@ -575,7 +592,7 @@ private fun CordnQuoteActionSheet(
|
||||
Column(Modifier.padding(bottom = 24.dp)) {
|
||||
TileRow {
|
||||
if (onGoToMessage != null) {
|
||||
ActionTile(MaterialSymbols.ArrowUpward, stringRes(R.string.cordn_action_go_to_message)) {
|
||||
ActionTile(MaterialSymbols.ArrowUpward, stringRes(Res.string.cordn_action_go_to_message)) {
|
||||
onGoToMessage()
|
||||
onDismiss()
|
||||
}
|
||||
@@ -594,7 +611,7 @@ private fun CordnQuoteActionSheet(
|
||||
*/
|
||||
@Composable
|
||||
internal fun UnreadDivider() {
|
||||
ChatDivisor(stringRes(R.string.cordn_chat_unread_divider), MaterialTheme.colorScheme.primary)
|
||||
ChatDivisor(stringRes(Res.string.cordn_chat_unread_divider), MaterialTheme.colorScheme.primary)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -618,7 +635,7 @@ private fun CordnMessageFooter(
|
||||
if (isPinned) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.PushPin,
|
||||
contentDescription = stringRes(R.string.cordn_action_pin),
|
||||
contentDescription = stringRes(Res.string.cordn_action_pin),
|
||||
modifier = Modifier.size(12.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -627,7 +644,7 @@ private fun CordnMessageFooter(
|
||||
|
||||
if (isEdited) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_message_edited),
|
||||
text = stringRes(Res.string.cordn_message_edited),
|
||||
fontSize = Font12SP,
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
maxLines = 1,
|
||||
@@ -658,7 +675,7 @@ private fun CordnMessageFooter(
|
||||
Spacer(StdHorzSpacer)
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Done,
|
||||
contentDescription = stringRes(R.string.cordn_delivery_accepted),
|
||||
contentDescription = stringRes(Res.string.cordn_delivery_accepted),
|
||||
modifier = Modifier.size(12.dp),
|
||||
tint = MaterialTheme.colorScheme.allGoodColor,
|
||||
)
|
||||
@@ -711,18 +728,18 @@ private fun CordnMessageDetailsSheet(
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_message_details_title),
|
||||
text = stringRes(Res.string.cordn_message_details_title),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
DetailLine(stringRes(R.string.cordn_message_details_sent_at), sentAt)
|
||||
DetailLine(stringRes(R.string.cordn_message_details_cursor), message.cursor.toString())
|
||||
DetailLine(stringRes(Res.string.cordn_message_details_sent_at), sentAt)
|
||||
DetailLine(stringRes(Res.string.cordn_message_details_cursor), message.cursor.toString())
|
||||
DetailLine(
|
||||
stringRes(R.string.cordn_message_details_coordinator),
|
||||
stringRes(Res.string.cordn_message_details_coordinator),
|
||||
coordinatorDisplayName(coordinatorPubKey, label = null, accountViewModel = accountViewModel),
|
||||
)
|
||||
if (isMine) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_delivery_accepted),
|
||||
text = stringRes(Res.string.cordn_delivery_accepted),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.allGoodColor,
|
||||
)
|
||||
@@ -797,10 +814,10 @@ private fun CordnMessageActionSheet(
|
||||
|
||||
if (confirmingDelete) {
|
||||
QuickActionAlertDialog(
|
||||
title = stringRes(R.string.cordn_delete_confirm_title),
|
||||
textContent = stringRes(R.string.cordn_delete_confirm_body),
|
||||
title = stringRes(Res.string.cordn_delete_confirm_title),
|
||||
textContent = stringRes(Res.string.cordn_delete_confirm_body),
|
||||
buttonIcon = MaterialSymbols.Delete,
|
||||
buttonText = stringRes(R.string.cordn_action_delete),
|
||||
buttonText = stringRes(Res.string.cordn_action_delete),
|
||||
onClickDoOnce = performDelete,
|
||||
onClickDontShowAgain = {
|
||||
accountViewModel.account.settings.setHideDeleteRequestDialog()
|
||||
@@ -843,7 +860,7 @@ private fun CordnMessageActionSheet(
|
||||
|
||||
TileRow {
|
||||
if (isLive) {
|
||||
ActionTile(MaterialSymbols.AutoMirrored.Chat, stringRes(R.string.cordn_action_reply)) {
|
||||
ActionTile(MaterialSymbols.AutoMirrored.Chat, stringRes(Res.string.cordn_action_reply)) {
|
||||
onReply()
|
||||
onDismiss()
|
||||
}
|
||||
@@ -853,7 +870,7 @@ private fun CordnMessageActionSheet(
|
||||
// message rather than only on your own.
|
||||
ActionTile(
|
||||
MaterialSymbols.PushPin,
|
||||
stringRes(if (isPinned) R.string.cordn_action_unpin else R.string.cordn_action_pin),
|
||||
stringRes(if (isPinned) Res.string.cordn_action_unpin else Res.string.cordn_action_pin),
|
||||
) {
|
||||
onTogglePin()
|
||||
onDismiss()
|
||||
@@ -863,11 +880,11 @@ private fun CordnMessageActionSheet(
|
||||
// anyone else. Hiding them here is the same rule, stated where it stops
|
||||
// being a surprise.
|
||||
if (isMine && isLive) {
|
||||
ActionTile(MaterialSymbols.Edit, stringRes(R.string.cordn_action_edit)) {
|
||||
ActionTile(MaterialSymbols.Edit, stringRes(Res.string.cordn_action_edit)) {
|
||||
onEdit()
|
||||
onDismiss()
|
||||
}
|
||||
ActionTile(MaterialSymbols.Delete, stringRes(R.string.cordn_action_delete), isDestructive = true) {
|
||||
ActionTile(MaterialSymbols.Delete, stringRes(Res.string.cordn_action_delete), isDestructive = true) {
|
||||
// A withdrawal cannot be taken back and the coordinator keeps
|
||||
// the ciphertext either way, so it is worth one question —
|
||||
// unless the account has already opted out of being asked.
|
||||
@@ -989,7 +1006,7 @@ internal fun DaySeparator(
|
||||
val label =
|
||||
when (day) {
|
||||
today -> stringRes(Res.string.today)
|
||||
today.minusDays(1) -> stringRes(R.string.cordn_chat_yesterday)
|
||||
today.minusDays(1) -> stringRes(Res.string.cordn_chat_yesterday)
|
||||
// Year included only when it is not this one: printing 2026 on every
|
||||
// divider all year is noise.
|
||||
else ->
|
||||
|
||||
+2
-7
@@ -106,7 +106,9 @@ import com.vitorpamplona.amethyst.commons.resources.relay_group_server_label
|
||||
import com.vitorpamplona.amethyst.commons.resources.remove_from_messages
|
||||
import com.vitorpamplona.amethyst.commons.resources.unmute_notifications
|
||||
import com.vitorpamplona.amethyst.commons.resources.unpin_conversation
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.NewItemsBubble
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.ChatHeaderLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.HeaderPill
|
||||
import com.vitorpamplona.amethyst.commons.ui.screen.LocalDisplaySettings
|
||||
@@ -118,7 +120,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.Size15Modifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.newItemBubbleModifier
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.model.buzz.toMembershipNotice
|
||||
import com.vitorpamplona.amethyst.model.nip11RelayInfo.loadRelayInfo
|
||||
@@ -126,7 +127,6 @@ import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observe
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteHasEvent
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderByParentFilterAssemblerSubscription
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserName
|
||||
import com.vitorpamplona.amethyst.ui.layouts.ChatHeaderLayout
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
|
||||
import com.vitorpamplona.amethyst.ui.note.BlankNote
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContentOrNull
|
||||
@@ -1377,8 +1377,3 @@ private fun TimeAgo(channelLastTime: Long?) {
|
||||
color = MaterialTheme.colorScheme.grayText,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NewItemsBubble() {
|
||||
Box(MaterialTheme.colorScheme.newItemBubbleModifier)
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,6 +53,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.Mute
|
||||
import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.chat_about_topic
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.HalfTopPadding
|
||||
@@ -61,7 +62,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.RowColSpacing
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannel
|
||||
import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
||||
import com.vitorpamplona.amethyst.ui.note.Gallery
|
||||
import com.vitorpamplona.amethyst.ui.note.LikeReaction
|
||||
|
||||
+1
-1
@@ -55,6 +55,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.Mute
|
||||
import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.community_about_topic
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.HalfTopPadding
|
||||
@@ -63,7 +64,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.RowColSpacing
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteEvent
|
||||
import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
||||
import com.vitorpamplona.amethyst.ui.note.Gallery
|
||||
import com.vitorpamplona.amethyst.ui.note.LikeReaction
|
||||
|
||||
+1
-1
@@ -41,6 +41,7 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.commons.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.HalfTopPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.RowColSpacing5dp
|
||||
@@ -51,7 +52,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.nip05
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription
|
||||
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.ui.note.LikeReaction
|
||||
import com.vitorpamplona.amethyst.ui.note.ZapReaction
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.BannerImage
|
||||
|
||||
+2
-2
@@ -46,12 +46,12 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedError
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.ScrollStateKeys
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchLifecycleAndUpdateModel
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.rememberForeverLazyGridState
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
|
||||
import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
+2
-2
@@ -61,6 +61,8 @@ import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.commons.feeds.ChannelFeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.ChannelFeedState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedContentState
|
||||
import com.vitorpamplona.amethyst.commons.feeds.FeedState
|
||||
import com.vitorpamplona.amethyst.commons.model.emphChat.EphemeralChatChannel
|
||||
@@ -96,8 +98,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.StdVertSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.TabRowHeight
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.ThemeComparisonRow
|
||||
import com.vitorpamplona.amethyst.service.location.LocationState
|
||||
import com.vitorpamplona.amethyst.ui.feeds.ChannelFeedContentState
|
||||
import com.vitorpamplona.amethyst.ui.feeds.ChannelFeedState
|
||||
import com.vitorpamplona.amethyst.ui.feeds.RenderFeedContentState
|
||||
import com.vitorpamplona.amethyst.ui.feeds.SaveableFeedContentState
|
||||
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
|
||||
|
||||
+1
-1
@@ -60,6 +60,7 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RelayReachCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RelayReachDetailDialog
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RelayReachMarkers
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.CloseIcon
|
||||
@@ -73,7 +74,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.Size10dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.StdVertSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.imageModifier
|
||||
import com.vitorpamplona.amethyst.logTime
|
||||
import com.vitorpamplona.amethyst.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.ui.note.BadgeCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.MessageSetCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.MultiSetCompose
|
||||
|
||||
+2
-2
@@ -40,12 +40,12 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedEmpty
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedError
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.LoadingFeed
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.RefresheableBox
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.feeds.PrefetchLoadedFeedMedia
|
||||
import com.vitorpamplona.amethyst.ui.feeds.StickToTopOnPrepend
|
||||
import com.vitorpamplona.amethyst.ui.feeds.WatchScrollToTop
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.newthreads.dal.UserProfileNewThreadsFeedViewModel
|
||||
|
||||
+1
-1
@@ -35,12 +35,12 @@ import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.commons.model.User
|
||||
import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.routeFor
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.EmptyNav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.BitcoinOrange
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.Size55dp
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.ThemeComparisonColumn
|
||||
import com.vitorpamplona.amethyst.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor
|
||||
import com.vitorpamplona.amethyst.ui.note.UserActionOptions
|
||||
import com.vitorpamplona.amethyst.ui.note.UserPicture
|
||||
|
||||
+1
-1
@@ -122,6 +122,7 @@ import com.vitorpamplona.amethyst.commons.resources.relay_management_tab_pubkeys
|
||||
import com.vitorpamplona.amethyst.commons.resources.relay_management_tab_settings
|
||||
import com.vitorpamplona.amethyst.commons.resources.relay_management_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.search_and_add_a_user
|
||||
import com.vitorpamplona.amethyst.commons.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.note.ClearTextIcon
|
||||
import com.vitorpamplona.amethyst.commons.ui.stringRes
|
||||
@@ -133,7 +134,6 @@ import com.vitorpamplona.amethyst.commons.ui.theme.SmallBorder
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.commons.ui.theme.nip05
|
||||
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.UserSearchDataSourceSubscription
|
||||
import com.vitorpamplona.amethyst.ui.layouts.listItem.SlimListItem
|
||||
import com.vitorpamplona.amethyst.ui.note.AboutDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||
import com.vitorpamplona.amethyst.ui.note.ObserveAndRenderNIP05VerifiedSymbol
|
||||
|
||||
+29
-16
@@ -52,13 +52,26 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_contents_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_contents_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_export
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_exported
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_passphrase
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_restore
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_restore_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_restore_confirm_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_restore_confirm_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_restored
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_section_export
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_section_passphrase
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_section_restore
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_backup_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarWithBackButton
|
||||
@@ -113,9 +126,9 @@ fun CordnBackupScreen(
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
var pendingRestore by remember { mutableStateOf<Uri?>(null) }
|
||||
|
||||
val exported = stringRes(R.string.cordn_backup_exported)
|
||||
val restored = stringRes(R.string.cordn_backup_restored)
|
||||
val failed = stringRes(R.string.cordn_backup_failed)
|
||||
val exported = stringRes(Res.string.cordn_backup_exported)
|
||||
val restored = stringRes(Res.string.cordn_backup_restored)
|
||||
val failed = stringRes(Res.string.cordn_backup_failed)
|
||||
|
||||
val saver =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/octet-stream")) { uri ->
|
||||
@@ -179,8 +192,8 @@ fun CordnBackupScreen(
|
||||
// The app's own empty state, centred and titled, rather than a
|
||||
// sentence stranded in the top-left corner.
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -196,7 +209,7 @@ fun CordnBackupScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_backup_explainer),
|
||||
text = stringRes(Res.string.cordn_backup_explainer),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -212,7 +225,7 @@ fun CordnBackupScreen(
|
||||
passphrase = it
|
||||
error = null
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_backup_passphrase)) },
|
||||
label = { Text(stringRes(Res.string.cordn_backup_passphrase)) },
|
||||
visualTransformation = PasswordVisualTransformation(),
|
||||
// The dots are only half of it. Without the password
|
||||
// keyboard type the IME treats this as ordinary prose:
|
||||
@@ -230,9 +243,9 @@ fun CordnBackupScreen(
|
||||
|
||||
SettingsSection(Res.string.cordn_backup_section_export) {
|
||||
SettingsFormBlock {
|
||||
Text(stringRes(R.string.cordn_backup_contents_title), style = MaterialTheme.typography.titleSmall)
|
||||
Text(stringRes(Res.string.cordn_backup_contents_title), style = MaterialTheme.typography.titleSmall)
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_backup_contents_body),
|
||||
text = stringRes(Res.string.cordn_backup_contents_body),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -248,7 +261,7 @@ fun CordnBackupScreen(
|
||||
// Key derivation here is scrypt, which is slow on
|
||||
// purpose, so a greyed-out button was the only sign
|
||||
// anything was happening for several seconds.
|
||||
BusyLabel(busy, stringRes(R.string.cordn_backup_export))
|
||||
BusyLabel(busy, stringRes(Res.string.cordn_backup_export))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +269,7 @@ fun CordnBackupScreen(
|
||||
SettingsSection(Res.string.cordn_backup_section_restore) {
|
||||
SettingsFormBlock {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_backup_restore_body),
|
||||
text = stringRes(Res.string.cordn_backup_restore_body),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -266,7 +279,7 @@ fun CordnBackupScreen(
|
||||
enabled = !busy && passphrase.isNotBlank(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
BusyLabel(busy, stringRes(R.string.cordn_backup_restore))
|
||||
BusyLabel(busy, stringRes(Res.string.cordn_backup_restore))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,8 +289,8 @@ fun CordnBackupScreen(
|
||||
pendingRestore?.let { uri ->
|
||||
AlertDialog(
|
||||
onDismissRequest = { pendingRestore = null },
|
||||
title = { Text(stringRes(R.string.cordn_backup_restore_confirm_title)) },
|
||||
text = { Text(stringRes(R.string.cordn_backup_restore_confirm_body)) },
|
||||
title = { Text(stringRes(Res.string.cordn_backup_restore_confirm_title)) },
|
||||
text = { Text(stringRes(Res.string.cordn_backup_restore_confirm_body)) },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
pendingRestore = null
|
||||
@@ -302,7 +315,7 @@ fun CordnBackupScreen(
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_backup_restore), color = MaterialTheme.colorScheme.error)
|
||||
Text(stringRes(Res.string.cordn_backup_restore), color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
|
||||
+74
-40
@@ -58,7 +58,6 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
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.cordn.CoordinatorConfig
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CoordinatorHealth
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnCoordinatorDiscovery
|
||||
@@ -68,10 +67,45 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_add_action
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_add_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_copy_key
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_action
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_add
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_seen
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_discover_unheard
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_health_down
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_health_ok
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_health_retrying
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_health_unknown
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_identify
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_key
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_label
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_label_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_more
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_purge
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_purge_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_purge_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_relays_label
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_remove
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_rename
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_section_discover
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_section_manual
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_section_yours
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_server
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_server_claim
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_server_silent
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_pubkey
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_create_coordinator_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_info_save
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.CrossfadeIfEnabled
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
@@ -127,8 +161,8 @@ fun CordnCoordinatorsScreen(
|
||||
// The app's own empty state, centred and titled, rather than a
|
||||
// sentence stranded in the top-left corner.
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -146,7 +180,7 @@ fun CordnCoordinatorsScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_explainer),
|
||||
text = stringRes(Res.string.cordn_coordinators_explainer),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -165,7 +199,7 @@ fun CordnCoordinatorsScreen(
|
||||
|
||||
if (coordinators.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_none),
|
||||
text = stringRes(Res.string.cordn_coordinators_none),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -225,7 +259,7 @@ private fun CoordinatorCard(
|
||||
IconButton(onClick = { renaming = true }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Edit,
|
||||
contentDescription = stringRes(R.string.cordn_coordinators_rename),
|
||||
contentDescription = stringRes(Res.string.cordn_coordinators_rename),
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -264,10 +298,10 @@ private fun CoordinatorCard(
|
||||
// away on the clipboard, which is how a comparison is actually done.
|
||||
val coordinator = remember(config.pubKey) { LocalCache.getOrCreateUser(config.pubKey) }
|
||||
CopyableKeyRow(
|
||||
label = stringRes(R.string.cordn_coordinators_key),
|
||||
label = stringRes(Res.string.cordn_coordinators_key),
|
||||
shown = coordinator.pubkeyDisplayHex(),
|
||||
copied = coordinator.pubkeyNpub(),
|
||||
copyDescription = stringRes(R.string.cordn_coordinators_copy_key),
|
||||
copyDescription = stringRes(Res.string.cordn_coordinators_copy_key),
|
||||
)
|
||||
|
||||
// Every relay, not the first two and a count: this is the management
|
||||
@@ -275,7 +309,7 @@ private fun CoordinatorCard(
|
||||
// came here to check or to rule out.
|
||||
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_relays_label),
|
||||
text = stringRes(Res.string.cordn_coordinators_relays_label),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
@@ -304,10 +338,10 @@ private fun CoordinatorCard(
|
||||
text =
|
||||
info?.let {
|
||||
stringRes(
|
||||
R.string.cordn_coordinators_server,
|
||||
Res.string.cordn_coordinators_server,
|
||||
listOfNotNull(it.name, it.version, it.protocolVersion).joinToString(" \u00b7 "),
|
||||
)
|
||||
} ?: stringRes(R.string.cordn_coordinators_server_silent),
|
||||
} ?: stringRes(Res.string.cordn_coordinators_server_silent),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -315,7 +349,7 @@ private fun CoordinatorCard(
|
||||
// Said next to it, every time, because a name on a settings
|
||||
// screen reads as verified and this one is not: §8.5 makes
|
||||
// the pubkey the identity and nothing else.
|
||||
text = stringRes(R.string.cordn_coordinators_server_claim),
|
||||
text = stringRes(Res.string.cordn_coordinators_server_claim),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -333,7 +367,7 @@ private fun CoordinatorCard(
|
||||
infoChecked = true
|
||||
}
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_coordinators_identify))
|
||||
Text(stringRes(Res.string.cordn_coordinators_identify))
|
||||
}
|
||||
|
||||
Spacer(Modifier.weight(1f))
|
||||
@@ -345,14 +379,14 @@ private fun CoordinatorCard(
|
||||
IconButton(onClick = { menuOpen = true }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.MoreVert,
|
||||
contentDescription = stringRes(R.string.cordn_coordinators_more),
|
||||
contentDescription = stringRes(Res.string.cordn_coordinators_more),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
DropdownMenu(expanded = menuOpen, onDismissRequest = { menuOpen = false }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringRes(R.string.cordn_coordinators_remove)) },
|
||||
text = { Text(stringRes(Res.string.cordn_coordinators_remove)) },
|
||||
onClick = {
|
||||
menuOpen = false
|
||||
scope.launch { runtime.forget(config.pubKey) }
|
||||
@@ -361,7 +395,7 @@ private fun CoordinatorCard(
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_purge),
|
||||
text = stringRes(Res.string.cordn_coordinators_purge),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
},
|
||||
@@ -378,14 +412,14 @@ private fun CoordinatorCard(
|
||||
if (confirmingPurge) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { confirmingPurge = false },
|
||||
title = { Text(stringRes(R.string.cordn_coordinators_purge_title)) },
|
||||
text = { Text(stringRes(R.string.cordn_coordinators_purge_body)) },
|
||||
title = { Text(stringRes(Res.string.cordn_coordinators_purge_title)) },
|
||||
text = { Text(stringRes(Res.string.cordn_coordinators_purge_body)) },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
confirmingPurge = false
|
||||
scope.launch { runtime.purge(config.pubKey) }
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_coordinators_purge), color = MaterialTheme.colorScheme.error)
|
||||
Text(stringRes(Res.string.cordn_coordinators_purge), color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
@@ -409,10 +443,10 @@ private fun CoordinatorCard(
|
||||
private fun HealthLine(state: CoordinatorHealth.State) {
|
||||
val text =
|
||||
when {
|
||||
state.isUnknown -> stringRes(R.string.cordn_coordinators_health_unknown)
|
||||
state.isDown -> stringRes(R.string.cordn_coordinators_health_down, state.consecutiveFailures)
|
||||
state.consecutiveFailures > 0 -> stringRes(R.string.cordn_coordinators_health_retrying)
|
||||
else -> stringRes(R.string.cordn_coordinators_health_ok)
|
||||
state.isUnknown -> stringRes(Res.string.cordn_coordinators_health_unknown)
|
||||
state.isDown -> stringRes(Res.string.cordn_coordinators_health_down, state.consecutiveFailures)
|
||||
state.consecutiveFailures > 0 -> stringRes(Res.string.cordn_coordinators_health_retrying)
|
||||
else -> stringRes(Res.string.cordn_coordinators_health_ok)
|
||||
}
|
||||
|
||||
Text(
|
||||
@@ -447,10 +481,10 @@ private fun DiscoverCoordinators(
|
||||
var result by remember { mutableStateOf<CordnCoordinatorDiscovery.Result?>(null) }
|
||||
var busy by remember { mutableStateOf(false) }
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
val failed = stringRes(R.string.cordn_coordinators_discover_failed)
|
||||
val failed = stringRes(Res.string.cordn_coordinators_discover_failed)
|
||||
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_discover_explainer),
|
||||
text = stringRes(Res.string.cordn_coordinators_discover_explainer),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -475,7 +509,7 @@ private fun DiscoverCoordinators(
|
||||
CircularProgressIndicator(Modifier.size(16.dp), strokeWidth = 2.dp)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
}
|
||||
Text(stringRes(R.string.cordn_coordinators_discover_action))
|
||||
Text(stringRes(Res.string.cordn_coordinators_discover_action))
|
||||
}
|
||||
|
||||
error?.let { Text(it, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.error) }
|
||||
@@ -497,11 +531,11 @@ private fun DiscoverCoordinators(
|
||||
Text(
|
||||
text =
|
||||
if (found.unreachable.isEmpty()) {
|
||||
stringRes(R.string.cordn_coordinators_discover_none)
|
||||
stringRes(Res.string.cordn_coordinators_discover_none)
|
||||
} else {
|
||||
// "Nobody is announcing" and "we were not told" are
|
||||
// different answers and only one of them is final.
|
||||
stringRes(R.string.cordn_coordinators_discover_unheard, found.unreachable.size)
|
||||
stringRes(Res.string.cordn_coordinators_discover_unheard, found.unreachable.size)
|
||||
},
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -529,19 +563,19 @@ private fun RenameCoordinatorDialog(
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringRes(R.string.cordn_coordinators_rename)) },
|
||||
title = { Text(stringRes(Res.string.cordn_coordinators_rename)) },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
OutlinedTextField(
|
||||
value = input,
|
||||
onValueChange = { input = it },
|
||||
label = { Text(stringRes(R.string.cordn_coordinators_label)) },
|
||||
label = { Text(stringRes(Res.string.cordn_coordinators_label)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
Text(
|
||||
// The same caution the add form gives, for the same reason.
|
||||
text = stringRes(R.string.cordn_coordinators_label_note),
|
||||
text = stringRes(Res.string.cordn_coordinators_label_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -549,7 +583,7 @@ private fun RenameCoordinatorDialog(
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { onSave(input.trim().ifEmpty { null }) }) {
|
||||
Text(stringRes(R.string.cordn_info_save))
|
||||
Text(stringRes(Res.string.cordn_info_save))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
@@ -601,7 +635,7 @@ private fun DiscoveredCard(
|
||||
Text(
|
||||
// Staleness matters more here than anywhere: the last live
|
||||
// survey found most announcements were months-dead demos.
|
||||
text = stringRes(R.string.cordn_coordinators_discover_seen, timeAgoNoDot(offer.announcedAt).trim()),
|
||||
text = stringRes(Res.string.cordn_coordinators_discover_seen, timeAgoNoDot(offer.announcedAt).trim()),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -619,7 +653,7 @@ private fun DiscoveredCard(
|
||||
enabled = !busy,
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_coordinators_discover_add))
|
||||
Text(stringRes(Res.string.cordn_coordinators_discover_add))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,7 +667,7 @@ private fun AddCoordinator(runtime: CordnRuntime) {
|
||||
var labelInput by remember { mutableStateOf("") }
|
||||
var error by remember { mutableStateOf<String?>(null) }
|
||||
var busy by remember { mutableStateOf(false) }
|
||||
val failed = stringRes(R.string.cordn_coordinators_add_failed)
|
||||
val failed = stringRes(Res.string.cordn_coordinators_add_failed)
|
||||
|
||||
val config =
|
||||
remember(pubKeyInput, relaysInput, labelInput) {
|
||||
@@ -652,7 +686,7 @@ private fun AddCoordinator(runtime: CordnRuntime) {
|
||||
pubKeyInput = it
|
||||
error = null
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_create_coordinator_pubkey)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_coordinator_pubkey)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
@@ -662,14 +696,14 @@ private fun AddCoordinator(runtime: CordnRuntime) {
|
||||
relaysInput = it
|
||||
error = null
|
||||
},
|
||||
label = { Text(stringRes(R.string.cordn_create_coordinator_relays)) },
|
||||
label = { Text(stringRes(Res.string.cordn_create_coordinator_relays)) },
|
||||
singleLine = false,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = labelInput,
|
||||
onValueChange = { labelInput = it },
|
||||
label = { Text(stringRes(R.string.cordn_coordinators_label)) },
|
||||
label = { Text(stringRes(Res.string.cordn_coordinators_label)) },
|
||||
singleLine = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
@@ -677,7 +711,7 @@ private fun AddCoordinator(runtime: CordnRuntime) {
|
||||
Text(
|
||||
// A label is ours, never theirs. A coordinator cannot prove a name and
|
||||
// this one is not asked for one.
|
||||
text = stringRes(R.string.cordn_coordinators_label_note),
|
||||
text = stringRes(Res.string.cordn_coordinators_label_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -705,6 +739,6 @@ private fun AddCoordinator(runtime: CordnRuntime) {
|
||||
enabled = !busy && config != null,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_coordinators_add_action))
|
||||
Text(stringRes(Res.string.cordn_coordinators_add_action))
|
||||
}
|
||||
}
|
||||
|
||||
+32
-18
@@ -47,14 +47,28 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CoordinatorConfig
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_coordinators_none
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_disclosure
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_explainer
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_last_resort_no
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_last_resort_yes
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_orphans
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_orphans_body
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_publish
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_publish_last_resort
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_section
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_summary
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_title
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_topup_note
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_withdraw_all
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_keypackages_withdraw_orphans
|
||||
import com.vitorpamplona.amethyst.commons.ui.components.EmptyState
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.topbars.TopBarWithBackButton
|
||||
@@ -106,8 +120,8 @@ fun CordnKeyPackagesScreen(
|
||||
) { padding ->
|
||||
if (runtime == null) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
@@ -125,7 +139,7 @@ fun CordnKeyPackagesScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_keypackages_explainer),
|
||||
text = stringRes(Res.string.cordn_keypackages_explainer),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -140,7 +154,7 @@ fun CordnKeyPackagesScreen(
|
||||
SettingsFormBlock {
|
||||
if (coordinators.isEmpty()) {
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_coordinators_none),
|
||||
text = stringRes(Res.string.cordn_coordinators_none),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -169,7 +183,7 @@ private fun CoordinatorKeyPackages(
|
||||
var rows by remember(config.pubKey) { mutableStateOf<List<CordnKeyPackageRow>?>(null) }
|
||||
var busy by remember(config.pubKey) { mutableStateOf(false) }
|
||||
var error by remember(config.pubKey) { mutableStateOf<String?>(null) }
|
||||
val failed = stringRes(R.string.cordn_keypackages_failed)
|
||||
val failed = stringRes(Res.string.cordn_keypackages_failed)
|
||||
|
||||
suspend fun reload() {
|
||||
busy = true
|
||||
@@ -204,15 +218,15 @@ private fun CoordinatorKeyPackages(
|
||||
val hasLastResort = loaded.any { it.lastResort }
|
||||
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_keypackages_summary, single, single),
|
||||
text = pluralStringRes(Res.plurals.cordn_keypackages_summary, single, single),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Text(
|
||||
text =
|
||||
if (hasLastResort) {
|
||||
stringRes(R.string.cordn_keypackages_last_resort_yes)
|
||||
stringRes(Res.string.cordn_keypackages_last_resort_yes)
|
||||
} else {
|
||||
stringRes(R.string.cordn_keypackages_last_resort_no)
|
||||
stringRes(Res.string.cordn_keypackages_last_resort_no)
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
@@ -225,11 +239,11 @@ private fun CoordinatorKeyPackages(
|
||||
) {
|
||||
Column(Modifier.padding(12.dp)) {
|
||||
Text(
|
||||
text = pluralStringRes(LocalContext.current, R.plurals.cordn_keypackages_orphans, orphans.size, orphans.size),
|
||||
text = pluralStringRes(Res.plurals.cordn_keypackages_orphans, orphans.size, orphans.size),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
Text(
|
||||
text = stringRes(R.string.cordn_keypackages_orphans_body),
|
||||
text = stringRes(Res.string.cordn_keypackages_orphans_body),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
TextButton(onClick = {
|
||||
@@ -242,7 +256,7 @@ private fun CoordinatorKeyPackages(
|
||||
reload()
|
||||
}
|
||||
}) {
|
||||
Text(stringRes(R.string.cordn_keypackages_withdraw_orphans))
|
||||
Text(stringRes(Res.string.cordn_keypackages_withdraw_orphans))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,7 +265,7 @@ private fun CoordinatorKeyPackages(
|
||||
Text(
|
||||
// Above the buttons, because it is the part that cannot be taken
|
||||
// back: §8.4 makes publishing an attributable, permanent record.
|
||||
text = stringRes(R.string.cordn_keypackages_disclosure),
|
||||
text = stringRes(Res.string.cordn_keypackages_disclosure),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -274,7 +288,7 @@ private fun CoordinatorKeyPackages(
|
||||
},
|
||||
enabled = !busy,
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_keypackages_publish))
|
||||
Text(stringRes(Res.string.cordn_keypackages_publish))
|
||||
}
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
@@ -289,7 +303,7 @@ private fun CoordinatorKeyPackages(
|
||||
},
|
||||
enabled = !busy && !hasLastResort,
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_keypackages_publish_last_resort))
|
||||
Text(stringRes(Res.string.cordn_keypackages_publish_last_resort))
|
||||
}
|
||||
if (loaded.isNotEmpty()) {
|
||||
TextButton(
|
||||
@@ -305,7 +319,7 @@ private fun CoordinatorKeyPackages(
|
||||
},
|
||||
enabled = !busy,
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_keypackages_withdraw_all), color = MaterialTheme.colorScheme.error)
|
||||
Text(stringRes(Res.string.cordn_keypackages_withdraw_all), color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,7 +327,7 @@ private fun CoordinatorKeyPackages(
|
||||
Text(
|
||||
// The rule CordnRuntime.maintainKeyPackages implements, said where
|
||||
// someone can see that it applies to them.
|
||||
text = stringRes(R.string.cordn_keypackages_topup_note),
|
||||
text = stringRes(Res.string.cordn_keypackages_topup_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
+10
-6
@@ -45,7 +45,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnLinkInspection
|
||||
import com.vitorpamplona.amethyst.commons.cordn.ui.CordnExposureCard
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
@@ -60,6 +59,11 @@ import com.vitorpamplona.amethyst.commons.resources.cordn_link_no_coordinator
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_not_joinable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_paste
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_request
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_request_disclosure
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_request_failed
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_request_sent
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_scan
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_section_input
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_link_title
|
||||
import com.vitorpamplona.amethyst.commons.ui.navigation.navs.INav
|
||||
@@ -102,8 +106,8 @@ fun CordnLinkScreen(
|
||||
var requesting by remember { mutableStateOf(false) }
|
||||
val runtime = accountViewModel.account.cordnRuntime
|
||||
val scope = rememberCoroutineScope()
|
||||
val requestFailed = stringRes(R.string.cordn_link_request_failed)
|
||||
val asked = stringRes(R.string.cordn_link_request_sent)
|
||||
val requestFailed = stringRes(Res.string.cordn_link_request_failed)
|
||||
val asked = stringRes(Res.string.cordn_link_request_sent)
|
||||
var scanning by remember { mutableStateOf(false) }
|
||||
val clipboard = LocalClipboardManager.current
|
||||
|
||||
@@ -163,7 +167,7 @@ fun CordnLinkScreen(
|
||||
Text(stringResource(Res.string.cordn_link_paste))
|
||||
}
|
||||
OutlinedButton(onClick = { scanning = true }) {
|
||||
Text(stringRes(R.string.cordn_link_scan))
|
||||
Text(stringRes(Res.string.cordn_link_scan))
|
||||
}
|
||||
if (input.isNotEmpty()) {
|
||||
OutlinedButton(
|
||||
@@ -265,7 +269,7 @@ fun CordnLinkScreen(
|
||||
enabled = !requesting,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Text(stringRes(R.string.cordn_link_request))
|
||||
Text(stringRes(Res.string.cordn_link_request))
|
||||
}
|
||||
|
||||
Text(
|
||||
@@ -274,7 +278,7 @@ fun CordnLinkScreen(
|
||||
// KeyPackage under this account's own key and tells
|
||||
// the coordinator this account wants into this
|
||||
// group, whether or not anyone ever answers (§8.4).
|
||||
text = stringRes(R.string.cordn_link_request_disclosure),
|
||||
text = stringRes(Res.string.cordn_link_request_disclosure),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
+4
-3
@@ -47,9 +47,10 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.commons.cordn.CordnMigration
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_group_unavailable_detail
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_migrate_cancel
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_migrate_cancel_desc
|
||||
import com.vitorpamplona.amethyst.commons.resources.cordn_migrate_code_note
|
||||
@@ -119,8 +120,8 @@ fun CordnMigrateScreen(
|
||||
) { padding ->
|
||||
if (runtime == null) {
|
||||
EmptyState(
|
||||
title = stringRes(R.string.cordn_group_unavailable),
|
||||
description = stringRes(R.string.cordn_group_unavailable_detail),
|
||||
title = stringRes(Res.string.cordn_group_unavailable),
|
||||
description = stringRes(Res.string.cordn_group_unavailable_detail),
|
||||
modifier = Modifier.padding(padding),
|
||||
)
|
||||
return@Scaffold
|
||||
|
||||
@@ -353,322 +353,4 @@
|
||||
<string name="mute_button">ध्वनि सक्रिय। मौन करने के लिए टाँकें</string>
|
||||
<string name="play">चलाएँ</string>
|
||||
<string name="pause">विराम</string>
|
||||
<string name="backup_conflict_title">आपने अपना %1$s अन्य क्रमक में परिवर्तित किया</string>
|
||||
<string name="backup_conflict_removed">हटाए गए (%1$s)</string>
|
||||
<string name="backup_conflict_added">जोडे गए (%1$s)</string>
|
||||
<string name="backup_conflict_changed">परिवर्तित (%1$s)</string>
|
||||
<string name="backup_conflict_private_cleared">आपने सभी निजी (रहस्यीकृत) वस्तुओं को हटा दिया।</string>
|
||||
<string name="backup_conflict_private_changed">आपने निजी (रहस्यीकृत) वस्तुओं का परिवर्तन भी किया। उनकी तुलना यहाँ नहीं की जा सकती।</string>
|
||||
<string name="backup_conflict_private_added">आपने निजी (रहस्यीकृत) वस्तुओं को जोडा।</string>
|
||||
<string name="backup_conflict_restore_mine">सुरक्षित संस्करण पुनःस्थापन</string>
|
||||
<string name="backup_review_saved">इस यन्त्र पर</string>
|
||||
<string name="backup_review_new">नया संस्करण</string>
|
||||
<string name="backup_review_not_set">स्थापित नहीं</string>
|
||||
<string name="backup_conflict_count_removed">%1$s हटाए गए</string>
|
||||
<string name="backup_conflict_count_added">%1$s जोडे गए</string>
|
||||
<string name="backup_conflict_count_changed">%1$s परिवर्तित</string>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">आपने %1$d व्यक्ति का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d व्यक्तियों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<string name="backup_card_accept">स्वीकार</string>
|
||||
<string name="backup_review_title_updated">%1$s अद्यतनकृत</string>
|
||||
<string name="backup_review_title_cleared">%1$s पारित</string>
|
||||
<string name="backup_review_changed_by_other_app">अन्य क्रमक में परिवर्तित। %1$s</string>
|
||||
<string name="backup_action_keep_count">रखें %1$s</string>
|
||||
<string name="backup_action_restore_count">पुनःस्थापन %1$s</string>
|
||||
<string name="backup_action_remute">पुनःमौन %1$s</string>
|
||||
<string name="backup_action_rejoin">पुनःजुडें %1$s</string>
|
||||
<string name="backup_action_restore_profile">परिचय पुनःस्थापध</string>
|
||||
<string name="backup_action_restore_relays">पुनःप्रसारक पुनःस्थापन</string>
|
||||
<string name="backup_review_kept_count">%1$s रखे गए</string>
|
||||
<string name="backup_review_dropped_count">%1$s परित्यक्त</string>
|
||||
<string name="backup_review_new_count">%1$s नए</string>
|
||||
<string name="backup_review_tab_dropped">परित्यक्त। %1$s</string>
|
||||
<string name="backup_review_tab_new">नए। %1$s</string>
|
||||
<string name="backup_review_tab_edited">सम्पादित। %1$s</string>
|
||||
<string name="backup_review_search_people">%1$s लोग खोजें</string>
|
||||
<string name="backup_review_nothing_here">यहाँ कुछ नहीं</string>
|
||||
<string name="backup_review_unmuted">%1$s मौनावस्था हटाए गए</string>
|
||||
<string name="backup_review_unmuted_explainer">ये पुनः आपके सूचनावलियों तक अभिगम्य</string>
|
||||
<string name="backup_review_newly_muted">%1$s नए मौनकृत</string>
|
||||
<string name="backup_review_words_and_hashtags">शब्द तथा विषयसूचक</string>
|
||||
<string name="backup_review_names_and_more">%1$s तथा %2$s अधिक</string>
|
||||
<string name="backup_review_private_wiped_title">आपने सभी निजी वस्तुओं को हटा दिया</string>
|
||||
<string name="backup_review_private_wiped_body">वे रहस्यीकृत हैं। इसलिए केवल आप देख सकते हैं कि वे क्या थे। पुनःस्थापन से सब लौटके आ जाएँगे।</string>
|
||||
<string name="backup_review_private_added_title">आपने वस्तुओं को निजी किया</string>
|
||||
<string name="backup_review_private_added_body">वे अब रहस्यीकृत हैं। जो कि सम्भाव्यतः ऊपर के सार्वजनिक वस्तुओं का गन्तव्य था।</string>
|
||||
<string name="backup_review_private_changed_title">आपने निजी वस्तुओं का परिवर्तन किया</string>
|
||||
<string name="backup_review_private_changed_body">वे रहस्यीकृत हैं। इसलिए उनकी तुलना यहाँ नहीं की जा सकती।</string>
|
||||
<string name="backup_review_gone">चला गया</string>
|
||||
<string name="backup_review_new_tag">नव्य</string>
|
||||
<string name="backup_review_dropped_tag">परित्यक्त</string>
|
||||
<string name="backup_review_demoted_tag">स्थानान्तरित</string>
|
||||
<string name="backup_review_units_tag">इकाई</string>
|
||||
<string name="backup_review_left_tag">शेष</string>
|
||||
<string name="backup_review_renamed_tag">पुनःनामकृत</string>
|
||||
<string name="backup_review_outbox">निर्गतपेटिका</string>
|
||||
<string name="backup_review_outbox_explainer">आप जहाँ प्रकाशित करते हैं</string>
|
||||
<string name="backup_review_inbox">आगतपेटिका</string>
|
||||
<string name="backup_review_inbox_explainer">जहाँ अन्य आप तक अभिगमन करते हैं</string>
|
||||
<string name="backup_review_key_replaced">ग्राहक कुंचिका प्रतिस्थापित</string>
|
||||
<string name="backup_review_key_removed">ग्राहक कुंचिका हटाया गया</string>
|
||||
<string name="backup_review_key_warning">नटज्साप आगे से इस कुंचिका से बद्ध होंगे। यदि इस यन्त्र में वह नहीं है तो आप सम्भाव्यतः उनको यहाँ नहीं चुका सकते।</string>
|
||||
<string name="backup_review_left">शेष</string>
|
||||
<string name="backup_review_joined">जुड गए</string>
|
||||
<string name="backup_review_renamed">पुनःनामकृत</string>
|
||||
<string name="backup_review_was_named">पूर्वतः %1$s था</string>
|
||||
<string name="backup_action_block_again">पुनःबाधित करें %1$s को</string>
|
||||
<string name="backup_action_restore_feeds">सूचनावलियाँ पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_topics">विषय पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_places">स्थल पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_providers">प्रदाता पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_wallet">धनकोष पुनःस्थापन</string>
|
||||
<string name="backup_review_kept">रखे गए</string>
|
||||
<string name="backup_review_receiving_tag">ग्रहण मध्य</string>
|
||||
<string name="backup_review_listed_tag">सूचीबद्ध</string>
|
||||
<string name="backup_review_searching_tag">खोज मध्य</string>
|
||||
<string name="backup_review_storing_tag">अभिलेखन मध्य</string>
|
||||
<string name="backup_review_trusted_tag">विश्वसनीय</string>
|
||||
<string name="backup_review_untrusted_tag">अविश्वसनीय</string>
|
||||
<string name="backup_review_unblocked">%1$s अबाधित</string>
|
||||
<string name="backup_review_unblocked_explainer">अमेथिस्ट पुनः उनसे जुडेगा</string>
|
||||
<string name="backup_review_no_longer_blocked">अब से बाधित नहीं</string>
|
||||
<string name="backup_review_newly_blocked">नव्यतः बाधित</string>
|
||||
<string name="backup_review_still_blocked">अभी भी बाधित</string>
|
||||
<string name="backup_review_allowed_tag">अनुमत</string>
|
||||
<string name="backup_review_moved_tag">स्थानान्तरित</string>
|
||||
<string name="backup_review_feed">सूचनावली</string>
|
||||
<string name="backup_review_topics_gone">विषय हटाए गए</string>
|
||||
<string name="backup_review_places_gone">स्थल हटाए गए</string>
|
||||
<string name="backup_review_new_count_caption">नव्य</string>
|
||||
<string name="backup_review_hashtags_you_follow">विषयसूचक जिनका आप अनुगमन करते हैं</string>
|
||||
<string name="backup_review_places_you_follow">स्थल जिनका आप अनुगमन करते हैं</string>
|
||||
<string name="backup_review_services_changed">%2$s में से %1$s सेवाएँ परिवर्तित</string>
|
||||
<string name="backup_review_services_changed_explainer">वे अब अन्य व्यक्ति से आते है। अथवा किसी से नहीं</string>
|
||||
<string name="backup_review_service">सेवा</string>
|
||||
<string name="backup_review_service_rank">श्रेणी</string>
|
||||
<string name="backup_review_service_followers">अनुचर</string>
|
||||
<string name="backup_review_service_topics">विषयसूची</string>
|
||||
<string name="backup_review_trust_warning">श्रेणीयाँ तथा अनुचर गिनती तथा कचरालेख छालन जो आप देखते हैं इन प्रदाताओं से आते हैं।</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">आपको भुगतान करने की %1$d विधि हटाया गया</item>
|
||||
<item quantity="other">आपको भुगतान करने की %1$d विधियाँ हटाए गए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d प्रस्ताव हटाया गया</item>
|
||||
<item quantity="other">%1$d प्रस्ताव हटाए गए</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">लोग जो आपको भुगतान करते हैं उसी को देखते हैं जो इस सूची में है।</string>
|
||||
<string name="backup_review_offer">बोल्ट॰बारह प्रस्ताव</string>
|
||||
<string name="backup_review_encrypted_cleared">आपने उसे रिक्त किया</string>
|
||||
<string name="backup_review_encrypted_added">आपने उसे बनाया</string>
|
||||
<string name="backup_review_encrypted_changed">आपने उसे परिवर्तित किया</string>
|
||||
<string name="backup_review_wallet_body">आपके धनकोष के टकसाल तथा कुंचिकाएँ आपके लिए रहस्यीकृत हैं। इसलिए उनकी तुलना वस्तु प्रति वस्तु यहाँ नहीं की जा सकती। पुनःस्थापन उन्हीं को लौट डालेगा जिनका अभिलेखन इस यन्त्र ने किया।</string>
|
||||
<string name="backup_review_concord_body">आपके कोंकोर्ड समुदाय आपके लिए रहस्यीकृत हैं। इसलिए उनकी तुलना यहाँ नहीं की जा सकती। पुनःस्थापन उन्हीं को लौट डालेगा जिनका अभिलेखन इस यन्त्र ने किया।</string>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">आपने %1$d की मौनावस्था हटाया</item>
|
||||
<item quantity="other">आपने %1$d की मौनावस्था हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">आपने %1$d परिचय प्रपत्रस्थान हटाया</item>
|
||||
<item quantity="other">आपने %1$d परिचय प्रपत्रस्थान हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">आपने %1$d सार्वजनिक पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d सार्वजनिक पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">आपने %1$d सीधासन्देश पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d सीधासन्देश पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">आपने %1$d समूहचर्चा कुंचिका पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d समूहचर्चा कुंचिका पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">आपने %1$d खोज पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d खोज पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">आपने %1$d अनुक्रमणीकार पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d अनुक्रमणीकार पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक सूचनावली हटाया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारक सूचनावलियाँ हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">आपने %1$d निजी पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d निजी पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक पर विश्वास करना रोक दिया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारकों पर विश्वास करना रोक दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक अबाधित किया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारकों को अबाधित किए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">आपने %1$d सार्वजनिक चर्चा छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d सार्वजनिक चर्चाओं को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">आपने %1$d समुदाय छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d समुदायों को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">आपने %1$d चर्चाशाला छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d चर्चाशालाओं को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">आपने %1$d समूह छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d समूहों को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">आपने %1$d इष्ट सूचनावली हटाया</item>
|
||||
<item quantity="other">आपने %1$d इष्ट सूचनावलियों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">आपने %1$d विषयसूचक का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d विषयसूचकों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">आपने %1$d स्थल का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d स्थलों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">आपने %1$d विश्वाससेवा प्रदाता परिवर्तित किया</item>
|
||||
<item quantity="other">आपने %1$d विश्वाससेवाओं के प्रदाता को परिवर्तित किया</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">आपने %1$d नटज्साप टकसाल हटाया</item>
|
||||
<item quantity="other">आपने %1$d नटज्साप टकसालों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">आपने %1$d भुगतान प्राप्त करने की विधि हटाया</item>
|
||||
<item quantity="other">आपने %1$d भुगतान प्राप्त करने के विधियों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">आपने %1$d बोल्ट॰बारह प्रस्ताव हटाया</item>
|
||||
<item quantity="other">आपने %1$d बोल्ट॰बारह प्रस्तावों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s तथा %2$d जोडा</item>
|
||||
<item quantity="other">%1$s तथा %2$d जोडे</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s तथा %2$d का अनुगमन किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d का अनुगमन किए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s तथा %2$d को मौनकृत किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d को मौनकृत किए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s तथा %2$d से जुडे</item>
|
||||
<item quantity="other">%1$s तथा %2$d से जुडे</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s तथा %2$d बाधित किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d को बाधित किए</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">आपके अमेथिस्ट समचरणीकृत क्रमक स्थापना विकल्पों को परिवर्तित किया गया एक अन्य क्रमक में और वह अमेथिस्ट नहीं था। इससे समस्याएँ उत्पन्न हो सकते हैं।</string>
|
||||
<string name="backup_card_nutzap_key_replaced">आपने अपनी नटज्साप कुंचिका का प्रतिस्थापन किया</string>
|
||||
<string name="backup_card_nutzap_key_removed">आपने अपनी नटज्साप कुंचिका को हटाया</string>
|
||||
<string name="backup_card_wallet_emptied">आपने अपना काशयू धनकोष रिक्त किया</string>
|
||||
<string name="backup_card_wallet_rewritten">आपने अपने काशयू धनकोष को परिवर्तित किया</string>
|
||||
<string name="backup_card_concord_emptied">आपने अपनी कोंकोर्ड सूची रिक्त की</string>
|
||||
<string name="backup_card_concord_rewritten">आपने अपनी कोंकोर्ड सूची का परिवर्तन किया</string>
|
||||
<string name="backup_conflict_keep_new">नया संस्करण का उपयोग करें</string>
|
||||
<string name="backup_conflict_relay_read_only">पठनेवशक्य</string>
|
||||
<string name="backup_conflict_relay_write_only">लेखनेवशक्य</string>
|
||||
<string name="backup_conflict_relay_read_write">पठन तथा लेखन</string>
|
||||
<string name="backup_type_profile">परिचय</string>
|
||||
<string name="backup_type_profile_explainer">आपका नाम चित्र चरित तथा भुगतान पते। जैसे सब को दिखते हैं वैसे।</string>
|
||||
<string name="backup_type_follow_list">अनुचरण सूची</string>
|
||||
<string name="backup_type_follow_list_explainer">निर्णय करता है किसके पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_mute_list">मौन सूची</string>
|
||||
<string name="backup_type_mute_list_explainer">छिपाता है लोग शब्द विषयसूचक तथा सूत्र उन सब में से जो आप देखते हैं।</string>
|
||||
<string name="backup_type_outbox_inbox_relays">सार्वजनिक पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">सबको बताता है आपके पत्र कहाँ प्राप्त करें तथा आपको उत्तर तथा उल्लेखों को कहाँ भेजें।</string>
|
||||
<string name="backup_type_dm_relays">सीधासन्देश पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_dm_relays_explainer">जहाँ अन्य आपके निजी सन्देश भेजते हैं।</string>
|
||||
<string name="backup_type_key_package_relays">समूहचर्चा कुंचिका पुनःप्रसारक</string>
|
||||
<string name="backup_type_key_package_relays_explainer">जहाँ अन्य उन कुंचिकाओं को प्राप्त करते हैं आपको रहस्यीकृत समूहचर्चाओं में जोडने के लिए।</string>
|
||||
<string name="backup_type_search_relays">खोज पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_search_relays_explainer">उपयुक्त पुनःप्रसारक जब आप खोजते हैं।</string>
|
||||
<string name="backup_type_indexer_relays">अनुक्रमणीकार पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_indexer_relays_explainer">पुनःप्रसारक उपयुक्त अन्य लोगों के परिचय तथा पुनःप्रसारक सूचियों को प्राप्त करने के लिए।</string>
|
||||
<string name="backup_type_relay_feeds">इष्ट पुनःप्रसारक सूचनावलियाँ</string>
|
||||
<string name="backup_type_relay_feeds_explainer">पुनःप्रसारक जिनका आप वीक्षण करते हैं सूचनावलियों के रूप में।</string>
|
||||
<string name="backup_type_blocked_relays">बाधित पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_blocked_relays_explainer">पुनःप्रसारक जिनसे यह क्रमक कभी भी संयोजन नहीं करता।</string>
|
||||
<string name="backup_type_trusted_relays">विश्वसनीय पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_trusted_relays_explainer">पुनःप्रसारक जिनपर आप पर्याप्त विश्वास करते हैं बिना पूछे उनसे संयोजन करने के लिए।</string>
|
||||
<string name="backup_type_private_outbox_relays">निजी पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">जहाँ आपके पाण्डुलिपियाँ तथा निजी जानकारी रखे जाते हैं।</string>
|
||||
<string name="backup_type_app_settings">समचरणीकृत क्रमक स्थापना विकल्प</string>
|
||||
<string name="backup_type_app_settings_explainer">अमेथिस्ट स्थापना विकल्प समचरणीकृत आपके यन्त्रों में। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_public_chats">सार्वजनिक चर्चा सूची</string>
|
||||
<string name="backup_type_public_chats_explainer">सार्वजनिक चर्चाएँ जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_communities">समुदाय सूची</string>
|
||||
<string name="backup_type_communities_explainer">समुदाय जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_hashtags">अनुचरित विषयसूचक</string>
|
||||
<string name="backup_type_hashtags_explainer">विषयसूचक जिससे युक्त पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_geohashes">अनुचरित स्थान</string>
|
||||
<string name="backup_type_geohashes_explainer">स्थान जहाँ से पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_favorite_algo_feeds">इष्ट सूचनावली सूची</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">कलनविध्यात्मक सूचनावलियाँ जिनको आपने अभिलेखित किया।</string>
|
||||
<string name="backup_type_ephemeral_chats">अस्थायी चर्चा सूची</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">अस्थायी चर्चा शालाएँ जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_relay_groups">समूह सूची</string>
|
||||
<string name="backup_type_relay_groups_explainer">पुनःप्रसारक आधारित समूह जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_concord_communities">कोंकोर्ड समुदाय सूची</string>
|
||||
<string name="backup_type_concord_communities_explainer">कोंकोर्ड समुदाय जिनसे आप जुडे। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_trust_providers">विश्वाससेवा प्रदाता सूची</string>
|
||||
<string name="backup_type_trust_providers_explainer">सेवाएँ जिनपर आप विश्वास करते है आपके लिए लोगों का सत्यापन तथा श्रेणीकरण करने के लिए।</string>
|
||||
<string name="backup_type_cashu_wallet">काशयू धनकोष</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">आपके ईकाश धनकोष स्थापना विकल्प तथा टकसाल। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_nutzap_info">नटज्साप प्राप्ती स्थापना विकल्प</string>
|
||||
<string name="backup_type_nutzap_info_explainer">टकसाल तथा कुंचिका जिनका उपयोग अन्य करते हैं आपको नटज्साप भेजने के लिए।</string>
|
||||
<string name="backup_type_payment_targets">भुगतान पते</string>
|
||||
<string name="backup_type_payment_targets_explainer">विधियाँ जिनसे अन्य लोग आपको भुगतान कर सके।</string>
|
||||
<string name="backup_type_bolt12_offers">बोल्ट॰बारह प्रस्ताव</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">लैटनिंग प्रस्ताव जिनका उपयोग करके अन्य लोग आपको भुगतान करते हैं।</string>
|
||||
<string name="backup_type_other">सूची</string>
|
||||
<string name="backup_type_other_explainer">इस यन्त्र पर अभिलेखित सूची।</string>
|
||||
<string name="backup_entry_profile_field">परिचय प्रपत्रस्थान</string>
|
||||
<string name="backup_entry_person">लोग</string>
|
||||
<string name="backup_entry_hashtag">विषयसूचक</string>
|
||||
<string name="backup_entry_word">शब्द</string>
|
||||
<string name="backup_entry_thread">सूत्र</string>
|
||||
<string name="backup_entry_public_chat">सार्वजनिक चर्चाएँ</string>
|
||||
<string name="backup_entry_community">समुदाय</string>
|
||||
<string name="backup_entry_algo_feed">सूचनावलियाँ</string>
|
||||
<string name="backup_entry_location">स्थान</string>
|
||||
<string name="backup_entry_relay">पुनःप्रसारक</string>
|
||||
<string name="backup_entry_relay_group">समूह</string>
|
||||
<string name="backup_entry_chat_room">चर्चा शालाएँ</string>
|
||||
<string name="backup_entry_trust_provider">विश्वाससेवा प्रदाता</string>
|
||||
<string name="backup_entry_mint">टकसाल</string>
|
||||
<string name="backup_entry_nutzap_key">नटज्साप कुंचिकाएँ</string>
|
||||
<string name="backup_entry_payment_target">भुगतान पते</string>
|
||||
<string name="backup_entry_offer">प्रस्ताव</string>
|
||||
<string name="backup_entry_identity_claim">सम्बन्धित व्यक्तिगण</string>
|
||||
<string name="backup_entry_other">अन्य प्रविष्टियाँ</string>
|
||||
<string name="backup_profile_field_name">प्रयोक्तानाम</string>
|
||||
<string name="backup_profile_field_display_name">प्रदर्शन नाम</string>
|
||||
<string name="backup_profile_field_about">जानकारी</string>
|
||||
<string name="backup_profile_field_picture">चित्र</string>
|
||||
<string name="backup_profile_field_banner">ध्वज</string>
|
||||
<string name="backup_profile_field_website">जालस्थान</string>
|
||||
<string name="backup_profile_field_nip05">नोस्टर पता</string>
|
||||
<string name="backup_profile_field_lud16">लैटनिंग पता</string>
|
||||
<string name="backup_profile_field_lud06">लैटनिंग जालपता</string>
|
||||
<string name="backup_profile_field_pronouns">सर्वनाम</string>
|
||||
<string name="backup_profile_field_birthday">जन्मदिन</string>
|
||||
<string name="backup_profile_field_clink_offer">क्लिंक॰ प्रस्ताव</string>
|
||||
<string name="backup_profile_field_bot">क्रमचर चिह्न</string>
|
||||
</resources>
|
||||
|
||||
@@ -353,322 +353,4 @@
|
||||
<string name="mute_button">Hang bekapcsolva. Koppintson a némításhoz</string>
|
||||
<string name="play">Lejátszás</string>
|
||||
<string name="pause">Szüneteltetés</string>
|
||||
<string name="backup_conflict_title">Ön módosította a következőt: %1$s, egy másik alkalmazásban</string>
|
||||
<string name="backup_conflict_removed">Eltávolítva (%1$s)</string>
|
||||
<string name="backup_conflict_added">Hozzáadva (%1$s)</string>
|
||||
<string name="backup_conflict_changed">Módosítva (%1$s)</string>
|
||||
<string name="backup_conflict_private_cleared">Ön eltávolította az összes privát (titkosított) elemet.</string>
|
||||
<string name="backup_conflict_private_changed">Ön privát (titkosított) elemeket is módosított. Ezek itt nem hasonlíthatók össze.</string>
|
||||
<string name="backup_conflict_private_added">Ön privát (titkosított) elemeket adott hozzá.</string>
|
||||
<string name="backup_conflict_restore_mine">Mentett verzió visszaállítása</string>
|
||||
<string name="backup_review_saved">Ezen az eszközön</string>
|
||||
<string name="backup_review_new">Új verzió</string>
|
||||
<string name="backup_review_not_set">Nincs beállítva</string>
|
||||
<string name="backup_conflict_count_removed">%1$s eltávolítva</string>
|
||||
<string name="backup_conflict_count_added">%1$s hozzáadva</string>
|
||||
<string name="backup_conflict_count_changed">%1$s módosítva</string>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">%1$d személyt nem követ többé</item>
|
||||
<item quantity="other">%1$d személyt nem követ többé</item>
|
||||
</plurals>
|
||||
<string name="backup_card_accept">Elfogadás</string>
|
||||
<string name="backup_review_title_updated">%1$s frissítve</string>
|
||||
<string name="backup_review_title_cleared">%1$s törölve</string>
|
||||
<string name="backup_review_changed_by_other_app">Módosítva egy másik alkalmazásban · %1$s</string>
|
||||
<string name="backup_action_keep_count">%1$s megtartása</string>
|
||||
<string name="backup_action_restore_count">%1$s visszaállítása</string>
|
||||
<string name="backup_action_remute">%1$s újbóli némítása</string>
|
||||
<string name="backup_action_rejoin">Újbóli csatlakozás ehhez: %1$s</string>
|
||||
<string name="backup_action_restore_profile">Profil visszaállítása</string>
|
||||
<string name="backup_action_restore_relays">Átjátszók visszaállítása</string>
|
||||
<string name="backup_review_kept_count">%1$s megtartva</string>
|
||||
<string name="backup_review_dropped_count">%1$s elvetve</string>
|
||||
<string name="backup_review_new_count">%1$s új</string>
|
||||
<string name="backup_review_tab_dropped">Elvetve · %1$s</string>
|
||||
<string name="backup_review_tab_new">Új · %1$s</string>
|
||||
<string name="backup_review_tab_edited">Szerkesztve · %1$s</string>
|
||||
<string name="backup_review_search_people">%1$s személy keresése</string>
|
||||
<string name="backup_review_nothing_here">Itt nincs semmi</string>
|
||||
<string name="backup_review_unmuted">%1$s némítása feloldva</string>
|
||||
<string name="backup_review_unmuted_explainer">Ezek újra megjelenhetnek a hírfolyamaiban</string>
|
||||
<string name="backup_review_newly_muted">%1$s újonnan némítva</string>
|
||||
<string name="backup_review_words_and_hashtags">Szavak és kulcsszavak</string>
|
||||
<string name="backup_review_names_and_more">%1$s és %2$s további</string>
|
||||
<string name="backup_review_private_wiped_title">Ön eltávolította az összes privát elemet</string>
|
||||
<string name="backup_review_private_wiped_body">Titkosítva vannak, így csak Ön láthatja, mik voltak. A visszaállítás mindet visszahozza.</string>
|
||||
<string name="backup_review_private_added_title">Ön priváttá tette az elemeket</string>
|
||||
<string name="backup_review_private_added_body">Most már titkosítva vannak, valószínűleg ide kerültek a fenti nyilvános elemek.</string>
|
||||
<string name="backup_review_private_changed_title">Ön módosította a privát elemeket</string>
|
||||
<string name="backup_review_private_changed_body">Titkosítva vannak, így itt nem hasonlíthatók össze.</string>
|
||||
<string name="backup_review_gone">Eltűnt</string>
|
||||
<string name="backup_review_new_tag">Új</string>
|
||||
<string name="backup_review_dropped_tag">Elvetve</string>
|
||||
<string name="backup_review_demoted_tag">Áthelyezve</string>
|
||||
<string name="backup_review_units_tag">Egységek</string>
|
||||
<string name="backup_review_left_tag">Elhagyva</string>
|
||||
<string name="backup_review_renamed_tag">Átnevezve</string>
|
||||
<string name="backup_review_outbox">Kimenő</string>
|
||||
<string name="backup_review_outbox_explainer">ahol közzétesz</string>
|
||||
<string name="backup_review_inbox">Bejövő</string>
|
||||
<string name="backup_review_inbox_explainer">ahol mások elérik Önt</string>
|
||||
<string name="backup_review_key_replaced">Fogadási kulcs lecserélve</string>
|
||||
<string name="backup_review_key_removed">Fogadási kulcs eltávolítva</string>
|
||||
<string name="backup_review_key_warning">A nutzapok ehhez az új kulcshoz lesznek kötve. Ha ez az eszköz nem rendelkezik vele, lehet, hogy itt nem tudja beváltani őket.</string>
|
||||
<string name="backup_review_left">elhagyta a csoportot</string>
|
||||
<string name="backup_review_joined">csatlakozott</string>
|
||||
<string name="backup_review_renamed">átnevezte</string>
|
||||
<string name="backup_review_was_named">„%1$s” volt</string>
|
||||
<string name="backup_action_block_again">%1$s újbóli letiltása</string>
|
||||
<string name="backup_action_restore_feeds">Hírfolyamok visszaállítása</string>
|
||||
<string name="backup_action_restore_topics">Témák visszaállítása</string>
|
||||
<string name="backup_action_restore_places">Helyek visszaállítása</string>
|
||||
<string name="backup_action_restore_providers">Szolgáltatók visszaállítása</string>
|
||||
<string name="backup_action_restore_wallet">Pénztárca visszaállítása</string>
|
||||
<string name="backup_review_kept">megtartva</string>
|
||||
<string name="backup_review_receiving_tag">Fogadás</string>
|
||||
<string name="backup_review_listed_tag">Listázva</string>
|
||||
<string name="backup_review_searching_tag">Keresés</string>
|
||||
<string name="backup_review_storing_tag">Tárolás</string>
|
||||
<string name="backup_review_trusted_tag">Megbízható</string>
|
||||
<string name="backup_review_untrusted_tag">Nem megbízható</string>
|
||||
<string name="backup_review_unblocked">%1$s letiltása feloldva</string>
|
||||
<string name="backup_review_unblocked_explainer">Az Amethyst újra kapcsolódni fog hozzájuk</string>
|
||||
<string name="backup_review_no_longer_blocked">Már nincs letiltva</string>
|
||||
<string name="backup_review_newly_blocked">Újonnan letiltva</string>
|
||||
<string name="backup_review_still_blocked">Továbbra is le van tiltva</string>
|
||||
<string name="backup_review_allowed_tag">Engedélyezve</string>
|
||||
<string name="backup_review_moved_tag">Áthelyezve</string>
|
||||
<string name="backup_review_feed">Hírfolyam</string>
|
||||
<string name="backup_review_topics_gone">eltűnt témák</string>
|
||||
<string name="backup_review_places_gone">eltűnt helyek</string>
|
||||
<string name="backup_review_new_count_caption">új</string>
|
||||
<string name="backup_review_hashtags_you_follow">Ön által követett kulcsszavak</string>
|
||||
<string name="backup_review_places_you_follow">Ön által követett helyek</string>
|
||||
<string name="backup_review_services_changed">%2$s szolgáltatásból %1$s módosult</string>
|
||||
<string name="backup_review_services_changed_explainer">Most már valaki mástól vagy senkitől sem származnak</string>
|
||||
<string name="backup_review_service">Szolgáltatás</string>
|
||||
<string name="backup_review_service_rank">Rang</string>
|
||||
<string name="backup_review_service_followers">Követők</string>
|
||||
<string name="backup_review_service_topics">Témák</string>
|
||||
<string name="backup_review_trust_warning">A látott rangok, követőszámok és a kéretlen tartalomszűrés ezektől a szolgáltatóktól származnak.</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">%1$d fizetési mód eltávolítva</item>
|
||||
<item quantity="other">%1$d fizetési mód eltávolítva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d ajánlat eltávolítva</item>
|
||||
<item quantity="other">%1$d ajánlat eltávolítva</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">A fizető emberek csak azt látják, ami ebben a listában van.</string>
|
||||
<string name="backup_review_offer">BOLT12 ajánlat</string>
|
||||
<string name="backup_review_encrypted_cleared">Ön kiürítette</string>
|
||||
<string name="backup_review_encrypted_added">Ön hozta létre</string>
|
||||
<string name="backup_review_encrypted_changed">Ön módosította</string>
|
||||
<string name="backup_review_wallet_body">A saját pénztárca pénzverdéi és kulcsai Önhöz vannak titkosítva, így itt nem hasonlíthatók össze tételesen. A visszaállítás pontosan azt hozza vissza, amit ez az eszköz mentett.</string>
|
||||
<string name="backup_review_concord_body">A Concord közösségei Önhöz vannak titkosítva, így itt nem hasonlíthatók össze. A visszaállítás pontosan azt hozza vissza, amit ez az eszköz mentett.</string>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">Ön %1$d dolog némítását oldotta fel</item>
|
||||
<item quantity="other">%1$d dolog némítását oldotta fel</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">Ön %1$d profilmezőt távolított el</item>
|
||||
<item quantity="other">%1$d profilmezőt távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">Ön %1$d nyilvános átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d nyilvános átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">Ön %1$d privát üzenetátjátszót távolított el</item>
|
||||
<item quantity="other">%1$d privát üzenet átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">Ön %1$d csoportos csevegési kulcsátjátszót távolított el</item>
|
||||
<item quantity="other">%1$d csoportcsevegés kulcs átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">Ön %1$d kereső átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d kereső átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">Ön %1$d indexelő átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d indexelő átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">Ön %1$d átjátszó-hírfolyamot távolított el</item>
|
||||
<item quantity="other">%1$d átjátszó hírfolyamot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">Ön %1$d privát átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d privát átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">Ön %1$d átjátszóban nem bízik többé</item>
|
||||
<item quantity="other">%1$d átjátszóban nem bízik többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">Ön %1$d átjátszó letiltását oldotta fel</item>
|
||||
<item quantity="other">%1$d átjátszó blokkolását oldotta fel</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">Ön %1$d nyilvános csevegést hagyott el</item>
|
||||
<item quantity="other">%1$d nyilvános csevegést hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">Ön %1$d közösséget hagyott el</item>
|
||||
<item quantity="other">%1$d közösséget hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">Ön %1$d csevegőszobát hagyott el</item>
|
||||
<item quantity="other">%1$d csevegőszobát hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">Ön %1$d csoportot hagyott el</item>
|
||||
<item quantity="other">%1$d csoportot hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">Ön %1$d kedvenc hírfolyamot távolított el</item>
|
||||
<item quantity="other">%1$d kedvenc hírfolyamot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">Ön %1$d kulcsszót nem követ többé</item>
|
||||
<item quantity="other">%1$d hashtaget nem követ többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">Ön %1$d helyet nem követ többé</item>
|
||||
<item quantity="other">%1$d helyet nem követ többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">Ön %1$d bizalmi szolgáltatás szolgáltatóját módosította</item>
|
||||
<item quantity="other">%1$d bizalmi szolgáltatás szolgáltatóját változtatta meg</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">Ön %1$d nutzap pénzverdét távolított el</item>
|
||||
<item quantity="other">%1$d nutzap pénzverdét távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">Ön %1$d fizetési módot távolított el</item>
|
||||
<item quantity="other">%1$d fizetési módot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">Ön %1$d BOLT12 ajánlatot távolított el</item>
|
||||
<item quantity="other">%1$d BOLT12 ajánlatot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s és %2$d hozzáadva</item>
|
||||
<item quantity="other">%1$s és %2$d hozzáadva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s és %2$d követve</item>
|
||||
<item quantity="other">%1$s és %2$d követve</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s és %2$d némítva</item>
|
||||
<item quantity="other">%1$s és %2$d némítva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s és %2$d csatlakozva</item>
|
||||
<item quantity="other">%1$s és %2$d csatlakozva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s és %2$d letiltva</item>
|
||||
<item quantity="other">%1$s és %2$d letiltva</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">A szinkronizált Amethyst alkalmazásbeállításai egy másik, nem Amethyst alkalmazásban módosultak. Ez problémákat okozhat.</string>
|
||||
<string name="backup_card_nutzap_key_replaced">Ön lecserélte a nutzap kulcsát</string>
|
||||
<string name="backup_card_nutzap_key_removed">Ön eltávolította a nutzap kulcsát</string>
|
||||
<string name="backup_card_wallet_emptied">Ön kiürítette a Cashu pénztárcáját</string>
|
||||
<string name="backup_card_wallet_rewritten">Ön módosította a Cashu pénztárcáját</string>
|
||||
<string name="backup_card_concord_emptied">Ön kiürítette a Concord listáját</string>
|
||||
<string name="backup_card_concord_rewritten">Ön módosította a Concord listáját</string>
|
||||
<string name="backup_conflict_keep_new">Új verzió használata</string>
|
||||
<string name="backup_conflict_relay_read_only">csak olvasható</string>
|
||||
<string name="backup_conflict_relay_write_only">csak írható</string>
|
||||
<string name="backup_conflict_relay_read_write">olvasás és írás</string>
|
||||
<string name="backup_type_profile">profil</string>
|
||||
<string name="backup_type_profile_explainer">Az Ön neve, képe, bemutatkozása és fizetési címei, ahogy mindenki látja őket.</string>
|
||||
<string name="backup_type_follow_list">követési lista</string>
|
||||
<string name="backup_type_follow_list_explainer">Meghatározza, kinek a bejegyzései jelenjenek meg a kezdőlapon.</string>
|
||||
<string name="backup_type_mute_list">némítási lista</string>
|
||||
<string name="backup_type_mute_list_explainer">Elrejti a személyeket, szavakat, kulcsszavakat és beszélgetéseket mindenből, amit lát.</string>
|
||||
<string name="backup_type_outbox_inbox_relays">nyilvános átjátszólista</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">Megmondja mindenkinek, hol találhatók a bejegyzései, és hová küldjék a válaszokat és említéseket.</string>
|
||||
<string name="backup_type_dm_relays">privát üzenet átjátszólista</string>
|
||||
<string name="backup_type_dm_relays_explainer">Ahová mások kézbesítik a privát üzeneteit.</string>
|
||||
<string name="backup_type_key_package_relays">csoportos csevegési kulcsátjátszók</string>
|
||||
<string name="backup_type_key_package_relays_explainer">Ahol mások megtalálják a kulcsokat, hogy titkosított csoportos csevegésekhez adhassák Önt.</string>
|
||||
<string name="backup_type_search_relays">kereső átjátszólista</string>
|
||||
<string name="backup_type_search_relays_explainer">Kereséskor használt átjátszók.</string>
|
||||
<string name="backup_type_indexer_relays">indexelő átjátszólista</string>
|
||||
<string name="backup_type_indexer_relays_explainer">Azok az átjátszók, amelyeket mások profiljainak és átjátszólistáinak megtalálásához használnak.</string>
|
||||
<string name="backup_type_relay_feeds">kedvenc átjátszóhírfolyamok</string>
|
||||
<string name="backup_type_relay_feeds_explainer">Olyan átjátszók, amelyeket hírfolyamként böngész.</string>
|
||||
<string name="backup_type_blocked_relays">letiltott átjátszólista</string>
|
||||
<string name="backup_type_blocked_relays_explainer">Átjátszók, amelyekhez ez az alkalmazás soha nem kapcsolódik.</string>
|
||||
<string name="backup_type_trusted_relays">megbízható átjátszólista</string>
|
||||
<string name="backup_type_trusted_relays_explainer">Átjátszók, amelyekhez kérdezés nélkül kapcsolódhat.</string>
|
||||
<string name="backup_type_private_outbox_relays">privát átjátszólista</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">Ahol a piszkozatai és privát adatai tárolódnak.</string>
|
||||
<string name="backup_type_app_settings">szinkronizált alkalmazásbeállítások</string>
|
||||
<string name="backup_type_app_settings_explainer">Az eszközök között szinkronizált Amethyst-beállítások. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_public_chats">nyilvános csevegési lista</string>
|
||||
<string name="backup_type_public_chats_explainer">Nyilvános csevegések, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_communities">közösséglista</string>
|
||||
<string name="backup_type_communities_explainer">Közösségek, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_hashtags">követett kulcsszavak</string>
|
||||
<string name="backup_type_hashtags_explainer">Kulcsszavak, amelyek bejegyzései megjelennek a hírfolyamban.</string>
|
||||
<string name="backup_type_geohashes">követett helyek</string>
|
||||
<string name="backup_type_geohashes_explainer">Helyek, amelyek bejegyzései megjelennek a hírfolyamaiban.</string>
|
||||
<string name="backup_type_favorite_algo_feeds">kedvenc hírfolyamlista</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">Mentett algoritmus-hírfolyamok.</string>
|
||||
<string name="backup_type_ephemeral_chats">rövid életű csevegési lista</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">Rövid életű csevegőszobák, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_relay_groups">csoportlista</string>
|
||||
<string name="backup_type_relay_groups_explainer">Átjátszó-alapú csoportok, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_concord_communities">Concord közösséglista</string>
|
||||
<string name="backup_type_concord_communities_explainer">A Concord közösségek, amelyekhez csatlakozott. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_trust_providers">bizalmi szolgáltatólista</string>
|
||||
<string name="backup_type_trust_providers_explainer">A szolgáltatások, amelyekben megbízik, hogy rangsorolják és ellenőrizzék Önnek az embereket.</string>
|
||||
<string name="backup_type_cashu_wallet">Cashu pénztárca</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">Az ecash pénztárca beállításai és pénzverdéi. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_nutzap_info">nutzap fogadási beállítások</string>
|
||||
<string name="backup_type_nutzap_info_explainer">A pénzverdék és a kulcs, amelyeket mások a nutzapok küldéséhez használnak az Ön számára.</string>
|
||||
<string name="backup_type_payment_targets">fizetési címek</string>
|
||||
<string name="backup_type_payment_targets_explainer">A módok, ahogy mások fizethetnek Önnek.</string>
|
||||
<string name="backup_type_bolt12_offers">BOLT12 ajánlatok</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">A lightning ajánlatok, amelyeket mások a fizetéshez használnak az Ön számára.</string>
|
||||
<string name="backup_type_other">lista</string>
|
||||
<string name="backup_type_other_explainer">Egy listaelem ezen az eszközön mentve.</string>
|
||||
<string name="backup_entry_profile_field">Profilmezők</string>
|
||||
<string name="backup_entry_person">Személyek</string>
|
||||
<string name="backup_entry_hashtag">Kulcsszavak</string>
|
||||
<string name="backup_entry_word">Szavak</string>
|
||||
<string name="backup_entry_thread">Beszélgetések</string>
|
||||
<string name="backup_entry_public_chat">Nyilvános csevegések</string>
|
||||
<string name="backup_entry_community">Közösségek</string>
|
||||
<string name="backup_entry_algo_feed">Hírfolyamok</string>
|
||||
<string name="backup_entry_location">Helyek</string>
|
||||
<string name="backup_entry_relay">Átjátszók</string>
|
||||
<string name="backup_entry_relay_group">Csoportok</string>
|
||||
<string name="backup_entry_chat_room">Csevegőszobák</string>
|
||||
<string name="backup_entry_trust_provider">Bizalmi szolgáltatók</string>
|
||||
<string name="backup_entry_mint">Pénzverdék</string>
|
||||
<string name="backup_entry_nutzap_key">Nutzap kulcsok</string>
|
||||
<string name="backup_entry_payment_target">Fizetési címek</string>
|
||||
<string name="backup_entry_offer">Ajánlatok</string>
|
||||
<string name="backup_entry_identity_claim">Kapcsolt identitások</string>
|
||||
<string name="backup_entry_other">Egyéb bejegyzések</string>
|
||||
<string name="backup_profile_field_name">Felhasználónév</string>
|
||||
<string name="backup_profile_field_display_name">Megjelenített név</string>
|
||||
<string name="backup_profile_field_about">Névjegy</string>
|
||||
<string name="backup_profile_field_picture">Kép</string>
|
||||
<string name="backup_profile_field_banner">Borító</string>
|
||||
<string name="backup_profile_field_website">Weboldal</string>
|
||||
<string name="backup_profile_field_nip05">Nostr-cím</string>
|
||||
<string name="backup_profile_field_lud16">Lightning-cím</string>
|
||||
<string name="backup_profile_field_lud06">LNURL</string>
|
||||
<string name="backup_profile_field_pronouns">Névmások</string>
|
||||
<string name="backup_profile_field_birthday">Születésnap</string>
|
||||
<string name="backup_profile_field_clink_offer">CLINK-ajánlat</string>
|
||||
<string name="backup_profile_field_bot">Bot jelölő</string>
|
||||
</resources>
|
||||
|
||||
@@ -381,382 +381,4 @@
|
||||
<string name="mute_button">Dźwięk włączony. Kliknij, aby wyciszyć</string>
|
||||
<string name="play">Odtwórz</string>
|
||||
<string name="pause">Pauza</string>
|
||||
<string name="backup_conflict_title">Zmieniłeś %1$s w innej aplikacji</string>
|
||||
<string name="backup_conflict_removed">Usunięto (%1$s)</string>
|
||||
<string name="backup_conflict_added">Dodano (%1$s)</string>
|
||||
<string name="backup_conflict_changed">Zmieniono (%1$s)</string>
|
||||
<string name="backup_conflict_private_cleared">Usunąłeś wszystkie prywatne (zaszyfrowane) elementy.</string>
|
||||
<string name="backup_conflict_private_changed">Zmieniłeś również elementy prywatne (zaszyfrowane). Nie można ich tutaj porównać.</string>
|
||||
<string name="backup_conflict_private_added">Dodano prywatne (zaszyfrowane) pozycje.</string>
|
||||
<string name="backup_conflict_restore_mine">Przywróć zapisaną wersję</string>
|
||||
<string name="backup_review_saved">Na tym urządzeniu</string>
|
||||
<string name="backup_review_new">Nowa wersja</string>
|
||||
<string name="backup_review_not_set">Nie ustawiono</string>
|
||||
<string name="backup_conflict_count_removed">Usunięto %1$s</string>
|
||||
<string name="backup_conflict_count_added">Dodano %1$s</string>
|
||||
<string name="backup_conflict_count_changed">%1$s zmieniono</string>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">Przestałeś obserwować %1$d osobę</item>
|
||||
<item quantity="few">Przestałeś obserwować %1$d osób</item>
|
||||
<item quantity="many">Przestałeś obserwować %1$d osób</item>
|
||||
<item quantity="other">Przestałeś obserwować %1$d osoby</item>
|
||||
</plurals>
|
||||
<string name="backup_card_accept">Zaakceptuj</string>
|
||||
<string name="backup_review_title_updated">%1$s zaktualizowano</string>
|
||||
<string name="backup_review_title_cleared">%1$s wyczyszczono</string>
|
||||
<string name="backup_review_changed_by_other_app">Zmieniono w innej aplikacji · %1$s</string>
|
||||
<string name="backup_action_keep_count">Zachowaj %1$s</string>
|
||||
<string name="backup_action_restore_count">Przywróć %1$s</string>
|
||||
<string name="backup_action_remute">Ponownie wycisz %1$s</string>
|
||||
<string name="backup_action_rejoin">Ponów %1$s</string>
|
||||
<string name="backup_action_restore_profile">Przywróć profil</string>
|
||||
<string name="backup_action_restore_relays">Przywróć transmitery</string>
|
||||
<string name="backup_review_kept_count">Zachowano %1$s</string>
|
||||
<string name="backup_review_dropped_count">%1$s odrzuconych</string>
|
||||
<string name="backup_review_new_count">%1$s nowych</string>
|
||||
<string name="backup_review_tab_dropped">Usunięte · %1$s</string>
|
||||
<string name="backup_review_tab_new">Nowe · %1$s</string>
|
||||
<string name="backup_review_tab_edited">Edytowane · %1$s</string>
|
||||
<string name="backup_review_search_people">Szukaj %1$s osób</string>
|
||||
<string name="backup_review_nothing_here">Nic tu nie ma!</string>
|
||||
<string name="backup_review_unmuted">%1$s odblokowanych</string>
|
||||
<string name="backup_review_unmuted_explainer">Mogą one ponownie pojawić się w Twoich informacjach</string>
|
||||
<string name="backup_review_newly_muted">%1$s nowo wyciszonych</string>
|
||||
<string name="backup_review_words_and_hashtags">Wyrazy & hasztagi</string>
|
||||
<string name="backup_review_names_and_more">%1$s i %2$s więcej</string>
|
||||
<string name="backup_review_private_wiped_title">Usunąłeś wszystkie prywatne elementy</string>
|
||||
<string name="backup_review_private_wiped_body">Są zaszyfrowane, więc tylko Ty możesz zobaczyć, co to było. Odtworzenie przywróci je wszystkie.</string>
|
||||
<string name="backup_review_private_added_title">Ustawiłeś te pozycje jako prywatne</string>
|
||||
<string name="backup_review_private_added_body">Są teraz zaszyfrowane, co prawdopodobnie wyjaśnia, gdzie podziały się powyższe elementy publiczne.</string>
|
||||
<string name="backup_review_private_changed_title">Zmieniłeś prywatne elementy</string>
|
||||
<string name="backup_review_private_changed_body">Są zaszyfrowane, więc nie można ich tu porównać.</string>
|
||||
<string name="backup_review_gone">Zniknęła</string>
|
||||
<string name="backup_review_new_tag">Nowa</string>
|
||||
<string name="backup_review_dropped_tag">Usunięta</string>
|
||||
<string name="backup_review_demoted_tag">Przeniesiona</string>
|
||||
<string name="backup_review_units_tag">Jednostek</string>
|
||||
<string name="backup_review_left_tag">Zostało</string>
|
||||
<string name="backup_review_renamed_tag">Zmieniono nazwę</string>
|
||||
<string name="backup_review_outbox">Skrzynka nadawcza</string>
|
||||
<string name="backup_review_outbox_explainer">gdzie publikujesz</string>
|
||||
<string name="backup_review_inbox">Skrzynka odbiorcza</string>
|
||||
<string name="backup_review_inbox_explainer">gdzie inni docierają do Ciebie</string>
|
||||
<string name="backup_review_key_replaced">Wymieniono klucz odbierający</string>
|
||||
<string name="backup_review_key_removed">Usunięto klucz odbierający</string>
|
||||
<string name="backup_review_key_warning">Nutzapy zostaną przypisane do tego nowego klucza. Jeśli urządzenie nie posiada tego klucza, może się okazać, że nie będzie można ich tutaj zrealizować.</string>
|
||||
<string name="backup_review_left">zostało</string>
|
||||
<string name="backup_review_joined">dołączył(a)</string>
|
||||
<string name="backup_review_renamed">zmieniono nazwę</string>
|
||||
<string name="backup_review_was_named">było „%1$s”</string>
|
||||
<string name="backup_action_block_again">Zablokuj %1$s ponownie</string>
|
||||
<string name="backup_action_restore_feeds">Przywróć kanały</string>
|
||||
<string name="backup_action_restore_topics">Przywróć tematy</string>
|
||||
<string name="backup_action_restore_places">Przywróć miejsca</string>
|
||||
<string name="backup_action_restore_providers">Przywróć dostawców</string>
|
||||
<string name="backup_action_restore_wallet">Przywróć portfel</string>
|
||||
<string name="backup_review_kept">zachowane</string>
|
||||
<string name="backup_review_receiving_tag">Pobieranie</string>
|
||||
<string name="backup_review_listed_tag">Na Liście</string>
|
||||
<string name="backup_review_searching_tag">Szukam</string>
|
||||
<string name="backup_review_storing_tag">Przechowywanie</string>
|
||||
<string name="backup_review_trusted_tag">Zaufane</string>
|
||||
<string name="backup_review_untrusted_tag">Niezaufane</string>
|
||||
<string name="backup_review_unblocked">%1$s odblokowane</string>
|
||||
<string name="backup_review_unblocked_explainer">Ametyst ponownie połączy się z nimi</string>
|
||||
<string name="backup_review_no_longer_blocked">Nie jest już zablokowana</string>
|
||||
<string name="backup_review_newly_blocked">Nowo zablokowana</string>
|
||||
<string name="backup_review_still_blocked">Nadal zablokowana</string>
|
||||
<string name="backup_review_allowed_tag">Dozwolona</string>
|
||||
<string name="backup_review_moved_tag">Przeniesiona</string>
|
||||
<string name="backup_review_feed">Kanał</string>
|
||||
<string name="backup_review_topics_gone">tematy zniknęły</string>
|
||||
<string name="backup_review_places_gone"> miejsca zniknęły</string>
|
||||
<string name="backup_review_new_count_caption">nowe</string>
|
||||
<string name="backup_review_hashtags_you_follow">Hashtagi, które obserwujesz</string>
|
||||
<string name="backup_review_places_you_follow">Miejsca które obserwujesz</string>
|
||||
<string name="backup_review_services_changed">Zmieniono %1$s z %2$s serwisów</string>
|
||||
<string name="backup_review_services_changed_explainer">Teraz pochodzą od kogoś innego albo od nikogo</string>
|
||||
<string name="backup_review_service">Serwis</string>
|
||||
<string name="backup_review_service_rank">Ranking</string>
|
||||
<string name="backup_review_service_followers">Obserwujący</string>
|
||||
<string name="backup_review_service_topics">Tematy</string>
|
||||
<string name="backup_review_trust_warning">Rankingi, liczba obserwujących i filtrowanie spamu, które widzisz, pochodzą od tych dostawców.</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">%1$d sposób płatności został usunięty</item>
|
||||
<item quantity="few">%1$d sposobów płatności zostało usuniętych</item>
|
||||
<item quantity="many">%1$d sposobów płatności zostało usuniętych</item>
|
||||
<item quantity="other">%1$d sposoby płatności zostały usunięte</item>
|
||||
</plurals>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d oferta usunięta</item>
|
||||
<item quantity="few">%1$d ofert usunięto</item>
|
||||
<item quantity="many">%1$d ofert usunięto</item>
|
||||
<item quantity="other">%1$d oferty usunięte</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">Osoby, które Ci płacą, widzą tylko to, co znajduje się na tej liście.</string>
|
||||
<string name="backup_review_offer">Oferta BOLT12</string>
|
||||
<string name="backup_review_encrypted_cleared">Opróżniłeś to</string>
|
||||
<string name="backup_review_encrypted_added">Utworzyłeś to</string>
|
||||
<string name="backup_review_encrypted_changed">Zmieniłeś to</string>
|
||||
<string name="backup_review_wallet_body">Minty i klucze w Twoim portfelu są zaszyfrowane dla Ciebie, więc nie można ich tutaj porównać pozycja po pozycji. Przywrócenie danych powoduje przywrócenie dokładnie tego, co zostało zapisane na tym urządzeniu.</string>
|
||||
<string name="backup_review_concord_body">Twoje społeczności w Concord są dla Ciebie zaszyfrowane, więc nie można ich tutaj porównać. Przywrócenie danych powoduje przywrócenie dokładnie tego, co zostało zapisane na tym urządzeniu.</string>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">Włączyłeś dźwięk dla %1$d elementu</item>
|
||||
<item quantity="few">Włączyłeś dźwięk dla %1$d elementów</item>
|
||||
<item quantity="many">Włączyłeś dźwięk dla %1$d elementów</item>
|
||||
<item quantity="other">%1$d elementy mają włączony dźwięk</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">Usunąłeś %1$d pole profilu</item>
|
||||
<item quantity="few">Usunąłeś %1$d pól profilowych</item>
|
||||
<item quantity="many">Usunąłeś %1$d pól profilowych</item>
|
||||
<item quantity="other">Usunąłeś %1$d pola profilowe</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">Usunąłeś %1$d publiczny transmiter</item>
|
||||
<item quantity="few">Usunąłeś %1$d publicznych transmiterów</item>
|
||||
<item quantity="many">Usunąłeś %1$d publicznych transmiterów</item>
|
||||
<item quantity="other">Usunąłeś %1$d publiczne transmitery</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">Usunąłeś %1$d transmiter DM</item>
|
||||
<item quantity="few">Usunąłeś %1$d transmiterów DM</item>
|
||||
<item quantity="many">Usunąłeś %1$d transmiterów DM</item>
|
||||
<item quantity="other">Usunąłeś %1$d transmitery DM</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">Usunięto %1$d transmiter klucza grupowego czatu</item>
|
||||
<item quantity="few">Usunięto %1$d transmiterów klucza grupowego czatu</item>
|
||||
<item quantity="many">Usunięto %1$d transmiterów klucza grupowego czatu</item>
|
||||
<item quantity="other">Usunięto %1$d transmitery klucza grupowego czatu</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">Usunięto %1$d transmiter wyszukiwania</item>
|
||||
<item quantity="few">Usunięto %1$d transmiterów wyszukiwania</item>
|
||||
<item quantity="many">Usunięto %1$d transmiterów wyszukiwania</item>
|
||||
<item quantity="other">Usunięto %1$d transmitery wyszukiwania</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">Usunięto %1$d transmiter indeksujący</item>
|
||||
<item quantity="few">Usunięto %1$d transmiterów indeksujących</item>
|
||||
<item quantity="many">Usunięto %1$d transmiterów indeksujących</item>
|
||||
<item quantity="other">Usunięto %1$d transmitery indeksujące</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">Usunięto %1$d kanał transmitera</item>
|
||||
<item quantity="few">Usunięto %1$d kanałów transmitera</item>
|
||||
<item quantity="many">Usunięto %1$d kanałów transmitera</item>
|
||||
<item quantity="other">Usunięto %1$d kanały transmitera</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">Usunięto %1$d prywatny transmiter</item>
|
||||
<item quantity="few">Usunięto %1$d prywatnych transmiterów</item>
|
||||
<item quantity="many">Usunięto %1$d prywatnych transmiterów</item>
|
||||
<item quantity="other">Usunięto %1$d prywatne transmitery</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">Przestałeś ufać %1$d transmiterowi</item>
|
||||
<item quantity="few">Przestałeś ufać %1$d transmiterom</item>
|
||||
<item quantity="many">Przestałeś ufać %1$d transmiterom</item>
|
||||
<item quantity="other">Przestałeś ufać %1$d transmiterom</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">Odblokowałeś %1$d transmiter</item>
|
||||
<item quantity="few">Odblokowałeś %1$d transmiterów</item>
|
||||
<item quantity="many">Odblokowałeś %1$d transmiterów</item>
|
||||
<item quantity="other">Odblokowałeś %1$d transmitery</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">Opuściłeś %1$d czat publiczny</item>
|
||||
<item quantity="few">Opuściłeś %1$d czatów publicznych</item>
|
||||
<item quantity="many">Opuściłeś %1$d czatów publicznych</item>
|
||||
<item quantity="other">Opuściłeś %1$d czaty publiczne</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">Opuściłeś %1$d społeczność</item>
|
||||
<item quantity="few">Opuściłeś %1$d społeczności</item>
|
||||
<item quantity="many">Opuściłeś %1$d społeczności</item>
|
||||
<item quantity="other">Opuściłeś %1$d społeczności</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">Opuściłeś %1$d pokój czatu</item>
|
||||
<item quantity="few">Opuściłeś %1$d pokoi czatu</item>
|
||||
<item quantity="many">Opuściłeś %1$d pokoi czatu</item>
|
||||
<item quantity="other">Opuściłeś %1$d pokoje czatu</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">Opuściłeś %1$d grupę</item>
|
||||
<item quantity="few">Opuściłeś %1$d grup</item>
|
||||
<item quantity="many">Opuściłeś %1$d grup</item>
|
||||
<item quantity="other">Opuszczono %1$d grupy</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">Usunąłeś %1$d ulubiony kanał</item>
|
||||
<item quantity="few">Usunąłeś %1$d ulubionych kanałów</item>
|
||||
<item quantity="many">Usunąłeś %1$d ulubionych kanałów</item>
|
||||
<item quantity="other">Usunięto %1$d ulubione kanały</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">Przestałeś obserwować %1$d hashtag</item>
|
||||
<item quantity="few">Przestałeś obserwować %1$d hashtagów</item>
|
||||
<item quantity="many">Przestałeś obserwować %1$d hashtagów</item>
|
||||
<item quantity="other">Przestałeś obserwować %1$d hashtagi</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">Przestałeś obserwować %1$d miejsce</item>
|
||||
<item quantity="few">Przestałeś obserwować %1$d miejsc</item>
|
||||
<item quantity="many">Przestałeś obserwować %1$d miejsc</item>
|
||||
<item quantity="other">Przestałeś obserwować %1$d miejsca</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">Zmieniłeś dostawcę %1$d zaufanego serwisu</item>
|
||||
<item quantity="few">Zmieniłeś dostawcę %1$d zaufanych serwisów</item>
|
||||
<item quantity="many">Zmieniłeś dostawcę %1$d zaufanych serwisów</item>
|
||||
<item quantity="other">Zmieniłeś dostawcę %1$d zaufanych serwisów</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">Usunięto %1$d nutzap mint</item>
|
||||
<item quantity="few">Usunięto %1$d nutzap mintów</item>
|
||||
<item quantity="many">Usunięto %1$d nutzap mintów</item>
|
||||
<item quantity="other">Usunięto %1$d nutzap minty</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">Usunięto %1$d sposób na otrzymanie zapłaty</item>
|
||||
<item quantity="few">Usunięto %1$d sposobów otrzymywania zapłaty</item>
|
||||
<item quantity="many">Usunięto %1$d sposobów otrzymywania zapłaty</item>
|
||||
<item quantity="other">Usunięto %1$d sposoby otrzymywania zapłaty</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">Usunięto %1$d ofertę BOLT12</item>
|
||||
<item quantity="few">Usunięto %1$d ofert BOLT12</item>
|
||||
<item quantity="many">Usunięto %1$d ofert BOLT12</item>
|
||||
<item quantity="other">Usunięto %1$d oferty BOLT12</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s i dodano %2$d</item>
|
||||
<item quantity="few">%1$s i dodano %2$d</item>
|
||||
<item quantity="many">%1$s i dodano %2$d</item>
|
||||
<item quantity="other">%1$s i dodano %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s i obserwowany %2$d</item>
|
||||
<item quantity="few">%1$s i obserwowanych %2$d</item>
|
||||
<item quantity="many">%1$s i obserwowanych %2$d</item>
|
||||
<item quantity="other">%1$s i obserwowane %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s i wyciszony %2$d</item>
|
||||
<item quantity="few">%1$s i wyciszono %2$d</item>
|
||||
<item quantity="many">%1$s i wyciszono %2$d</item>
|
||||
<item quantity="other">%1$s i wyciszone %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s i dołączono do %2$d</item>
|
||||
<item quantity="few">%1$s i dołączono do %2$d</item>
|
||||
<item quantity="many">%1$s i dołączono do %2$d</item>
|
||||
<item quantity="other">%1$s i dołączono do %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s i zablokowano %2$d</item>
|
||||
<item quantity="few">%1$s i zablokowano %2$d</item>
|
||||
<item quantity="many">%1$s i zablokowano %2$d</item>
|
||||
<item quantity="other">%1$s i zablokowano %2$d</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">Twoje zsynchronizowane ustawienia aplikacji Amethyst zostały zmienione w innej aplikacji, która nie jest Amethystem. To może powodować problemy.</string>
|
||||
<string name="backup_card_nutzap_key_replaced">Wymieniłeś swój klucz Nutzap</string>
|
||||
<string name="backup_card_nutzap_key_removed">Usunąłeś swój klucz nutzap</string>
|
||||
<string name="backup_card_wallet_emptied">Opróżniłeś swój portfel Cashu</string>
|
||||
<string name="backup_card_wallet_rewritten">Zmieniłeś swój portfel Cashu</string>
|
||||
<string name="backup_card_concord_emptied">Opróżniłeś swoją listę Concorda</string>
|
||||
<string name="backup_card_concord_rewritten">Zmieniłeś swoją listę Concorda</string>
|
||||
<string name="backup_conflict_keep_new">Użyj nowej wersji</string>
|
||||
<string name="backup_conflict_relay_read_only">tylko do odczytu</string>
|
||||
<string name="backup_conflict_relay_write_only">tylko do zapisu</string>
|
||||
<string name="backup_conflict_relay_read_write">odczyt i zapis</string>
|
||||
<string name="backup_type_profile">profil</string>
|
||||
<string name="backup_type_profile_explainer">Twoje imię i nazwisko, zdjęcie, biografia oraz adresy do płatności – tak, jak widzą je wszyscy.</string>
|
||||
<string name="backup_type_follow_list">lista obserwowanych</string>
|
||||
<string name="backup_type_follow_list_explainer">Określa, czyje posty pojawiają się w Twoim kanale głównym.</string>
|
||||
<string name="backup_type_mute_list">lista zablokowanych</string>
|
||||
<string name="backup_type_mute_list_explainer">Ukrywa osoby, słowa, hashtagi i wątki we wszystkich wyświetlanych treściach.</string>
|
||||
<string name="backup_type_outbox_inbox_relays">lista publicznych transmiterów</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">Informuje wszystkich, gdzie mogą znaleźć Twoje posty oraz gdzie mają wysyłać Ci odpowiedzi i wzmianki.</string>
|
||||
<string name="backup_type_dm_relays">Lista transmiterów DM</string>
|
||||
<string name="backup_type_dm_relays_explainer">Gdzie inni dostarczają Twoje prywatne wiadomości.</string>
|
||||
<string name="backup_type_key_package_relays">transmitery kluczy czatu grupowego</string>
|
||||
<string name="backup_type_key_package_relays_explainer">Gdzie inni znajdą klucze do dodawania cię do zaszyfrowanych czatów grupowych.</string>
|
||||
<string name="backup_type_search_relays">lista transmiterów wyszukiwania</string>
|
||||
<string name="backup_type_search_relays_explainer">Transmitery używane podczas wyszukiwania.</string>
|
||||
<string name="backup_type_indexer_relays">lista transmiterów indeksujących</string>
|
||||
<string name="backup_type_indexer_relays_explainer">Transmitery służące do wyszukiwania profili innych osób oraz list transmiterów.</string>
|
||||
<string name="backup_type_relay_feeds">ulubione kanały transmitera</string>
|
||||
<string name="backup_type_relay_feeds_explainer">Transmitery, które przeglądasz jako kanały informacyjne.</string>
|
||||
<string name="backup_type_blocked_relays">lista zablokowanych przekaźników</string>
|
||||
<string name="backup_type_blocked_relays_explainer">Transmitery, z którymi ta aplikacja nigdy się nie łączy.</string>
|
||||
<string name="backup_type_trusted_relays">lista zaufanych transmiterów</string>
|
||||
<string name="backup_type_trusted_relays_explainer">Zaufane transmitery, z którymi bez wahania nawiązujesz połączenie.</string>
|
||||
<string name="backup_type_private_outbox_relays">lista prywatnych transmiterów</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">Gdzie przechowywane są Twoje projekty i prywatne dane.</string>
|
||||
<string name="backup_type_app_settings">zsynchronizowane ustawienia aplikacji</string>
|
||||
<string name="backup_type_app_settings_explainer">Ustawienia Amethyst są synchronizowane na wszystkich Twoich urządzeniach. Są one zaszyfrowane, więc można porównać jedynie sam fakt ich obecności.</string>
|
||||
<string name="backup_type_public_chats">lista czatów publicznych</string>
|
||||
<string name="backup_type_public_chats_explainer">Publiczne czaty, do których dołączyłeś.</string>
|
||||
<string name="backup_type_communities">lista społeczności</string>
|
||||
<string name="backup_type_communities_explainer">Społeczności, do których dołączyłeś.</string>
|
||||
<string name="backup_type_hashtags">obserwowane hashtagi</string>
|
||||
<string name="backup_type_hashtags_explainer">Hashtagi, z których pochodzą posty wyświetlane w Twoich kanałach.</string>
|
||||
<string name="backup_type_geohashes">obserwowane lokalizacje</string>
|
||||
<string name="backup_type_geohashes_explainer">Miejsca, z których posty pojawiają się na Twoich kanałach.</string>
|
||||
<string name="backup_type_favorite_algo_feeds">lista ulubionych kanałów</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">Zapisane przez Ciebie kanały algorytmiczne.</string>
|
||||
<string name="backup_type_ephemeral_chats">lista czatów efemerycznych</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">Tymczasowe czaty, do których dołączyłeś.</string>
|
||||
<string name="backup_type_relay_groups">lista grup</string>
|
||||
<string name="backup_type_relay_groups_explainer">Grupy oparte na transmiterach, do których dołączyłeś.</string>
|
||||
<string name="backup_type_concord_communities">Lista społeczności Concord</string>
|
||||
<string name="backup_type_concord_communities_explainer">Społeczności Concord, do których dołączyłeś. Są one zaszyfrowane, więc można porównać jedynie fakt ich istnienia.</string>
|
||||
<string name="backup_type_trust_providers">lista zaufanych dostawców</string>
|
||||
<string name="backup_type_trust_providers_explainer">Serwisy, którym ufasz, a które zajmują się klasyfikowaniem i weryfikacją osób w Twoim imieniu.</string>
|
||||
<string name="backup_type_cashu_wallet">Portfel Cashu</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">Ustawienia portfela ecash oraz minty. Są one zaszyfrowane, więc można porównać jedynie sam fakt ich istnienia.</string>
|
||||
<string name="backup_type_nutzap_info">ustawienia odbioru nutzap</string>
|
||||
<string name="backup_type_nutzap_info_explainer">Minty i klucz, które inni używają do wysyłania ci „nutzapów”.</string>
|
||||
<string name="backup_type_payment_targets">adresy płatności</string>
|
||||
<string name="backup_type_payment_targets_explainer">Sposoby, w jakie inni mogą Ci zapłacić.</string>
|
||||
<string name="backup_type_bolt12_offers">Oferta BOLT12</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">Ta możliwość pozwala innym płacić Ci za pomocą Lightning.</string>
|
||||
<string name="backup_type_other">lista</string>
|
||||
<string name="backup_type_other_explainer">Lista zapisana na tym urządzeniu.</string>
|
||||
<string name="backup_entry_profile_field">Pola profilu</string>
|
||||
<string name="backup_entry_person">Osoby</string>
|
||||
<string name="backup_entry_hashtag">Hashtagi</string>
|
||||
<string name="backup_entry_word">Słowa</string>
|
||||
<string name="backup_entry_thread">Wątki</string>
|
||||
<string name="backup_entry_public_chat">Czaty publiczne</string>
|
||||
<string name="backup_entry_community">Społeczności</string>
|
||||
<string name="backup_entry_algo_feed">Kanały</string>
|
||||
<string name="backup_entry_location">Lokalizacje</string>
|
||||
<string name="backup_entry_relay">Transmitery</string>
|
||||
<string name="backup_entry_relay_group">Grupy</string>
|
||||
<string name="backup_entry_chat_room">Czat pokoje</string>
|
||||
<string name="backup_entry_trust_provider">Zaufani dostawcy</string>
|
||||
<string name="backup_entry_mint">Minty</string>
|
||||
<string name="backup_entry_nutzap_key">Klucze Nutzap</string>
|
||||
<string name="backup_entry_payment_target">Adresy płatności</string>
|
||||
<string name="backup_entry_offer">Oferty</string>
|
||||
<string name="backup_entry_identity_claim">Powiązane tożsamości</string>
|
||||
<string name="backup_entry_other">Inne wpisy</string>
|
||||
<string name="backup_profile_field_name">Nazwa użytkownika</string>
|
||||
<string name="backup_profile_field_display_name">Nazwa wyświetlana</string>
|
||||
<string name="backup_profile_field_about">O profilu</string>
|
||||
<string name="backup_profile_field_picture">Zdjęcie</string>
|
||||
<string name="backup_profile_field_banner">Baner</string>
|
||||
<string name="backup_profile_field_website">Strona www</string>
|
||||
<string name="backup_profile_field_nip05">Adres Nostr</string>
|
||||
<string name="backup_profile_field_lud16">Lightning Adres</string>
|
||||
<string name="backup_profile_field_lud06">LNURL</string>
|
||||
<string name="backup_profile_field_pronouns">Zaimki</string>
|
||||
<string name="backup_profile_field_birthday">Data urodzin</string>
|
||||
<string name="backup_profile_field_clink_offer">Oferta CLINK</string>
|
||||
<string name="backup_profile_field_bot">Flaga bota</string>
|
||||
</resources>
|
||||
|
||||
@@ -305,250 +305,6 @@
|
||||
|
||||
|
||||
|
||||
<string name="cordn_groups_manage">Coordinators</string>
|
||||
<string name="cordn_groups_down_note">Nothing is arriving from these groups. Amethyst keeps retrying.</string>
|
||||
<string name="cordn_groups_none">No cordn groups yet</string>
|
||||
<string name="cordn_groups_none_detail">A cordn group lives on one coordinator that holds its membership and passes messages along, without ever seeing what anyone writes.</string>
|
||||
<string name="cordn_groups_start">Start one</string>
|
||||
<string name="cordn_group_unavailable">This group is not available. Its coordinator may have been removed.</string>
|
||||
<string name="cordn_group_info">Group info</string>
|
||||
<string name="cordn_message_deleted">Message deleted</string>
|
||||
<string name="cordn_message_edited">edited</string>
|
||||
<string name="cordn_action_go_to_message">Go to message</string>
|
||||
<string name="cordn_delete_confirm_title">Withdraw message</string>
|
||||
<string name="cordn_delete_confirm_body">Everyone in the group will see this message as withdrawn, and Amethyst will stop showing its text. The coordinator still holds the encrypted copy it was sent as, and anyone who already read it has already read it.</string>
|
||||
<string name="cordn_delivery_accepted">Accepted by the coordinator</string>
|
||||
<string name="cordn_message_details_title">Message details</string>
|
||||
<string name="cordn_message_details_sent_at">Sent</string>
|
||||
<string name="cordn_message_details_cursor">Cursor</string>
|
||||
<string name="cordn_message_details_coordinator">Coordinator</string>
|
||||
<string name="cordn_composer_hint">Message</string>
|
||||
<string name="cordn_action_reply">Reply</string>
|
||||
<string name="cordn_action_edit">Edit</string>
|
||||
<string name="cordn_action_delete">Delete</string>
|
||||
<string name="cordn_action_pin">Pin</string>
|
||||
<string name="cordn_pinned_previous">Previous pinned message</string>
|
||||
<string name="cordn_pinned_next">Next pinned message</string>
|
||||
<string name="cordn_pinned_show_all">Show all pinned messages</string>
|
||||
<string name="cordn_pinned_title">Pinned messages</string>
|
||||
<string name="cordn_pinned_by">Pinned by %1$s</string>
|
||||
<plurals name="cordn_pinned_count">
|
||||
<item quantity="one">%1$d pinned message in this group</item>
|
||||
<item quantity="other">%1$d pinned messages in this group</item>
|
||||
</plurals>
|
||||
<string name="cordn_action_unpin">Unpin</string>
|
||||
<string name="cordn_action_editing">Editing your message</string>
|
||||
<string name="cordn_media_upload_failed">Could not send that file.</string>
|
||||
<string name="cordn_send_failed">That did not send.</string>
|
||||
<string name="cordn_send_no_session">This group\'s coordinator is not open, so nothing can be sent yet.</string>
|
||||
<string name="cordn_media_download_failed">Could not open that file.</string>
|
||||
<string name="cordn_media_no_server">No media server is set for this account, so there is nowhere to put the file. Pick one in Settings.</string>
|
||||
<string name="cordn_media_unreadable">That file could not be read.</string>
|
||||
<string name="cordn_voice_record">Record a voice note</string>
|
||||
<string name="cordn_voice_stop">Stop and send</string>
|
||||
<string name="cordn_voice_play">Play voice note</string>
|
||||
<string name="cordn_backup_explainer">Your nsec cannot bring cordn groups back. A cordn group lives as encryption state on this device and an ordered stream on a coordinator that cannot read it — lose the device without a backup and the group is gone, including everything already said in it.</string>
|
||||
<string name="cordn_backup_passphrase">Passphrase</string>
|
||||
<string name="cordn_backup_contents_title">What is in the file</string>
|
||||
<string name="cordn_backup_contents_body">Your group encryption keys, your key packages, and every message in those groups. Anyone who opens it can read the conversations. The passphrase is the only thing protecting it once it leaves Amethyst.</string>
|
||||
<string name="cordn_backup_export">Export</string>
|
||||
<string name="cordn_backup_exported">Backup saved.</string>
|
||||
<string name="cordn_backup_restore_title">Restore</string>
|
||||
<string name="cordn_backup_restore_body">Restoring replaces the cordn groups on this device with the ones in the file. It is for a phone that has taken over from another — not a way to use the same groups on two devices at once.</string>
|
||||
<string name="cordn_backup_restore">Restore</string>
|
||||
<string name="cordn_backup_restore_confirm_title">Replace this device\'s cordn groups?</string>
|
||||
<string name="cordn_backup_restore_confirm_body">Every cordn group now on this device will be removed and replaced by the ones in the file.\n\nDo not restore onto a second phone while the first is still in use. Both would hold the same group keys, and once both have sent a message the group breaks for everyone — silently, and with no way back.</string>
|
||||
<string name="cordn_backup_restored">Restored.</string>
|
||||
<string name="cordn_backup_failed">That did not work. Check the passphrase and the file.</string>
|
||||
<string name="cordn_send">Send</string>
|
||||
<string name="cordn_info_coordinator">Coordinator</string>
|
||||
<string name="cordn_info_coordinator_key">Coordinator key</string>
|
||||
<string name="cordn_info_coordinator_nprofile">Coordinator link</string>
|
||||
<string name="cordn_info_copy_nprofile">Copy the coordinator\'s nprofile</string>
|
||||
<string name="cordn_info_gid">Group id</string>
|
||||
<string name="cordn_info_epoch">Epoch</string>
|
||||
<string name="cordn_info_members">Members</string>
|
||||
<string name="cordn_info_egalitarian">This group has no admins: everyone can add, remove and rename, permanently.</string>
|
||||
<string name="cordn_info_technical">Technical details</string>
|
||||
<string name="cordn_create_title">New Cordn group</string>
|
||||
<string name="cordn_create_explainer">A cordn group is ordered by one coordinator you choose. Creating the group happens on this device — the coordinator only learns the group exists once you invite someone or send a message.</string>
|
||||
<string name="cordn_create_people_none">Nobody yet — tap to add people</string>
|
||||
<string name="cordn_create_people_empty">Nobody added yet. A group can be created empty and invitations sent later, but naming people now is what shows which coordinator can reach them.</string>
|
||||
<string name="cordn_create_people_done">Done</string>
|
||||
<string name="cordn_create_you">You, always an admin</string>
|
||||
<string name="cordn_create_step_name">Name it</string>
|
||||
<string name="cordn_create_step_people">Who is in it</string>
|
||||
<string name="cordn_create_step_where">Where it lives</string>
|
||||
<string name="cordn_create_step_admins">Who can add and remove</string>
|
||||
<string name="cordn_create_add_member">Add someone</string>
|
||||
<string name="cordn_create_people_note">Naming people now is what tells us which coordinator can reach them. Each one gets a Welcome left on that coordinator, which they pick up next time they open their app.</string>
|
||||
<string name="cordn_create_reach_unknown">Not checked yet</string>
|
||||
<string name="cordn_create_reach_none">No key on any coordinator you use</string>
|
||||
<string name="cordn_create_egalitarian">Everyone can add and remove</string>
|
||||
<string name="cordn_create_admin">Admin</string>
|
||||
<string name="cordn_create_no_coordinator">No coordinator chosen</string>
|
||||
<string name="cordn_create_coordinator_change">Change</string>
|
||||
<string name="cordn_create_coordinator_hide">Done</string>
|
||||
<string name="cordn_create_coverage_unknown">Not checked — picking it will ask</string>
|
||||
<string name="cordn_create_coverage_all">Reaches all %1$d of your people</string>
|
||||
<string name="cordn_create_coverage_partial">Reaches %1$d of %2$d — the rest would be left out</string>
|
||||
<string name="cordn_create_outcome_title">The group exists</string>
|
||||
<string name="cordn_create_outcome_explainer">Each invitation is a Welcome left on the coordinator, so they can fail one at a time. Nobody has been notified: they see it next time they open their app.</string>
|
||||
<string name="cordn_create_outcome_no_welcome">Added to the group, but the invitation did not reach them — try again from the group screen</string>
|
||||
<string name="cordn_create_outcome_waiting">Waiting for them</string>
|
||||
<string name="cordn_create_outcome_failed">The coordinator refused the invitation</string>
|
||||
<string name="cordn_create_outcome_skipped">No key here, so no Welcome could be left</string>
|
||||
<string name="cordn_create_outcome_link">Send a link</string>
|
||||
<string name="cordn_create_outcome_open">Open the chat</string>
|
||||
<string name="cordn_create_coordinator">Coordinator</string>
|
||||
<string name="cordn_create_coordinator_discover">Find coordinators</string>
|
||||
<string name="cordn_create_coordinator_new">Another coordinator</string>
|
||||
<string name="cordn_create_coordinator_pubkey">Coordinator public key (hex or npub)</string>
|
||||
<string name="cordn_create_coordinator_relays">Relays it answers on, one per line</string>
|
||||
<string name="cordn_create_name">Group name</string>
|
||||
<string name="cordn_create_description">Description (optional)</string>
|
||||
<string name="cordn_create_egalitarian_note">Everyone in the group can invite, remove members and change its details. Any member can name admins later, which ends that.</string>
|
||||
<string name="cordn_create_admin_only_me">Only I manage this group</string>
|
||||
<string name="cordn_admin_action_failed">That change could not be made.</string>
|
||||
<string name="cordn_info_remove_member">Remove</string>
|
||||
<string name="cordn_info_remove_confirm_title">Remove from group?</string>
|
||||
<string name="cordn_info_remove_confirm_body">%1$s stops receiving messages from here. They keep what they have already read, and this cannot be undone — they would have to be invited again.</string>
|
||||
<string name="cordn_info_edit_details">Edit details</string>
|
||||
<string name="cordn_info_save">Save</string>
|
||||
<string name="cordn_create_admin_only_me_on">Only you can invite, remove members or change the group\'s details. You can hand that to someone else later.</string>
|
||||
<string name="cordn_create_action">Create group</string>
|
||||
<string name="cordn_create_failed">The group could not be created.</string>
|
||||
<string name="cordn_invitations_title">Cordn invitations</string>
|
||||
<string name="cordn_invitations_explainer">Checked when you open this screen, and at no other time — asking a coordinator whether anyone invited you tells it you are here, so Amethyst does not do it in the background.</string>
|
||||
<string name="cordn_invitations_refresh">Check again</string>
|
||||
<string name="cordn_invitations_accept">Join</string>
|
||||
<string name="cordn_invitations_decline">Decline</string>
|
||||
<string name="cordn_invitations_decline_warning">Declining is permanent. Getting back in means being invited again.</string>
|
||||
<string name="cordn_chat_yesterday">Yesterday</string>
|
||||
<string name="cordn_chat_unread_divider">New messages</string>
|
||||
<string name="cordn_chat_empty_title">No messages yet</string>
|
||||
<string name="cordn_chat_empty_description">Anything sent here is encrypted for this group. The coordinator relays it without being able to read it.</string>
|
||||
<string name="cordn_reactions_title">Reactions</string>
|
||||
<string name="cordn_group_unavailable_detail">Add a coordinator in Settings to start using cordn groups.</string>
|
||||
<string name="cordn_coordinators_discover_explainer">Reads announcements your relays already carry. No coordinator is contacted, so none of them learns you looked.</string>
|
||||
<string name="cordn_coordinators_discover_action">Look for coordinators</string>
|
||||
<string name="cordn_coordinators_discover_add">Add</string>
|
||||
<string name="cordn_coordinators_discover_failed">Could not read announcements</string>
|
||||
<string name="cordn_coordinators_discover_none">Nobody is announcing on your relays.</string>
|
||||
<string name="cordn_coordinators_discover_unheard">Nothing found, and %1$d of your relays did not answer.</string>
|
||||
<string name="cordn_coordinators_discover_seen">Announced %1$s ago</string>
|
||||
<string name="cordn_coordinators_discover_seen_on">Last announced %1$s</string>
|
||||
<string name="cordn_coordinators_relays">%1$s</string>
|
||||
<string name="cordn_coordinators_relays_more">%1$s +%2$d more</string>
|
||||
<string name="cordn_coordinators_show_all">Show all %1$d</string>
|
||||
<string name="cordn_coordinators_show_fewer">Show fewer</string>
|
||||
<string name="cordn_coordinators_show_older">Show %1$d that stopped announcing</string>
|
||||
<string name="cordn_coordinators_hide_older">Hide the ones that stopped announcing</string>
|
||||
<string name="cordn_coordinators_stale_note">These have not announced in over a month. Creating a group on one that has gone away will fail.</string>
|
||||
<string name="cordn_info_add_member">Add someone</string>
|
||||
<string name="cordn_info_add_member_placeholder">Name, npub or name@domain</string>
|
||||
<string name="cordn_info_has_key_package">Can be added on this coordinator</string>
|
||||
<string name="cordn_info_add_member_note">They can only be added if they published a key package to this coordinator.</string>
|
||||
<string name="cordn_exposure_open">What this coordinator can see</string>
|
||||
<string name="cordn_exposure_close">Got it</string>
|
||||
<string name="cordn_admin_someone">That person</string>
|
||||
<string name="cordn_admin_no_key_package">%1$s has not published a key package to this coordinator, so they cannot be added yet. Ask them to open cordn on this coordinator first.</string>
|
||||
<string name="cordn_admin_wrong_key_package">This coordinator served a key package that belongs to someone else, so %1$s was not added. Nothing was changed.</string>
|
||||
<string name="cordn_admin_no_welcome">%1$s could not be given a way into the group, so the add was abandoned.</string>
|
||||
<string name="cordn_admin_not_a_member">%1$s is not in this group.</string>
|
||||
<string name="cordn_admin_no_self_remove">You cannot remove yourself from a cordn group.</string>
|
||||
<string name="cordn_admin_coordinator_silent">The coordinator did not answer, so nothing was changed. Try again in a moment.</string>
|
||||
<string name="cordn_info_add_member_none">Nobody found by that name.</string>
|
||||
<string name="cordn_info_admin_badge">Admin</string>
|
||||
<string name="cordn_invitations_members_more">+%1$d more</string>
|
||||
<string name="cordn_invitations_via">Through %1$s</string>
|
||||
<string name="cordn_invitations_none">No invitations waiting.</string>
|
||||
<string name="cordn_invitations_no_coordinators">You have no coordinator open. cordn invitations arrive through a coordinator, so there is nowhere to look yet.</string>
|
||||
<string name="cordn_invitations_unreachable">%1$s did not answer</string>
|
||||
<string name="cordn_invitations_skipped">An invitation was left for another device</string>
|
||||
<string name="cordn_invitations_load_failed">Could not read invitations.</string>
|
||||
<string name="cordn_link_request">Ask to join this group</string>
|
||||
<string name="cordn_link_request_disclosure">This publishes a key package under your own account key and tells the coordinator you want into this group — whether or not anyone answers.</string>
|
||||
<string name="cordn_link_request_sent">Asked. A member of the group has to add you; the invitation will show up under cordn invitations.</string>
|
||||
<string name="cordn_link_request_failed">Could not ask to join.</string>
|
||||
<string name="cordn_requests_title">Requests to join</string>
|
||||
<string name="cordn_requests_check">Check for requests</string>
|
||||
<string name="cordn_requests_none">Nobody is waiting to join.</string>
|
||||
<string name="cordn_requests_accept">Add</string>
|
||||
<string name="cordn_requests_decline">Dismiss</string>
|
||||
<string name="cordn_requests_admin_only">Only an admin can accept. In a group with no admins, that is everyone.</string>
|
||||
<string name="cordn_requests_failed">Could not read the requests.</string>
|
||||
<string name="cordn_link_scan">Scan</string>
|
||||
<string name="cordn_share_title">Share this group</string>
|
||||
<string name="cordn_share_explainer">Anyone with this link can ask to join. An admin still has to let them in.</string>
|
||||
<string name="cordn_share_copy">Copy link</string>
|
||||
<string name="cordn_share_copied">Copied</string>
|
||||
<string name="cordn_coordinators_explainer">A coordinator orders one group\'s messages and is the only thing that can. Losing it loses the ordering, and a second one does not mirror the first — so these are named things you choose, not interchangeable relays.</string>
|
||||
<string name="cordn_coordinators_none">No coordinators yet.</string>
|
||||
<string name="cordn_coordinators_add_action">Add</string>
|
||||
<string name="cordn_coordinators_add_failed">Could not open that coordinator.</string>
|
||||
<string name="cordn_coordinators_label">A name for it (yours, optional)</string>
|
||||
<string name="cordn_coordinators_relays_label">Answers on</string>
|
||||
<string name="cordn_coordinators_key">Coordinator key</string>
|
||||
<string name="cordn_coordinators_copy_key">Copy the coordinator\'s npub</string>
|
||||
<string name="cordn_coordinators_more">More actions</string>
|
||||
<string name="cordn_coordinators_rename">Rename</string>
|
||||
<string name="cordn_coordinators_label_note">This name is yours and stays on this device. A coordinator cannot prove a name, so it is never asked for one.</string>
|
||||
<string name="cordn_coordinators_identify">Ask who it is</string>
|
||||
<string name="cordn_coordinators_server">Says it is: %1$s</string>
|
||||
<string name="cordn_coordinators_server_silent">Answered, but named nothing.</string>
|
||||
<string name="cordn_coordinators_server_claim">A coordinator\'s name and version are strings it chose. Its public key is the only thing that identifies it.</string>
|
||||
<string name="cordn_coordinators_health_ok">Answering.</string>
|
||||
<string name="cordn_coordinators_health_retrying">A call failed; retrying.</string>
|
||||
<string name="cordn_coordinators_health_down">Not answering — %1$d calls in a row have failed. Groups on it are not syncing.</string>
|
||||
<string name="cordn_coordinators_health_unknown">Nothing asked of it yet.</string>
|
||||
<string name="cordn_coordinators_remove">Remove</string>
|
||||
<string name="cordn_coordinators_purge">Purge</string>
|
||||
<string name="cordn_coordinators_purge_title">Purge this coordinator?</string>
|
||||
<string name="cordn_coordinators_purge_body">Removing keeps the groups on this device, so adding the coordinator back brings them with it. Purging deletes them: the group keys, the read positions and your key packages all go, and those groups can only be re-entered by a fresh invitation.\n\nThe coordinator is not told and keeps whatever it already had.</string>
|
||||
<string name="cordn_keypackages_explainer">Others can only add you to a cordn group by taking a key package you published to that coordinator. cordn has no other place to keep one, so with none published nobody can invite you — and nothing tells them why.</string>
|
||||
<plurals name="cordn_create_unreachable_count">
|
||||
<item quantity="one">%1$d person cannot be reached by any coordinator you use</item>
|
||||
<item quantity="other">%1$d people cannot be reached by any coordinator you use</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_groups_count">
|
||||
<item quantity="one">%1$d group</item>
|
||||
<item quantity="other">%1$d groups</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_create_reach_count">
|
||||
<item quantity="one">Reachable on %1$d coordinator</item>
|
||||
<item quantity="other">Reachable on %1$d coordinators</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_create_admin_count">
|
||||
<item quantity="one">%1$d person can add and remove</item>
|
||||
<item quantity="other">%1$d people can add and remove</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_create_action_invite">
|
||||
<item quantity="one">Create and invite %1$d person</item>
|
||||
<item quantity="other">Create and invite %1$d people</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_member_count">
|
||||
<item quantity="one">%1$d member</item>
|
||||
<item quantity="other">%1$d members</item>
|
||||
</plurals>
|
||||
<plurals name="cordn_keypackages_summary">
|
||||
<item quantity="one">%1$d single-use package available.</item>
|
||||
<item quantity="other">%1$d single-use packages available.</item>
|
||||
</plurals>
|
||||
<string name="cordn_keypackages_last_resort_yes">A last-resort package is published, so an invitation can still be made once the single-use ones run out.</string>
|
||||
<string name="cordn_keypackages_last_resort_no">No last-resort package. Once the single-use ones run out, invitations fail.</string>
|
||||
<plurals name="cordn_keypackages_orphans">
|
||||
<item quantity="one">%1$d package this device cannot open</item>
|
||||
<item quantity="other">%1$d packages this device cannot open</item>
|
||||
</plurals>
|
||||
<string name="cordn_keypackages_orphans_body">The coordinator will hand these to anyone inviting you, but the private half is not on this device — it belongs to another install. If that install is gone, an invitation using one of these produces a welcome nobody can ever open.</string>
|
||||
<string name="cordn_keypackages_withdraw_orphans">Withdraw those</string>
|
||||
<string name="cordn_keypackages_disclosure">Publishing signs a record under your own account key. That coordinator then knows this account exists and is invitable — permanently, and whether or not anyone invites you.</string>
|
||||
<string name="cordn_keypackages_publish">Publish one</string>
|
||||
<string name="cordn_keypackages_publish_last_resort">Publish last-resort</string>
|
||||
<string name="cordn_keypackages_withdraw_all">Withdraw all</string>
|
||||
<string name="cordn_keypackages_topup_note">Once you have published here, Amethyst quietly replaces packages as they are used up. It never publishes the first one for you.</string>
|
||||
<string name="cordn_keypackages_failed">Could not read the key packages.</string>
|
||||
<!-- Buzz calls its groups channels, and a Buzz relay is one workspace rather than a directory of groups. -->
|
||||
<string name="buzz_channel_flag_forum">Forum channel</string>
|
||||
<string name="buzz_channel_flag_forum_desc">Threaded posts instead of a chat timeline. This cannot be changed later.</string>
|
||||
@@ -899,10 +655,6 @@
|
||||
|
||||
<!-- My Fitness: the signed-in user's own training summary. Android resource because
|
||||
NavBarItemDef labels are R.string ids. -->
|
||||
<plurals name="cordn_invitations_members">
|
||||
<item quantity="one">%1$d person is already in this group</item>
|
||||
<item quantity="other">%1$d people are already in this group</item>
|
||||
</plurals>
|
||||
<string name="private_message">Private Message</string>
|
||||
<string name="pow_kind_chat_message">Chat message</string>
|
||||
<string name="nest_notification_broadcasting">Nest — Live</string>
|
||||
@@ -931,326 +683,4 @@
|
||||
<string name="mute_button">Sound on. Click to mute</string>
|
||||
<string name="play">Play</string>
|
||||
<string name="pause">Pause</string>
|
||||
<string name="backup_conflict_title">You changed your %1$s in another app</string>
|
||||
<string name="backup_conflict_removed">Removed (%1$s)</string>
|
||||
<string name="backup_conflict_added">Added (%1$s)</string>
|
||||
<string name="backup_conflict_changed">Changed (%1$s)</string>
|
||||
<string name="backup_conflict_private_cleared">You removed all private (encrypted) items.</string>
|
||||
<string name="backup_conflict_private_changed">You also changed private (encrypted) items. They can\'t be compared here.</string>
|
||||
<string name="backup_conflict_private_added">You added private (encrypted) items.</string>
|
||||
<string name="backup_conflict_restore_mine">Restore saved version</string>
|
||||
<string name="backup_review_saved">On this device</string>
|
||||
<string name="backup_review_new">New version</string>
|
||||
<string name="backup_review_not_set">Not set</string>
|
||||
<string name="backup_conflict_count_removed">%1$s removed</string>
|
||||
<string name="backup_conflict_count_added">%1$s added</string>
|
||||
<string name="backup_conflict_count_changed">%1$s changed</string>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">You unfollowed %1$d person</item>
|
||||
<item quantity="other">You unfollowed %1$d people</item>
|
||||
</plurals>
|
||||
<string name="backup_card_accept">Accept</string>
|
||||
<string name="backup_review_title_updated">%1$s updated</string>
|
||||
<string name="backup_review_title_cleared">%1$s cleared</string>
|
||||
<string name="backup_review_changed_by_other_app">Changed in another app · %1$s</string>
|
||||
<string name="backup_action_keep_count">Keep %1$s</string>
|
||||
<string name="backup_action_restore_count">Restore %1$s</string>
|
||||
<string name="backup_action_remute">Re-mute %1$s</string>
|
||||
<string name="backup_action_rejoin">Rejoin %1$s</string>
|
||||
<string name="backup_action_restore_profile">Restore profile</string>
|
||||
<string name="backup_action_restore_relays">Restore relays</string>
|
||||
<string name="backup_review_kept_count">%1$s kept</string>
|
||||
<string name="backup_review_dropped_count">%1$s dropped</string>
|
||||
<string name="backup_review_new_count">%1$s new</string>
|
||||
<string name="backup_review_tab_dropped">Dropped · %1$s</string>
|
||||
<string name="backup_review_tab_new">New · %1$s</string>
|
||||
<string name="backup_review_tab_edited">Edited · %1$s</string>
|
||||
<string name="backup_review_search_people">Search %1$s people</string>
|
||||
<string name="backup_review_nothing_here">Nothing here</string>
|
||||
<string name="backup_review_unmuted">%1$s unmuted</string>
|
||||
<string name="backup_review_unmuted_explainer">These can reach your feeds again</string>
|
||||
<string name="backup_review_newly_muted">%1$s newly muted</string>
|
||||
<string name="backup_review_words_and_hashtags">Words & hashtags</string>
|
||||
<string name="backup_review_names_and_more">%1$s and %2$s more</string>
|
||||
<string name="backup_review_private_wiped_title">You removed all private items</string>
|
||||
<string name="backup_review_private_wiped_body">They\'re encrypted, so only you can see what they were. Restoring brings them all back.</string>
|
||||
<string name="backup_review_private_added_title">You made items private</string>
|
||||
<string name="backup_review_private_added_body">They\'re encrypted now, which is likely where the public items above went.</string>
|
||||
<string name="backup_review_private_changed_title">You changed private items</string>
|
||||
<string name="backup_review_private_changed_body">They\'re encrypted, so they can\'t be compared here.</string>
|
||||
<string name="backup_review_gone">Gone</string>
|
||||
<string name="backup_review_new_tag">New</string>
|
||||
<string name="backup_review_dropped_tag">Dropped</string>
|
||||
<string name="backup_review_demoted_tag">Moved</string>
|
||||
<string name="backup_review_units_tag">Units</string>
|
||||
<string name="backup_review_left_tag">Left</string>
|
||||
<string name="backup_review_renamed_tag">Renamed</string>
|
||||
<string name="backup_review_outbox">Outbox</string>
|
||||
<string name="backup_review_outbox_explainer">where you publish</string>
|
||||
<string name="backup_review_inbox">Inbox</string>
|
||||
<string name="backup_review_inbox_explainer">where others reach you</string>
|
||||
<string name="backup_review_key_replaced">Receiving key replaced</string>
|
||||
<string name="backup_review_key_removed">Receiving key removed</string>
|
||||
<string name="backup_review_key_warning">Nutzaps will be locked to this new key. If this device doesn\'t have it, you may not be able to redeem them here.</string>
|
||||
<string name="backup_review_left">left</string>
|
||||
<string name="backup_review_joined">joined</string>
|
||||
<string name="backup_review_renamed">renamed</string>
|
||||
<string name="backup_review_was_named">was “%1$s”</string>
|
||||
<string name="backup_action_block_again">Block %1$s again</string>
|
||||
<string name="backup_action_restore_feeds">Restore feeds</string>
|
||||
<string name="backup_action_restore_topics">Restore topics</string>
|
||||
<string name="backup_action_restore_places">Restore places</string>
|
||||
<string name="backup_action_restore_providers">Restore providers</string>
|
||||
<string name="backup_action_restore_wallet">Restore wallet</string>
|
||||
<string name="backup_review_kept">kept</string>
|
||||
<string name="backup_review_receiving_tag">Receiving</string>
|
||||
<string name="backup_review_listed_tag">Listed</string>
|
||||
<string name="backup_review_searching_tag">Searching</string>
|
||||
<string name="backup_review_storing_tag">Storing</string>
|
||||
<string name="backup_review_trusted_tag">Trusted</string>
|
||||
<string name="backup_review_untrusted_tag">Untrusted</string>
|
||||
<string name="backup_review_unblocked">%1$s unblocked</string>
|
||||
<string name="backup_review_unblocked_explainer">Amethyst will connect to them again</string>
|
||||
<string name="backup_review_no_longer_blocked">No longer blocked</string>
|
||||
<string name="backup_review_newly_blocked">Newly blocked</string>
|
||||
<string name="backup_review_still_blocked">Still blocked</string>
|
||||
<string name="backup_review_allowed_tag">Allowed</string>
|
||||
<string name="backup_review_moved_tag">Moved</string>
|
||||
<string name="backup_review_feed">Feed</string>
|
||||
<string name="backup_review_topics_gone">topics gone</string>
|
||||
<string name="backup_review_places_gone">places gone</string>
|
||||
<string name="backup_review_new_count_caption">new</string>
|
||||
<string name="backup_review_hashtags_you_follow">Hashtags you follow</string>
|
||||
<string name="backup_review_places_you_follow">Places you follow</string>
|
||||
<string name="backup_review_services_changed">%1$s of %2$s services changed</string>
|
||||
<string name="backup_review_services_changed_explainer">They now come from someone else, or no one</string>
|
||||
<string name="backup_review_service">Service</string>
|
||||
<string name="backup_review_service_rank">Rank</string>
|
||||
<string name="backup_review_service_followers">Followers</string>
|
||||
<string name="backup_review_service_topics">Topics</string>
|
||||
<string name="backup_review_trust_warning">Ranks, follower counts and spam filtering you see come from these providers.</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">%1$d way to pay you removed</item>
|
||||
<item quantity="other">%1$d ways to pay you removed</item>
|
||||
</plurals>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d offer removed</item>
|
||||
<item quantity="other">%1$d offers removed</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">People paying you only see what\'s in this list.</string>
|
||||
<string name="backup_review_offer">BOLT12 offer</string>
|
||||
<string name="backup_review_encrypted_cleared">You emptied it</string>
|
||||
<string name="backup_review_encrypted_added">You created it</string>
|
||||
<string name="backup_review_encrypted_changed">You changed it</string>
|
||||
<string name="backup_review_wallet_body">Your wallet\'s mints and keys are encrypted to you, so they can\'t be compared item by item here. Restoring puts back exactly what this device saved.</string>
|
||||
<string name="backup_review_concord_body">Your Concord communities are encrypted to you, so they can\'t be compared here. Restoring puts back exactly what this device saved.</string>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">You unmuted %1$d thing</item>
|
||||
<item quantity="other">You unmuted %1$d things</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">You removed %1$d profile field</item>
|
||||
<item quantity="other">You removed %1$d profile fields</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">You removed %1$d public relay</item>
|
||||
<item quantity="other">You removed %1$d public relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">You removed %1$d DM relay</item>
|
||||
<item quantity="other">You removed %1$d DM relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">You removed %1$d group-chat key relay</item>
|
||||
<item quantity="other">You removed %1$d group-chat key relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">You removed %1$d search relay</item>
|
||||
<item quantity="other">You removed %1$d search relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">You removed %1$d indexer relay</item>
|
||||
<item quantity="other">You removed %1$d indexer relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">You removed %1$d relay feed</item>
|
||||
<item quantity="other">You removed %1$d relay feeds</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">You removed %1$d private relay</item>
|
||||
<item quantity="other">You removed %1$d private relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">You stopped trusting %1$d relay</item>
|
||||
<item quantity="other">You stopped trusting %1$d relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">You unblocked %1$d relay</item>
|
||||
<item quantity="other">You unblocked %1$d relays</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">You left %1$d public chat</item>
|
||||
<item quantity="other">You left %1$d public chats</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">You left %1$d community</item>
|
||||
<item quantity="other">You left %1$d communities</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">You left %1$d chat room</item>
|
||||
<item quantity="other">You left %1$d chat rooms</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">You left %1$d group</item>
|
||||
<item quantity="other">You left %1$d groups</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">You removed %1$d favorite feed</item>
|
||||
<item quantity="other">You removed %1$d favorite feeds</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">You unfollowed %1$d hashtag</item>
|
||||
<item quantity="other">You unfollowed %1$d hashtags</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">You unfollowed %1$d place</item>
|
||||
<item quantity="other">You unfollowed %1$d places</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">You changed the provider of %1$d trust service</item>
|
||||
<item quantity="other">You changed the provider of %1$d trust services</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">You removed %1$d nutzap mint</item>
|
||||
<item quantity="other">You removed %1$d nutzap mints</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">You removed %1$d way to get paid</item>
|
||||
<item quantity="other">You removed %1$d ways to get paid</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">You removed %1$d BOLT12 offer</item>
|
||||
<item quantity="other">You removed %1$d BOLT12 offers</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s and added %2$d</item>
|
||||
<item quantity="other">%1$s and added %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s and followed %2$d</item>
|
||||
<item quantity="other">%1$s and followed %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s and muted %2$d</item>
|
||||
<item quantity="other">%1$s and muted %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s and joined %2$d</item>
|
||||
<item quantity="other">%1$s and joined %2$d</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s and blocked %2$d</item>
|
||||
<item quantity="other">%1$s and blocked %2$d</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">Your Amethyst synced app settings changed in another app that is not Amethyst. This can create problems.</string>
|
||||
<string name="backup_card_nutzap_key_replaced">You replaced your nutzap key</string>
|
||||
<string name="backup_card_nutzap_key_removed">You removed your nutzap key</string>
|
||||
<string name="backup_card_wallet_emptied">You emptied your Cashu wallet</string>
|
||||
<string name="backup_card_wallet_rewritten">You changed your Cashu wallet</string>
|
||||
<string name="backup_card_concord_emptied">You emptied your Concord list</string>
|
||||
<string name="backup_card_concord_rewritten">You changed your Concord list</string>
|
||||
<string name="backup_conflict_keep_new">Use new version</string>
|
||||
<string name="backup_conflict_relay_read_only">read only</string>
|
||||
<string name="backup_conflict_relay_write_only">write only</string>
|
||||
<string name="backup_conflict_relay_read_write">read and write</string>
|
||||
<string name="backup_type_profile">profile</string>
|
||||
<string name="backup_type_profile_explainer">Your name, picture, bio and payment addresses, as everyone sees them.</string>
|
||||
<string name="backup_type_follow_list">follow list</string>
|
||||
<string name="backup_type_follow_list_explainer">Decides whose posts appear in your home feed.</string>
|
||||
<string name="backup_type_mute_list">mute list</string>
|
||||
<string name="backup_type_mute_list_explainer">Hides people, words, hashtags and threads from everything you see.</string>
|
||||
<string name="backup_type_outbox_inbox_relays">public relay list</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">Tells everyone where to find your posts and where to send you replies and mentions.</string>
|
||||
<string name="backup_type_dm_relays">DM relay list</string>
|
||||
<string name="backup_type_dm_relays_explainer">Where others deliver your private messages.</string>
|
||||
<string name="backup_type_key_package_relays">group-chat key relays</string>
|
||||
<string name="backup_type_key_package_relays_explainer">Where others find the keys to add you to encrypted group chats.</string>
|
||||
<string name="backup_type_search_relays">search relay list</string>
|
||||
<string name="backup_type_search_relays_explainer">The relays used when you search.</string>
|
||||
<string name="backup_type_indexer_relays">indexer relay list</string>
|
||||
<string name="backup_type_indexer_relays_explainer">The relays used to find other people\'s profiles and relay lists.</string>
|
||||
<string name="backup_type_relay_feeds">favorite relay feeds</string>
|
||||
<string name="backup_type_relay_feeds_explainer">The relays you browse as feeds.</string>
|
||||
<string name="backup_type_blocked_relays">blocked relay list</string>
|
||||
<string name="backup_type_blocked_relays_explainer">Relays this app never connects to.</string>
|
||||
<string name="backup_type_trusted_relays">trusted relay list</string>
|
||||
<string name="backup_type_trusted_relays_explainer">Relays you trust to connect to without asking.</string>
|
||||
<string name="backup_type_private_outbox_relays">private relay list</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">Where your drafts and private data are stored.</string>
|
||||
<string name="backup_type_app_settings">synced app settings</string>
|
||||
<string name="backup_type_app_settings_explainer">Amethyst settings synced across your devices. They are encrypted, so only their presence can be compared.</string>
|
||||
<string name="backup_type_public_chats">public chat list</string>
|
||||
<string name="backup_type_public_chats_explainer">The public chats you joined.</string>
|
||||
<string name="backup_type_communities">community list</string>
|
||||
<string name="backup_type_communities_explainer">The communities you joined.</string>
|
||||
<string name="backup_type_hashtags">followed hashtags</string>
|
||||
<string name="backup_type_hashtags_explainer">Hashtags whose posts appear in your feeds.</string>
|
||||
<string name="backup_type_geohashes">followed locations</string>
|
||||
<string name="backup_type_geohashes_explainer">Locations whose posts appear in your feeds.</string>
|
||||
<string name="backup_type_favorite_algo_feeds">favorite feeds list</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">The algorithmic feeds you saved.</string>
|
||||
<string name="backup_type_ephemeral_chats">ephemeral chat list</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">The ephemeral chat rooms you joined.</string>
|
||||
<string name="backup_type_relay_groups">group list</string>
|
||||
<string name="backup_type_relay_groups_explainer">The relay-based groups you joined.</string>
|
||||
<string name="backup_type_concord_communities">Concord community list</string>
|
||||
<string name="backup_type_concord_communities_explainer">The Concord communities you joined. They are encrypted, so only their presence can be compared.</string>
|
||||
<string name="backup_type_trust_providers">trust provider list</string>
|
||||
<string name="backup_type_trust_providers_explainer">The services you trust to rank and verify people for you.</string>
|
||||
<string name="backup_type_cashu_wallet">Cashu wallet</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">Your ecash wallet settings and mints. They are encrypted, so only their presence can be compared.</string>
|
||||
<string name="backup_type_nutzap_info">nutzap receiving settings</string>
|
||||
<string name="backup_type_nutzap_info_explainer">The mints and key others use to send you nutzaps.</string>
|
||||
<string name="backup_type_payment_targets">payment addresses</string>
|
||||
<string name="backup_type_payment_targets_explainer">The ways other people can pay you.</string>
|
||||
<string name="backup_type_bolt12_offers">BOLT12 offers</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">The lightning offers others use to pay you.</string>
|
||||
<string name="backup_type_other">list</string>
|
||||
<string name="backup_type_other_explainer">A list saved on this device.</string>
|
||||
<string name="backup_entry_profile_field">Profile fields</string>
|
||||
<string name="backup_entry_person">People</string>
|
||||
<string name="backup_entry_hashtag">Hashtags</string>
|
||||
<string name="backup_entry_word">Words</string>
|
||||
<string name="backup_entry_thread">Threads</string>
|
||||
<string name="backup_entry_public_chat">Public chats</string>
|
||||
<string name="backup_entry_community">Communities</string>
|
||||
<string name="backup_entry_algo_feed">Feeds</string>
|
||||
<string name="backup_entry_location">Locations</string>
|
||||
<string name="backup_entry_relay">Relays</string>
|
||||
<string name="backup_entry_relay_group">Groups</string>
|
||||
<string name="backup_entry_chat_room">Chat rooms</string>
|
||||
<string name="backup_entry_trust_provider">Trust providers</string>
|
||||
<string name="backup_entry_mint">Mints</string>
|
||||
<string name="backup_entry_nutzap_key">Nutzap keys</string>
|
||||
<string name="backup_entry_payment_target">Payment addresses</string>
|
||||
<string name="backup_entry_offer">Offers</string>
|
||||
<string name="backup_entry_identity_claim">Linked identities</string>
|
||||
<string name="backup_entry_other">Other entries</string>
|
||||
<string name="backup_profile_field_name">Username</string>
|
||||
<string name="backup_profile_field_display_name">Display name</string>
|
||||
<string name="backup_profile_field_about">About</string>
|
||||
<string name="backup_profile_field_picture">Picture</string>
|
||||
<string name="backup_profile_field_banner">Banner</string>
|
||||
<string name="backup_profile_field_website">Website</string>
|
||||
<string name="backup_profile_field_nip05">Nostr address</string>
|
||||
<string name="backup_profile_field_lud16">Lightning address</string>
|
||||
<string name="backup_profile_field_lud06">LNURL</string>
|
||||
<string name="backup_profile_field_pronouns">Pronouns</string>
|
||||
<string name="backup_profile_field_birthday">Birthday</string>
|
||||
<string name="backup_profile_field_clink_offer">CLINK offer</string>
|
||||
<string name="backup_profile_field_bot">Bot flag</string>
|
||||
<plurals name="cordn_info_admins_kept">
|
||||
<item quantity="one">The group\'s %1$d admin stays as it is.</item>
|
||||
<item quantity="other">The group\'s %1$d admins stay as they are.</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -184,6 +184,13 @@ class NappletProtocolJsonTest {
|
||||
assertEquals("Hi", up.bytes.decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun uploadAcceptsUnpaddedBase64() {
|
||||
// java.util.Base64 decoded "SGk" (no '=') as "Hi"; the commonMain decoder must too.
|
||||
val up = NappletProtocolJson.decodeRequest("""{"type":"upload.upload","request":{"dataBase64":"SGk"}}""") as NappletRequest.UploadBlob
|
||||
assertEquals("Hi", up.bytes.decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unknownTypeDecodesToNull() {
|
||||
assertNull(NappletProtocolJson.decodeRequest("""{"type":"inc.emit","id":"1"}"""))
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class ScheduledPostWorkGateTest {
|
||||
decisions.clear()
|
||||
}
|
||||
|
||||
private fun newStore() = ScheduledPostStore(file)
|
||||
private fun newStore() = ScheduledPostStore(file.path)
|
||||
|
||||
private fun TestScope.startGate(store: ScheduledPostStore) =
|
||||
ScheduledPostWorkGate(
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.backups
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.diff.EventDiff
|
||||
import com.vitorpamplona.quartz.nip01Core.diff.ListDiff
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataDiff
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListDiff
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* rememberPresentation resolves labels in composition and hands presentationOf a lookup
|
||||
* over exactly [labelsWrittenBy]; a label presentationOf asks for that is not in that list
|
||||
* crashes the review screen. presentationOf asks for every label of a diff type
|
||||
* regardless of which fields changed, so an empty diff of each type exercises them all.
|
||||
*/
|
||||
class BackupPresentationLabelsTest {
|
||||
private fun <T> empty() = ListDiff<T>(emptyList(), emptyList(), emptyList())
|
||||
|
||||
private fun asked(diff: EventDiff): Set<StringResource> {
|
||||
val asked = mutableSetOf<StringResource>()
|
||||
presentationOf(diff) {
|
||||
asked.add(it)
|
||||
""
|
||||
}
|
||||
return asked
|
||||
}
|
||||
|
||||
@Test
|
||||
fun metadataLabelsAreAllProvided() {
|
||||
val diff = MetadataDiff(null, null, null, null, null, null, null, null, null, null, null, null, null, empty(), empty())
|
||||
assertEquals(labelsWrittenBy(diff).toSet(), asked(diff))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun relayListLabelsAreAllProvided() {
|
||||
val diff = AdvertisedRelayListDiff(empty())
|
||||
assertEquals(labelsWrittenBy(diff).toSet(), asked(diff))
|
||||
}
|
||||
}
|
||||
@@ -771,11 +771,11 @@ Options, for the maintainer to pick:
|
||||
|
||||
### Next work, in recommended order (needs maintainer go-ahead per item)
|
||||
|
||||
- **Tier 4 unlocks** (small, mechanical): `NappletProtocolJson`
|
||||
- **Tier 4 unlocks** — **done 2026-09-26**, see the last section. (Was: small, mechanical: `NappletProtocolJson`
|
||||
`java.util.Base64` → `kotlin.io.encoding.Base64` (frees
|
||||
`NappletIdentityWatch`); `ScheduledPostStore` Jackson+`java.io.File` →
|
||||
kotlinx-serialization+okio (frees `ScheduledPostWorkGate`).
|
||||
`LargeSoftCache` stays parked (needs a WeakReference expect/actual).
|
||||
`LargeSoftCache` stays parked (needs a WeakReference expect/actual).)
|
||||
- **Wave 2: LocalCache move-group** — **part A landed (2026-09-19)**, see the
|
||||
section below. Part B (repoint `desktopApp`, delete `DesktopLocalCache.kt`)
|
||||
is the remaining half.
|
||||
@@ -1302,3 +1302,133 @@ through an `ingest` helper that pins what the cache built for the lifetime of
|
||||
the test instance, the way a screen holds the notes it is showing in the app,
|
||||
and keeps the forced GC in the test that failed so the contract is asserted
|
||||
rather than left to the heap.
|
||||
|
||||
## 2026-09-26 — Tier 4 unlocks, the strings drift, and the UI stragglers
|
||||
|
||||
### Tier 4: two jvmAndroid groups promoted to `commonMain`
|
||||
|
||||
- **Napplet wire protocol.** `NappletProtocolJson`, `NappletIdentityWatch` and
|
||||
`NappletRequestRouter` moved to `commons/commonMain/…/napplet`. The only
|
||||
pins were `java.util.Base64` and one `System.currentTimeMillis()`. Base64 is
|
||||
now `kotlin.io.encoding.Base64`, decoding with `PaddingOption.PRESENT_OPTIONAL`
|
||||
because `java.util.Base64.getDecoder()` accepted unpadded input and applets
|
||||
may send it. The clock is `TimeUtils.now()`.
|
||||
- **Scheduled posts.** `ScheduledPostStore` had already dropped Jackson for
|
||||
kotlinx-serialization; what pinned it was `java.io.File` and a POSIX
|
||||
`chmod`. It now takes an okio `Path` plus a `FileSystem` (default
|
||||
`platformFileSystem`), and a `String` constructor so callers need no okio,
|
||||
the same shape as `FileSystemNip95BlobStore`. The owner-only permission is a
|
||||
new `expect fun restrictFileToOwner(path, tag)`:
|
||||
`Files.setPosixFilePermissions` on jvmAndroid, POSIX `chmod(0600)` on iOS.
|
||||
The temp-file swap is `FileSystem.atomicMove`, which replaces an existing
|
||||
target on every platform, so the old "rename, else delete and rename again"
|
||||
fallback went with it. `ScheduledPostWorkGate`, `ScheduledPostPublisher` and
|
||||
`ScheduledPostNotifier` came along; none had a JVM pin of its own.
|
||||
|
||||
### The strings drift, fixed
|
||||
|
||||
Between the 2026-09-22 move and today, the cordn UI and the backup-conflict
|
||||
review added **447 keys** to `amethyst/src/main/res` (`cordn_*`, `backup_*`),
|
||||
taking it from 190 keys back to 597. All 447 moved with
|
||||
`tools/strings-migrate/migrate.py` (1,131 elements over 57 locales) and the 18
|
||||
files that read them were repointed. The non-mechanical sites:
|
||||
|
||||
- `stringRes(context, …)` inside `suspend` senders (`sendAttachment`,
|
||||
`sendVoiceNote`) → `loadStringRes(…)`. `adminFailureText` became `suspend`;
|
||||
its only caller is already in `scope.launch`.
|
||||
- The backup review kept its labels as `@StringRes Int` (`DiffGroup.label`,
|
||||
`ReviewRow.*Res`, `eventTypeName()`, the `countTiles`/`moneyHero`/`laneItems`
|
||||
params) → `StringResource` / `PluralStringResource`.
|
||||
- `rememberPresentation` resolved labels inside `remember { }` through
|
||||
`LocalResources`. Compose resources have no non-suspend accessor, so the 16
|
||||
labels `presentationOf` writes into item text are resolved in composition into
|
||||
a map, and the map is the `remember` key.
|
||||
- `androidx.compose.ui.res.pluralStringResource` → the compose-resources one.
|
||||
|
||||
Six moved keys have no reader today (`cordn_backup_restore_title`,
|
||||
`cordn_coordinators_relays`, `cordn_create_admin_only_me`,
|
||||
`cordn_create_coordinator`, `cordn_send`, `cordn_voice_play`). They moved
|
||||
rather than being deleted; dropping them is the feature owner's call.
|
||||
`pow_notification_sending` stays in Android `res/`: the PoW foreground service
|
||||
reads it synchronously.
|
||||
|
||||
The rule is now written down in `.claude/CLAUDE.md` ("Strings"), in
|
||||
`commonsUI/ARCHITECTURE.md`, and in the `android-expert` and
|
||||
`find-missing-translations` skills: new strings go in `commonsUI`
|
||||
composeResources, even for Android-only screens.
|
||||
|
||||
### UI stragglers moved to `commonsUI`
|
||||
|
||||
A survey against `main` found that most of "Batch 4" had already landed in
|
||||
other PRs (`dde228d2`, `1a563cf2`, `8dd409cb`, `1f1b6dab`): the theme
|
||||
constants (in `commonsUI/…/theme/Shape.kt`, not the `Sizes.kt` this plan
|
||||
named), the feed shell, the top bars, `M3ActionDialog`, `NoteComposeLayout`,
|
||||
`RepostLayout` and the toast queue. This round moved what was left that had no
|
||||
real blocker:
|
||||
|
||||
| Moved | To | Note |
|
||||
|---|---|---|
|
||||
| `NewItemsBubble` (from `ChatroomHeaderCompose.kt`) | `commonsUI/…/ui/components` | |
|
||||
| `ChatHeaderLayout`, `LeftPictureLayout` | `commonsUI/…/ui/layouts` | Their `@Preview`s use app drawables, `TimeAgo` and `TextCount`, so the previews stay app-side in `*Preview.kt` files |
|
||||
| `listItem/SlimListItemLayout` | `commonsUI/…/ui/layouts/listItem` | Same preview split; `@VisibleForTesting` dropped (no androidx.annotation in commonMain) |
|
||||
| `WatchScrollToTop` (list/grid/pager overloads) | `commonsUI/…/ui/feeds` | The `CardFeedContentState` overload stays in the app |
|
||||
| app `StickToTopOnPrepend` | deleted | It was a copy of the commons one. The commons copy now collects with `collectAsStateWithLifecycle`, as the app copy did |
|
||||
| `ChannelFeedState`, `ChannelFeedContentState` | `commons/commonMain/…/feeds` | `checkNotInMainThread()` → `LocalCache.appHost.assertNotMainThread()`, which Android wires to the same check |
|
||||
| `ClickableBuzzInviteLink`, `ClickableConcordInviteLink`, `ClickableRelayGroupLink`, `ClickableRelayUrl`, `OutlinedThinPaddingTextField` | `commonsUI/…/ui/components` | |
|
||||
| app `ClickableEmail`, `ClickablePhone` | deleted | Android now uses the commons ones (`mailto:` / `tel:` through `LocalUriHandler`) instead of `ACTION_SEND` / `ACTION_DIAL` intents. The commons `ClickablePhone` is new. Desktop still renders phone numbers as plain text, on purpose |
|
||||
|
||||
**Still app-side, with the reason:**
|
||||
|
||||
- `AmethystClickableIcon`: 9 lines around an Android debug action; moving it
|
||||
only pushes `LocalContext` into its two callers.
|
||||
- `ScreenLayout`: needs `LocalConfiguration` → `LocalWindowInfo`, and the
|
||||
window-size-class breakpoints inlined.
|
||||
- `SlidingCarousel`: needs `animatedViewerChromeInset` hoisted out of the
|
||||
viewer-chrome file.
|
||||
- `AudioWaveformReadOnly`: needs two enums from the Android-only waveform
|
||||
library replaced.
|
||||
- `FileAttachmentCard`: needs `extractFilename` hoisted.
|
||||
- `PdfFetcher`: needs the disk cache injected.
|
||||
- `ClickablePhone` / `ClickableEmail` on Desktop: deliberately unchanged.
|
||||
- **`AmethystTheme` split** (the pure scheme/typography half to commonsUI; the
|
||||
`Amethyst.instance` overload and the system-bar `SideEffect` stay).
|
||||
- **`TimeAgo` split**: the labels, `NowProvider` and the style enum are pure;
|
||||
the absolute and short formatters need expect/actual over
|
||||
`android.text.format`.
|
||||
- **Palette unification**: Desktop's `PlatformColorScheme` and the app palette
|
||||
differ in primary, secondary, surfaces and outlines, and every shared token
|
||||
(`placeholderText`, `chatBubbleThem`, …) is frozen from the app palette. This
|
||||
is a design decision, not a move.
|
||||
|
||||
### Audit of the 2026-09-26 round
|
||||
|
||||
The four commits were reviewed file by file against the originals. They had no
|
||||
functional bugs. The follow-ups:
|
||||
|
||||
- **Compose resources keep XML whitespace; Android didn't.** This is older than this
|
||||
round (it dates back to the first string moves), and it is the one real
|
||||
regression. aapt collapses every whitespace run in an unquoted value and trims
|
||||
the ends; Compose draws the XML text verbatim. So the values wrapped over
|
||||
indented lines (`account_backup_tips2_md`, `push_server_install_app_description`,
|
||||
`couldnt_find_nwc_wallets_description`, the chat explainers, and 349 translated
|
||||
values) rendered with a leading line break and eight spaces. In the `_md` strings
|
||||
CommonMark turns that into a code block. Crowdin also exports a translator's stray
|
||||
edge space, which aapt used to drop, for example ` miejsca zniknęły` and Hindi's
|
||||
` दि॰` time suffix. `fix_escapes.py` now applies aapt's rule to runs holding a line
|
||||
break or tab. In a translation it also trims an edge space its source string lacks,
|
||||
which keeps deliberate ones like `" and "`. The Crowdin workflow already runs it
|
||||
after every sync, and `compose_escaping_check.py` now fails on raw line breaks, so
|
||||
a sync can't bring it back. 598 values across 54 files were repaired.
|
||||
- `rememberPresentation` read all 16 backup labels on every recomposition, even for
|
||||
diff types that write none. It now reads only the ones its diff type uses, and
|
||||
`BackupPresentationLabelsTest` fails if `presentationOf` asks for a label that list
|
||||
lacks.
|
||||
- `ScheduledPostStore`: a failed stat now counts as "no file" rather than throwing
|
||||
(okio's posix metadata throws on EACCES where `File.exists()` returned false).
|
||||
Symlinked store files still count as present. The chmod is skipped for an injected
|
||||
non-system `FileSystem`, and the cleanup log keeps its throwable.
|
||||
- `ClickableEmail` percent-encodes `%` in the `mailto:` URI (RFC 6068).
|
||||
- Left as-is, by design: Kotlin's Base64 rejects non-zero pad bits (`"SGl="`) that
|
||||
Java ignored, which no browser encoder produces. `%1$d` arguments now render ASCII
|
||||
digits in every locale, the same as every other migrated string.
|
||||
`ChannelFeedContentState` reaches `LocalCache.appHost` for its main-thread check.
|
||||
|
||||
+6
-8
@@ -18,26 +18,24 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.feeds
|
||||
package com.vitorpamplona.amethyst.commons.feeds
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.vitorpamplona.amethyst.commons.feeds.AdditiveComplexFeedFilter
|
||||
import com.vitorpamplona.amethyst.commons.feeds.InvalidatableContent
|
||||
import com.vitorpamplona.amethyst.commons.feeds.LoadedFeedState
|
||||
import com.vitorpamplona.amethyst.commons.model.Channel
|
||||
import com.vitorpamplona.amethyst.commons.model.Note
|
||||
import com.vitorpamplona.amethyst.commons.model.cache.LocalCache
|
||||
import com.vitorpamplona.amethyst.commons.service.BundledInsert
|
||||
import com.vitorpamplona.amethyst.commons.service.BundledUpdate
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
||||
import com.vitorpamplona.amethyst.commons.util.equalImmutableLists
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import com.vitorpamplona.quartz.utils.flattenToSet
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.IO
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -75,7 +73,7 @@ class ChannelFeedContentState(
|
||||
}
|
||||
|
||||
fun refreshSuspended() {
|
||||
checkNotInMainThread()
|
||||
LocalCache.appHost.assertNotMainThread()
|
||||
|
||||
isRefreshing.value = true
|
||||
try {
|
||||
@@ -178,7 +176,7 @@ class ChannelFeedContentState(
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" }
|
||||
Log.d("Init") { "OnCleared: ${this::class.simpleName}" }
|
||||
bundlerInsert.cancel()
|
||||
bundler.cancel()
|
||||
}
|
||||
+1
-2
@@ -18,10 +18,9 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.feeds
|
||||
package com.vitorpamplona.amethyst.commons.feeds
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.vitorpamplona.amethyst.commons.feeds.LoadedFeedState
|
||||
import com.vitorpamplona.amethyst.commons.model.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
+14
-8
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.commons.napplet.protocol
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
@@ -37,7 +38,7 @@ import kotlinx.serialization.json.long
|
||||
import kotlinx.serialization.json.put
|
||||
import kotlinx.serialization.json.putJsonArray
|
||||
import kotlinx.serialization.json.putJsonObject
|
||||
import java.util.Base64
|
||||
import kotlin.io.encoding.Base64
|
||||
|
||||
/**
|
||||
* Marshals the KMP-pure [NappletRequest] / [NappletResponse] types to and from the wire the
|
||||
@@ -45,10 +46,10 @@ import java.util.Base64
|
||||
* (`@napplet/shim` / `@napplet/nap`): requests are `{ "type": "<domain>.<action>", "id", ...fields }`
|
||||
* and replies are `{ "type": "<domain>.<action>.result", "id", ...fields }`.
|
||||
*
|
||||
* Lives in `commons/jvmAndroid` (not in any single front end) because the wire contract is identical
|
||||
* Lives in `commons/commonMain` (not in any single front end) because the wire contract is identical
|
||||
* across hosts: the Android `:napplet` WebView host and a future desktop host both marshal through
|
||||
* here. It depends only on `quartz` (Event/Filter), kotlinx.serialization, and `java.util.Base64`
|
||||
* (available on Android API 26+ and the JVM) — no platform-UI or process APIs.
|
||||
* here. It depends only on `quartz` (Event/Filter), kotlinx.serialization and `kotlin.io.encoding`
|
||||
* — no platform-UI or process APIs.
|
||||
*
|
||||
* This is the only place the boundary parses untrusted applet input, so it is deliberately
|
||||
* strict: an unrecognized `type` decodes to `null` (the broker denies it) and a malformed/short
|
||||
@@ -58,6 +59,11 @@ import java.util.Base64
|
||||
object NappletProtocolJson {
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
|
||||
// Accepts unpadded input, as java.util.Base64's decoder did before this moved to commonMain.
|
||||
// One difference remains: non-zero pad bits ("SGl=") are rejected where Java ignored them.
|
||||
// Browsers' btoa/readAsDataURL never produce those, so only a hand-crafted payload hits it.
|
||||
private val lenientBase64 = Base64.withPadding(Base64.PaddingOption.PRESENT_OPTIONAL)
|
||||
|
||||
/** The `type` discriminant of a request envelope, used to build the matching `.result` type. */
|
||||
fun readType(envelopeJson: String): String? = json.parseToJsonElement(envelopeJson).jsonObject.str("type")
|
||||
|
||||
@@ -166,7 +172,7 @@ object NappletProtocolJson {
|
||||
kind = t.kindOf(),
|
||||
tags = decodeTags(t),
|
||||
content = t.str("content") ?: "",
|
||||
createdAt = t["created_at"]?.jsonPrimitive?.long ?: (System.currentTimeMillis() / 1000),
|
||||
createdAt = t["created_at"]?.jsonPrimitive?.long ?: TimeUtils.now(),
|
||||
)
|
||||
}
|
||||
// NIP-07 nip44.encrypt/decrypt: crypto only, no publish. `peer` is the counterparty
|
||||
@@ -194,7 +200,7 @@ object NappletProtocolJson {
|
||||
// The Blob in `request.data` is inlined as base64 `request.dataBase64` by shell.html.
|
||||
val request = o.getValue("request").jsonObject
|
||||
NappletRequest.UploadBlob(
|
||||
bytes = Base64.getDecoder().decode(request.req("dataBase64")),
|
||||
bytes = lenientBase64.decode(request.req("dataBase64")),
|
||||
contentType = request.str("mimeType") ?: "application/octet-stream",
|
||||
filename = request.str("filename"),
|
||||
)
|
||||
@@ -275,7 +281,7 @@ object NappletProtocolJson {
|
||||
}
|
||||
is NappletResponse.Bytes -> {
|
||||
put("ok", true)
|
||||
put("bytes", Base64.getEncoder().encodeToString(response.bytes))
|
||||
put("bytes", Base64.encode(response.bytes))
|
||||
put("mime", response.contentType)
|
||||
}
|
||||
is NappletResponse.ResourceInfo -> {
|
||||
@@ -301,7 +307,7 @@ object NappletProtocolJson {
|
||||
put("url", item.url)
|
||||
put("ok", item.resource != null)
|
||||
item.resource?.let {
|
||||
put("bytes", Base64.getEncoder().encodeToString(it.bytes))
|
||||
put("bytes", Base64.encode(it.bytes))
|
||||
put("mime", it.contentType)
|
||||
}
|
||||
item.error?.let { put("error", it) }
|
||||
+60
-41
@@ -20,21 +20,31 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.scheduledposts
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.util.platformFileSystem
|
||||
import com.vitorpamplona.amethyst.commons.util.restrictFileToOwner
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.attribute.PosixFilePermission
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
import okio.Path.Companion.toPath
|
||||
|
||||
class ScheduledPostStore(
|
||||
private val storageFile: File,
|
||||
private val nowSec: () -> Long = { System.currentTimeMillis() / 1000 },
|
||||
private val storageFile: Path,
|
||||
private val nowSec: () -> Long = { TimeUtils.now() },
|
||||
private val fileSystem: FileSystem = platformFileSystem,
|
||||
) {
|
||||
/** Takes the platform's own path string, so callers need no okio of their own. */
|
||||
constructor(
|
||||
storagePath: String,
|
||||
nowSec: () -> Long = { TimeUtils.now() },
|
||||
) : this(storagePath.toPath(), nowSec)
|
||||
|
||||
/**
|
||||
* `encodeDefaults = true` so this writes the same bytes Jackson did — kotlinx
|
||||
* omits a value equal to its default, which would silently drop `"version":1`
|
||||
@@ -214,7 +224,7 @@ class ScheduledPostStore(
|
||||
*/
|
||||
suspend fun publishNow(
|
||||
id: String,
|
||||
nowSec: Long = System.currentTimeMillis() / 1000,
|
||||
nowSec: Long = TimeUtils.now(),
|
||||
): Boolean =
|
||||
mutex.withLock {
|
||||
ensureLoaded()
|
||||
@@ -336,8 +346,8 @@ class ScheduledPostStore(
|
||||
private fun reloadFromDiskLocked() {
|
||||
val fromDisk =
|
||||
try {
|
||||
if (storageFile.exists() && storageFile.length() > 0) {
|
||||
json.decodeFromString<ScheduledPostFile>(storageFile.readText()).posts.toMutableList()
|
||||
if (hasContent()) {
|
||||
json.decodeFromString<ScheduledPostFile>(readText()).posts.toMutableList()
|
||||
} else {
|
||||
// File vanished — treat as no external state; keep current in-memory.
|
||||
return
|
||||
@@ -354,8 +364,8 @@ class ScheduledPostStore(
|
||||
if (loaded) return
|
||||
posts =
|
||||
try {
|
||||
if (storageFile.exists() && storageFile.length() > 0) {
|
||||
json.decodeFromString<ScheduledPostFile>(storageFile.readText()).posts.toMutableList()
|
||||
if (hasContent()) {
|
||||
json.decodeFromString<ScheduledPostFile>(readText()).posts.toMutableList()
|
||||
} else {
|
||||
mutableListOf()
|
||||
}
|
||||
@@ -367,7 +377,7 @@ class ScheduledPostStore(
|
||||
// Secure a pre-existing file up front (an older build may have left it at the
|
||||
// 0644 umask default) so it's owner-only even if nothing mutates the store
|
||||
// this session.
|
||||
if (storageFile.exists()) restrictToOwner(storageFile)
|
||||
if (storeFileExists()) restrictToOwner(storageFile)
|
||||
var dirty = purgeStale(nowSec())
|
||||
// Recover claims stranded by a crash-mid-publish so they aren't lost forever.
|
||||
if (recoverStuckClaimsLocked(nowSec())) dirty = true
|
||||
@@ -412,49 +422,58 @@ class ScheduledPostStore(
|
||||
private fun persist() {
|
||||
val snapshot = posts.toList()
|
||||
_flow.value = snapshot
|
||||
storageFile.parentFile?.mkdirs()
|
||||
val tmp = File(storageFile.parentFile, storageFile.name + ".tmp")
|
||||
val tmp = "$storageFile.tmp".toPath()
|
||||
try {
|
||||
tmp.writeText(json.encodeToString(ScheduledPostFile(version = 1, posts = snapshot)))
|
||||
// Restrict to owner-only BEFORE the rename so the store is never briefly
|
||||
storageFile.parent?.let { fileSystem.createDirectories(it) }
|
||||
fileSystem.write(tmp) { writeUtf8(json.encodeToString(ScheduledPostFile(version = 1, posts = snapshot))) }
|
||||
// Restrict to owner-only BEFORE the rename, so the store file itself is never
|
||||
// world-readable. It holds pre-signed events + the account's pubkey, which
|
||||
// must not leak to other local users on a shared machine.
|
||||
// must not leak to other local users on a shared machine. (The tmp file is
|
||||
// created at the umask default and narrowed right after its write; the
|
||||
// directory around it is owner-only on every host that uses this store.)
|
||||
restrictToOwner(tmp)
|
||||
if (!tmp.renameTo(storageFile)) {
|
||||
if (!storageFile.delete()) {
|
||||
Log.w(TAG) { "Failed to delete existing $storageFile before rename retry" }
|
||||
}
|
||||
if (!tmp.renameTo(storageFile)) {
|
||||
Log.e(TAG) { "Failed to rename $tmp to $storageFile" }
|
||||
if (!tmp.delete()) {
|
||||
Log.w(TAG) { "Failed to clean up temp file $tmp after rename failure" }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Replaces an existing target, including on Windows, where a plain rename
|
||||
// onto an existing file fails.
|
||||
fileSystem.atomicMove(tmp, storageFile)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to persist scheduled posts to $storageFile", e)
|
||||
if (!tmp.delete()) {
|
||||
Log.w(TAG) { "Failed to clean up temp file $tmp after persist exception" }
|
||||
try {
|
||||
fileSystem.delete(tmp)
|
||||
} catch (cleanupError: Exception) {
|
||||
Log.w(TAG, "Failed to clean up temp file $tmp after persist exception", cleanupError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort chmod to `0600` (owner read/write only). No-op on filesystems
|
||||
* without POSIX permissions (e.g. Windows), where confidentiality relies on the
|
||||
* per-user home directory instead. Never throws.
|
||||
* Permissions are a property of the real disk, so a caller that injects another
|
||||
* [FileSystem] (an in-memory fake) gets no chmod aimed at a same-named real path.
|
||||
*/
|
||||
private fun restrictToOwner(file: File) {
|
||||
try {
|
||||
Files.setPosixFilePermissions(
|
||||
file.toPath(),
|
||||
setOf(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG) { "Could not restrict permissions on $file: ${e.message}" }
|
||||
}
|
||||
private fun restrictToOwner(path: Path) {
|
||||
if (fileSystem === platformFileSystem) restrictFileToOwner(path, TAG)
|
||||
}
|
||||
|
||||
/**
|
||||
* The store file's metadata, or null when there is none. A directory is not a store
|
||||
* file. A symlink counts: okio's metadata does not follow links, so its size is the
|
||||
* link's, and reading it (which does follow) decides whether there is anything in it.
|
||||
* A stat that fails (EACCES on iOS, where File.exists() used to answer false) is "no
|
||||
* file" rather than an exception out of the store.
|
||||
*/
|
||||
private fun storeFileMetadata() =
|
||||
try {
|
||||
fileSystem.metadataOrNull(storageFile)?.takeIf { it.isRegularFile || it.symlinkTarget != null }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Could not stat $storageFile", e)
|
||||
null
|
||||
}
|
||||
|
||||
private fun storeFileExists(): Boolean = storeFileMetadata() != null
|
||||
|
||||
private fun hasContent(): Boolean = (storeFileMetadata()?.size ?: 0L) > 0L
|
||||
|
||||
private fun readText(): String = fileSystem.read(storageFile) { readUtf8() }
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ScheduledPostStore"
|
||||
const val FILE_NAME = "scheduled_posts.json"
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.util
|
||||
|
||||
import okio.Path
|
||||
|
||||
/**
|
||||
* Restricts the file at [path] to owner read/write (`0600`), best-effort. Never throws.
|
||||
*
|
||||
* Silent where the filesystem has no POSIX permissions (Windows), where the user profile's
|
||||
* ACLs apply instead; logs under [tag] when a POSIX filesystem refuses.
|
||||
*/
|
||||
expect fun restrictFileToOwner(
|
||||
path: Path,
|
||||
tag: String,
|
||||
)
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.util
|
||||
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import kotlinx.cinterop.convert
|
||||
import okio.Path
|
||||
import platform.posix.S_IRUSR
|
||||
import platform.posix.S_IWUSR
|
||||
import platform.posix.chmod
|
||||
import platform.posix.errno
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
actual fun restrictFileToOwner(
|
||||
path: Path,
|
||||
tag: String,
|
||||
) {
|
||||
if (chmod(path.toString(), (S_IRUSR or S_IWUSR).convert()) != 0) {
|
||||
val error = errno
|
||||
Log.w(tag) { "Could not restrict permissions on $path: errno $error" }
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.util
|
||||
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import okio.Path
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.attribute.PosixFilePermission
|
||||
|
||||
actual fun restrictFileToOwner(
|
||||
path: Path,
|
||||
tag: String,
|
||||
) {
|
||||
try {
|
||||
Files.setPosixFilePermissions(
|
||||
path.toNioPath(),
|
||||
setOf(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE),
|
||||
)
|
||||
} catch (_: UnsupportedOperationException) {
|
||||
// Windows: no POSIX permissions; the user profile's NTFS ACLs apply instead.
|
||||
} catch (e: Exception) {
|
||||
Log.w(tag, "Could not restrict permissions on $path", e)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -47,7 +47,7 @@ class ScheduledPostStoreTest {
|
||||
file = File(temp.root, "scheduled_posts.json")
|
||||
}
|
||||
|
||||
private fun newStore(now: () -> Long = { System.currentTimeMillis() / 1000 }) = ScheduledPostStore(file, now)
|
||||
private fun newStore(now: () -> Long = { System.currentTimeMillis() / 1000 }) = ScheduledPostStore(file.path, now)
|
||||
|
||||
private fun samplePost(
|
||||
id: String = "id-1",
|
||||
|
||||
@@ -58,7 +58,10 @@ is specific to the UI module.
|
||||
`tools/icon-font/build_icon_font.py` read `icons/` and write
|
||||
`composeResources/font/` in this module (see root `.claude/CLAUDE.md`, "Icons").
|
||||
- Translations: `crowdin.yml` and `tools/strings-migrate/` target
|
||||
`commonsUI/src/commonMain/composeResources/`.
|
||||
`commonsUI/src/commonMain/composeResources/`. This is where **every new
|
||||
user-visible string** goes, Android-only screens included; the app's own
|
||||
`res/values/strings.xml` holds only the synchronous-platform tier (see root
|
||||
`.claude/CLAUDE.md`, "Strings").
|
||||
- CI: `.github/workflows/build.yml` runs `:commonsUI:jvmTest`,
|
||||
`:commonsUI:verifyKmpPurity` and the iOS compile/test tasks next to the
|
||||
`:commons` ones.
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
<string name="copy_user_id">نسخ معرف المستخدم</string>
|
||||
<string name="unblock_user">إلغاء حظر عن مستخدم</string>
|
||||
<string name="user_is_blocked_hidden">هذا المستخدم محظور/مكتوم. منشوراته مخفية.</string>
|
||||
<string name="npub_hex_username">npub, hex, username </string>
|
||||
<string name="npub_hex_username">npub, hex, username</string>
|
||||
<string name="clear">نظف</string>
|
||||
<string name="app_logo">شعار التطبيق</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex private key</string>
|
||||
@@ -282,15 +282,8 @@
|
||||
<string name="mark_all_known_as_read">ضع علامة على جميع الرسائل/الاشعارات المعروفة كمقروء</string>
|
||||
<string name="mark_all_new_as_read">تعيين الجديد كمقروء</string>
|
||||
<string name="mark_all_as_read">تعيين الكل كمقروء</string>
|
||||
<string name="account_backup_tips2_md"> ## النصائح الرئيسية للنسخ الاحتياطي والسلامة
|
||||
\n\n- يتم تأمين حسابك بمفتاح سري. المفتاح السري هو سلسلة عشوائية طويلة تبدأ بـ **nsec1**. أي شخص لديه مفتاحك السري يمكنه نشر المحتوى باستخدام هويتك.
|
||||
\n\n- لا تقم بوضع مفتاحك السري في أي موقع أو برنامج لا تثق به.
|
||||
\n- مطوري Amethyst لن يطلبوا منك **أبدا** المفتاح السري الخاص بك.
|
||||
\n- حافظ على نسخة احتياطية آمنة لمفتاحك السري لاسترداد الحساب. نوصي باستخدام برنامج لادارة كلمات المرور.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> للحصول على أمان إضافي، يمكنك تشفير مفتاحك الخاص بكلمة مرور. يبدأ هذا المفتاح المشفر بـ **ncryptsec1** ولا يمكن استخدامه دون كلمة المرور الخاصة بك.
|
||||
\n\nإذا فقدت كلمة المرور، لن تتمكن من استرداد مفتاحك الخاص.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## النصائح الرئيسية للنسخ الاحتياطي والسلامة \n\n- يتم تأمين حسابك بمفتاح سري. المفتاح السري هو سلسلة عشوائية طويلة تبدأ بـ **nsec1**. أي شخص لديه مفتاحك السري يمكنه نشر المحتوى باستخدام هويتك. \n\n- لا تقم بوضع مفتاحك السري في أي موقع أو برنامج لا تثق به. \n- مطوري Amethyst لن يطلبوا منك **أبدا** المفتاح السري الخاص بك. \n- حافظ على نسخة احتياطية آمنة لمفتاحك السري لاسترداد الحساب. نوصي باستخدام برنامج لادارة كلمات المرور.</string>
|
||||
<string name="account_backup_tips3_md">للحصول على أمان إضافي، يمكنك تشفير مفتاحك الخاص بكلمة مرور. يبدأ هذا المفتاح المشفر بـ **ncryptsec1** ولا يمكن استخدامه دون كلمة المرور الخاصة بك. \n\nإذا فقدت كلمة المرور، لن تتمكن من استرداد مفتاحك الخاص.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">تشفير و نسخ المفتاح الخاص</string>
|
||||
<string name="badge_award_image_for">صورة شارة مكافئة ل %1$s</string>
|
||||
<string name="badge_award_image">"صورة منح الشارة</string>
|
||||
@@ -311,7 +304,7 @@
|
||||
<string name="quick_action_request_deletion_gallery_alert_body_v2">إزالة هذه الوسائط من معرضك.</string>
|
||||
<string name="quick_action_request_deletion_alert_title">طلب حذفها</string>
|
||||
<string name="quick_action_request_deletion_alert_body">سيطلب Amethyst حذف ملاحظتك من المرحلات المتصل بها حاليا، لا يوجد ضمان لحذفها من هذه المرحلات أو من المرحلات الأخرى التي ربما حفظت فيها.</string>
|
||||
<string name="quick_action_block_dialog_btn">حظر </string>
|
||||
<string name="quick_action_block_dialog_btn">حظر</string>
|
||||
<string name="quick_action_delete_dialog_btn">حذف</string>
|
||||
<string name="quick_action_block">حظر</string>
|
||||
<string name="quick_action_report">التبليغ</string>
|
||||
@@ -693,8 +686,7 @@
|
||||
<string name="add_caption">إضافة شرح توضيحي</string>
|
||||
<string name="add_caption_example">صديقي المميز</string>
|
||||
<string name="content_description">وصف المحتوى/المحتويات</string>
|
||||
<string name="content_description_example">A blue boat in a white sandy beach at sunset
|
||||
(قارب أزرق في شاطئ رملي أبيض عند غروب الشمس)</string>
|
||||
<string name="content_description_example">A blue boat in a white sandy beach at sunset (قارب أزرق في شاطئ رملي أبيض عند غروب الشمس)</string>
|
||||
<string name="ai_suggested_alt_text_hint">اقتراح من الذكاء الاصطناعي، يمكنك تعديله</string>
|
||||
<string name="ai_suggested_alt_text_dismiss">رفض اقتراح الذكاء الاصطناعي</string>
|
||||
<string name="zap_type">نوع الزاب</string>
|
||||
@@ -847,7 +839,7 @@
|
||||
<string name="relay_filter_since">منذ %1$s</string>
|
||||
<string name="relay_filter_until">حتى %1$s</string>
|
||||
<string name="relay_filter_limit">الحد %1$d</string>
|
||||
<string name="minimum_prefix">الحد الأدنى لل prefix </string>
|
||||
<string name="minimum_prefix">الحد الأدنى لل prefix</string>
|
||||
<string name="maximum_event_tags">الحد الأقصى لوسوم الحدث</string>
|
||||
<string name="max_content_length">الحد الأقصى لطول المحتوى</string>
|
||||
<string name="discards_older_than">تُهمَل أقدم من</string>
|
||||
@@ -886,10 +878,8 @@
|
||||
<string name="followed_tags">العلامات المُتابعة</string>
|
||||
<string name="discover_follows_explainer">هذه قوائم بالمستخدمين التي توصي بها للآخرين. يُسمح فقط بالمستخدمين العامين.</string>
|
||||
<string name="community_approved_posts">المنشورات الموافق عليها</string>
|
||||
<string name="groups_no_descriptor">هذه المجموعة ليس لديها وصف أو قواعد.
|
||||
تحدث إلى المالك لإضافة مستخدم جديد</string>
|
||||
<string name="community_no_descriptor">هذا المجتمع ليس لديه وصف أو قواعد.
|
||||
تحدث إلى المالك لإضافة مستخدم جديد</string>
|
||||
<string name="groups_no_descriptor">هذه المجموعة ليس لديها وصف أو قواعد. تحدث إلى المالك لإضافة مستخدم جديد</string>
|
||||
<string name="community_no_descriptor">هذا المجتمع ليس لديه وصف أو قواعد. تحدث إلى المالك لإضافة مستخدم جديد</string>
|
||||
<string name="user_preferences">تفضيلات المستخدم</string>
|
||||
<string name="settings_search_placeholder">البحث في الإعدادات</string>
|
||||
<string name="settings_search_no_results">لا توجد إعدادات لـ "%1$s"</string>
|
||||
@@ -982,9 +972,7 @@
|
||||
<string name="push_server_none_explainer">تعطيل الإشعارات</string>
|
||||
<string name="push_server_uses_app_explainer">يتم استخدام هذا التطبيق: %1$s</string>
|
||||
<string name="push_server_install_app">إعدادات الإشعارات</string>
|
||||
<string name="push_server_install_app_description">لاستخدام الإشعارات حمل أي تطبيق يدعم ال [Unified Push](https://unifiedpush.org/)
|
||||
مثل [Ntfy](https://ntfy.sh/).
|
||||
بعد تثبيتك التطبيق قم باختياره من الإعدادات</string>
|
||||
<string name="push_server_install_app_description">لاستخدام الإشعارات حمل أي تطبيق يدعم ال [Unified Push](https://unifiedpush.org/) مثل [Ntfy](https://ntfy.sh/). بعد تثبيتك التطبيق قم باختياره من الإعدادات</string>
|
||||
<string name="thread_title">الخيط</string>
|
||||
<string name="send_the_seller_a_message">أرسل رسالة إلى البائع</string>
|
||||
<string name="hi_there_is_this_still_available">مرحبًا، هل هذا لا يزال متاحًا؟</string>
|
||||
@@ -1876,7 +1864,7 @@
|
||||
<string name="biometric_authentication_failed">فشلت المصادقة</string>
|
||||
<string name="biometric_authentication_failed_explainer">فشل التحقق البيومتري في مصادقة مالك هذا الهاتف</string>
|
||||
<string name="biometric_authentication_failed_explainer_with_error">فشل التحقق البيومتري في مصادقة مالك هذا الهاتف. الخطأ: %1$s</string>
|
||||
<string name="block_only">حظر </string>
|
||||
<string name="block_only">حظر</string>
|
||||
<string name="blocked_section_explainer">لن يتصل Amethyst أبدًا بهذه الـ relays</string>
|
||||
<string name="blocked_users">المستخدمين المحظورين</string>
|
||||
<string name="bookmark_list_creation_screen_title">قائمة إشارات مرجعية جديدة</string>
|
||||
@@ -1986,8 +1974,7 @@
|
||||
<string name="cashu_settings_delete_confirm_body">نشر طلب حذف لتوصية kind:38000 الخاصة بك لـ %1$s. ستحذفها الـ relays التي تحترم NIP-09.</string>
|
||||
<string name="cashu_settings_restore_result">تم استرداد %1$s sats عبر %2$s أدلة.</string>
|
||||
<string name="cashu_successful_redemption">تم استلام Cashu</string>
|
||||
<string name="cashu_successful_redemption_explainer">%1$s sats أرسلت الى محفظتك
|
||||
(الرسوم: sats %2$s ) </string>
|
||||
<string name="cashu_successful_redemption_explainer">%1$s sats أرسلت الى محفظتك (الرسوم: sats %2$s )</string>
|
||||
<plurals name="cashu_untrusted_mint_title">
|
||||
<item quantity="zero">لا أموال محتجزة في mint غير مستخدم</item>
|
||||
<item quantity="one">أموال محتجزة في %1$d mint لا تستخدمه</item>
|
||||
@@ -2060,15 +2047,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">تعذّر جلب الفاتورة من %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">تعذّر فتح الملف المضغوط</string>
|
||||
<string name="couldnt_find_nwc_wallets">لم يتم العثور على المحفظة</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">لم يتمكن Amethyst من العثور على أي تطبيقات محافظ تدعم Nostr Wallet Connect (NWC).
|
||||
\n\nما يمكنك فعله:
|
||||
\n\t1. التحقق من دعم NWC: تأكد من أن تطبيق محفظتك المفضل متوافق مع Nostr Wallet Connect.
|
||||
\n\t2. إنشاء اتصال: انتقل إلى تطبيق محفظتك وأنشئ اتصال NWC جديدًا.
|
||||
\n\t3. الربط بـ Amethyst: عادةً ما تتيح محفظتك ثلاثة خيارات:
|
||||
\n\t\t3.1 ربط تلقائي: زر لفتح Amethyst والاتصال به تلقائيًا. إذا كان الأمر كذلك، اضغط على الزر، وافتح Amethyst واضغط على حفظ في الشاشة الجديدة.
|
||||
\n\t\t3.2 ربط يدوي: عنوان URI للاتصال يمكنك نسخه والضغط على أيقونة اللصق في هذه الشاشة لإدخاله مباشرةً.
|
||||
\n\t\t3.3 رمز QR: تنشئ المحفظة رمز QR يمكنك قراءته من زر رمز QR في هذه الشاشة.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">لم يتمكن Amethyst من العثور على أي تطبيقات محافظ تدعم Nostr Wallet Connect (NWC). \n\nما يمكنك فعله: \n\t1. التحقق من دعم NWC: تأكد من أن تطبيق محفظتك المفضل متوافق مع Nostr Wallet Connect. \n\t2. إنشاء اتصال: انتقل إلى تطبيق محفظتك وأنشئ اتصال NWC جديدًا. \n\t3. الربط بـ Amethyst: عادةً ما تتيح محفظتك ثلاثة خيارات: \n\t\t3.1 ربط تلقائي: زر لفتح Amethyst والاتصال به تلقائيًا. إذا كان الأمر كذلك، اضغط على الزر، وافتح Amethyst واضغط على حفظ في الشاشة الجديدة. \n\t\t3.2 ربط يدوي: عنوان URI للاتصال يمكنك نسخه والضغط على أيقونة اللصق في هذه الشاشة لإدخاله مباشرةً. \n\t\t3.3 رمز QR: تنشئ المحفظة رمز QR يمكنك قراءته من زر رمز QR في هذه الشاشة.</string>
|
||||
<string name="create">إنشاء</string>
|
||||
<string name="d">يوم</string>
|
||||
<string name="danger_zone">منطقة الخطر</string>
|
||||
@@ -2451,7 +2430,7 @@
|
||||
<string name="login_with_a_private_key_to_be_able_to_send_zaps">قم بتسجيل الدخول باستخدام مفتاح خاص لتتمكن من إرسال Zaps</string>
|
||||
<string name="login_with_a_private_key_to_be_able_to_show_word">قم بتسجيل الدخول باستخدام مفتاحك السري لتتمكن من إظهار الكلمة أو الجملة</string>
|
||||
<string name="login_with_a_private_key_to_be_able_to_sign_events">أنت تستخدم مفتاحًا عامًا وهو للقراءة فقط. سجّل الدخول بمفتاح خاص لتتمكن من توقيع الأحداث</string>
|
||||
<string name="login_with_a_private_key_to_be_able_to_unfollow">قم بتسجيل الدخول بمفتاحك الخاص للتتمكن من إلغاء متابعة المستخدمين </string>
|
||||
<string name="login_with_a_private_key_to_be_able_to_unfollow">قم بتسجيل الدخول بمفتاحك الخاص للتتمكن من إلغاء متابعة المستخدمين</string>
|
||||
<string name="login_with_a_private_key_to_be_able_to_upload">أنت تستخدم مفتاحًا عامًا وهو للقراءة فقط. سجّل الدخول بمفتاح خاص لتتمكن من الرفع</string>
|
||||
<string name="login_with_a_private_key_to_like_posts">تسجيل الدخول باستخدام مفتاح خاص لإبداء الإعجاب بالمنشورات</string>
|
||||
<string name="longs">مقاطع فيديو</string>
|
||||
@@ -2786,8 +2765,7 @@
|
||||
<string name="preview_card_image_for">معاينة صورة البطاقة لـ %1$s</string>
|
||||
<string name="privacy_options">خيارات الخصوصية</string>
|
||||
<string name="privacy_policy">سياسة الخصوصية</string>
|
||||
<string name="private_conversation_notification"><استحالة فك تشفير الرسالة الخاصة>
|
||||
\n\n أنت الآن في محادثة خاصة/مشفرة بين %1$s و %2$s .</string>
|
||||
<string name="private_conversation_notification"><استحالة فك تشفير الرسالة الخاصة> \n\n أنت الآن في محادثة خاصة/مشفرة بين %1$s و %2$s .</string>
|
||||
<string name="private_inbox_section_explainer">أدخل ما بين 1 و3 relays لتكون صندوقًا واردًا خاصًا. سيستخدم الآخرون هذه الـ relays لإرسال رسائل مباشرة إليك. يجب أن تقبل DM Inbox relays أي رسالة من أي شخص، لكن تسمح لك وحدك بتنزيلها. خيارات جيدة:\n - inbox.nostr.wine (مدفوع)\n - auth.nostr1.com (مجاني)\n - you.nostr1.com (relays شخصية - مدفوعة)</string>
|
||||
<string name="private_inbox_section_explainer_profile">المستخدم يستقبل الرسائل المباشرة على هذه الـ relays</string>
|
||||
<string name="private_message">رسالة خاصة</string>
|
||||
@@ -2807,11 +2785,8 @@
|
||||
<string name="propose_an_edit">اقتراح تعديل</string>
|
||||
<string name="proxy_section_explainer">الـ relays التجميعية التي يجب أن يستخدمها التطبيق لتنزيل تغذياتك منها، مثل filter.nostr.wine. هذا يستبدل نموذج outbox وسيجعل التطبيق يتصل فقط بالـ relays الموجودة في قوائمك.</string>
|
||||
<string name="public_chat">الدردشة العامة</string>
|
||||
<string name="public_chat_explainer">المحادثات العامة مرئية للجميع على Nostr ويمكن لأي شخص
|
||||
المشاركة فيها. إنها مناسبة للمجتمعات المفتوحة حول مواضيع محددة.
|
||||
يمكن التحكم في الإشراف عبر حذف المنشورات على relay المجموعة</string>
|
||||
<string name="public_chat_relays_explainer">أدخل من 1 إلى 3 relay تستضيف هذه المجموعة.
|
||||
تستخدم تطبيقات Nostr هذا الإعداد لمعرفة مكان تنزيل الرسائل وإرسالها.</string>
|
||||
<string name="public_chat_explainer">المحادثات العامة مرئية للجميع على Nostr ويمكن لأي شخص المشاركة فيها. إنها مناسبة للمجتمعات المفتوحة حول مواضيع محددة. يمكن التحكم في الإشراف عبر حذف المنشورات على relay المجموعة</string>
|
||||
<string name="public_chat_relays_explainer">أدخل من 1 إلى 3 relay تستضيف هذه المجموعة. تستخدم تطبيقات Nostr هذا الإعداد لمعرفة مكان تنزيل الرسائل وإرسالها.</string>
|
||||
<string name="public_chat_title">بيانات المحادثة العامة</string>
|
||||
<string name="public_chats">المحادثات العامة</string>
|
||||
<string name="public_home_section_explainer">يخزّن هذا النوع من الـ relay جميع محتواك. سيرسل Amethyst منشوراتك إليها وسيستخدم الآخرون هذه الـ relays للعثور على محتواك. أدخل ما بين 1 و3 relays. يمكن أن تكون relays شخصية أو مدفوعة أو عامة.</string>
|
||||
@@ -2833,10 +2808,7 @@
|
||||
<string name="read_only_user">مستخدم في وضع القراءة فقط</string>
|
||||
<string name="record_a_message_description">اضغط مطوّلًا لتسجيل رسالة</string>
|
||||
<string name="relay_chat">محادثة relay</string>
|
||||
<string name="relay_chat_explainer">محادثات relay هي مجموعات دردشة يتحكم فيها الـ relay المضيف.
|
||||
إنها مرئية للجميع على Nostr ويمكن لأي شخص المشاركة فيها.
|
||||
إنها مناسبة للمجتمعات المفتوحة حول مواضيع محددة. بعض هذه المجموعات مؤقتة
|
||||
وبالتالي تختفي رسائل الدردشة بمرور الوقت</string>
|
||||
<string name="relay_chat_explainer">محادثات relay هي مجموعات دردشة يتحكم فيها الـ relay المضيف. إنها مرئية للجميع على Nostr ويمكن لأي شخص المشاركة فيها. إنها مناسبة للمجتمعات المفتوحة حول مواضيع محددة. بعض هذه المجموعات مؤقتة وبالتالي تختفي رسائل الدردشة بمرور الوقت</string>
|
||||
<string name="relay_chat_title">محادثات relay</string>
|
||||
<string name="relay_management_tab_events">الأحداث</string>
|
||||
<string name="relay_management_tab_ips">عناوين IP</string>
|
||||
|
||||
@@ -271,15 +271,8 @@
|
||||
<string name="mark_all_known_as_read">পরিচিত সবগুলোকে পঠিত হিসেবে চিহ্নিত করুন</string>
|
||||
<string name="mark_all_new_as_read">নতুন সবগুলোকে পঠিত হিসেবে চিহ্নিত করুন</string>
|
||||
<string name="mark_all_as_read">সবগুলোকে পঠিত হিসেবে চিহ্নিত করুন</string>
|
||||
<string name="account_backup_tips2_md"> ## মূল ব্যাকআপ এবং নিরাপত্তা টিপস
|
||||
\n\n আপনার অ্যাকাউন্ট একটি গোপন কী দ্বারা সুরক্ষিত। মূলটি হল অক্ষরগুলির একটি দীর্ঘ ক্রম যা শুরু হয় **nsec1**. যে কেউ এই গোপন কী অ্যাক্সেস করতে পারে পোস্ট এবং আপনার পরিচয় পরিবর্তন করতে পারেন.
|
||||
\n\n- আপনি বিশ্বাস করেন না এমন কোনো ওয়েবসাইট বা সফ্টওয়্যারে আপনার গোপন কী **করবেন না**.
|
||||
\n- অ্যামেথিস্ট ডেভেলপাররা **কখনই** আপনার গোপন কী চাইবে না.
|
||||
\n- **করুন** অ্যাকাউন্ট পুনরুদ্ধারের জন্য আপনার গোপন কীটির একটি নিরাপদ ব্যাকআপ রাখুন৷. আমরা একটি পাসওয়ার্ড ম্যানেজার ব্যবহার করার পরামর্শ দিই।.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> অতিরিক্ত নিরাপত্তার জন্য, আপনি একটি পাসওয়ার্ড দিয়ে আপনার কী এনক্রিপ্ট করতে পারেন. এই কী দিয়ে শুরু হয় **ncryptsec1** এবং আপনার পাসওয়ার্ড ছাড়া ব্যবহার করা যাবে না।.
|
||||
\n\n আপনি যদি আপনার পাসওয়ার্ড হারিয়ে ফেলেন, আপনি আপনার কী পুনরুদ্ধার করতে পারবেন না।.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## মূল ব্যাকআপ এবং নিরাপত্তা টিপস \n\n আপনার অ্যাকাউন্ট একটি গোপন কী দ্বারা সুরক্ষিত। মূলটি হল অক্ষরগুলির একটি দীর্ঘ ক্রম যা শুরু হয় **nsec1**. যে কেউ এই গোপন কী অ্যাক্সেস করতে পারে পোস্ট এবং আপনার পরিচয় পরিবর্তন করতে পারেন. \n\n- আপনি বিশ্বাস করেন না এমন কোনো ওয়েবসাইট বা সফ্টওয়্যারে আপনার গোপন কী **করবেন না**. \n- অ্যামেথিস্ট ডেভেলপাররা **কখনই** আপনার গোপন কী চাইবে না. \n- **করুন** অ্যাকাউন্ট পুনরুদ্ধারের জন্য আপনার গোপন কীটির একটি নিরাপদ ব্যাকআপ রাখুন৷. আমরা একটি পাসওয়ার্ড ম্যানেজার ব্যবহার করার পরামর্শ দিই।.</string>
|
||||
<string name="account_backup_tips3_md">অতিরিক্ত নিরাপত্তার জন্য, আপনি একটি পাসওয়ার্ড দিয়ে আপনার কী এনক্রিপ্ট করতে পারেন. এই কী দিয়ে শুরু হয় **ncryptsec1** এবং আপনার পাসওয়ার্ড ছাড়া ব্যবহার করা যাবে না।. \n\n আপনি যদি আপনার পাসওয়ার্ড হারিয়ে ফেলেন, আপনি আপনার কী পুনরুদ্ধার করতে পারবেন না।.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">এনক্রিপ্ট এবং আমার গোপন কী অনুলিপি</string>
|
||||
<string name="badge_award_image_for">%1$s -এর জন্য ব্যাজ পুরষ্কারের ছবি</string>
|
||||
<string name="badge_award_image">"ব্যাজ পুরস্কার চিত্র</string>
|
||||
@@ -963,9 +956,7 @@
|
||||
<string name="push_server_none_explainer">Push বিজ্ঞপ্তি নিষ্ক্রিয় করে</string>
|
||||
<string name="push_server_uses_app_explainer">অ্যাপ %1$s ব্যবহার করে</string>
|
||||
<string name="push_server_install_app">Push বিজ্ঞপ্তি সেটআপ</string>
|
||||
<string name="push_server_install_app_description"> পুশ নোটিফিকেশন পেতে, [Unified Push](https://unifiedpush.org/) সমর্থন করে এমন যেকোনো অ্যাপ ইনস্টল করুন, যেমন [Ntfy](https://ntfy.sh/)।
|
||||
ইনস্টল করার পরে, সেটিংসে আপনি যে অ্যাপটি ব্যবহার করতে চান তা নির্বাচন করুন।
|
||||
</string>
|
||||
<string name="push_server_install_app_description">পুশ নোটিফিকেশন পেতে, [Unified Push](https://unifiedpush.org/) সমর্থন করে এমন যেকোনো অ্যাপ ইনস্টল করুন, যেমন [Ntfy](https://ntfy.sh/)। ইনস্টল করার পরে, সেটিংসে আপনি যে অ্যাপটি ব্যবহার করতে চান তা নির্বাচন করুন।</string>
|
||||
<string name="thread_title">থ্রেড</string>
|
||||
<string name="send_the_seller_a_message">বিক্রেতাকে একটি বার্তা পাঠান</string>
|
||||
<string name="hi_there_is_this_still_available">হাই, এটা কি এখনও পাওয়া যায়?</string>
|
||||
@@ -2022,15 +2013,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">%1$s থেকে ইনভয়েস আনতে পারেনি: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">সংকুচিত ফাইলটি খোলা যায়নি</string>
|
||||
<string name="couldnt_find_nwc_wallets">ওয়ালেট পাওয়া যায়নি</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst কোনো ওয়ালেট অ্যাপ খুঁজে পায়নি যা Nostr Wallet Connect (NWC) সমর্থন করে।
|
||||
\n\nআপনি যা করতে পারেন:
|
||||
\n\t১. NWC সমর্থন যাচাই করুন: নিশ্চিত করুন যে আপনার পছন্দের ওয়ালেট অ্যাপ Nostr Wallet Connect-এর সাথে সামঞ্জস্যপূর্ণ।
|
||||
\n\t২. সংযোগ তৈরি করুন: আপনার ওয়ালেট অ্যাপে যান এবং একটি নতুন NWC সংযোগ তৈরি করুন।
|
||||
\n\t৩. Amethyst-এ লিঙ্ক করুন: আপনার ওয়ালেট সাধারণত তিনটি বিকল্প দেবে:
|
||||
\n\t\t৩.১ স্বয়ংক্রিয় লিঙ্ক: একটি বোতাম যা স্বয়ংক্রিয়ভাবে Amethyst খুলে সংযুক্ত করবে। যদি তাই হয়, সেই বোতামে ক্লিক করুন, Amethyst খুলুন এবং নতুন স্ক্রিনে সেভ চাপুন।
|
||||
\n\t\t৩.২ ম্যানুয়াল লিঙ্ক: একটি Connection URI যা কপি করে এই স্ক্রিনের পেস্ট আইকনে ক্লিক করে সরাসরি ইনপুট করতে পারবেন।
|
||||
\n\t\t৩.৩ QR কোড: ওয়ালেট একটি QR কোড তৈরি করে যা আপনি এই স্ক্রিনের QR কোড বোতাম থেকে পড়তে পারবেন।
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst কোনো ওয়ালেট অ্যাপ খুঁজে পায়নি যা Nostr Wallet Connect (NWC) সমর্থন করে। \n\nআপনি যা করতে পারেন: \n\t১. NWC সমর্থন যাচাই করুন: নিশ্চিত করুন যে আপনার পছন্দের ওয়ালেট অ্যাপ Nostr Wallet Connect-এর সাথে সামঞ্জস্যপূর্ণ। \n\t২. সংযোগ তৈরি করুন: আপনার ওয়ালেট অ্যাপে যান এবং একটি নতুন NWC সংযোগ তৈরি করুন। \n\t৩. Amethyst-এ লিঙ্ক করুন: আপনার ওয়ালেট সাধারণত তিনটি বিকল্প দেবে: \n\t\t৩.১ স্বয়ংক্রিয় লিঙ্ক: একটি বোতাম যা স্বয়ংক্রিয়ভাবে Amethyst খুলে সংযুক্ত করবে। যদি তাই হয়, সেই বোতামে ক্লিক করুন, Amethyst খুলুন এবং নতুন স্ক্রিনে সেভ চাপুন। \n\t\t৩.২ ম্যানুয়াল লিঙ্ক: একটি Connection URI যা কপি করে এই স্ক্রিনের পেস্ট আইকনে ক্লিক করে সরাসরি ইনপুট করতে পারবেন। \n\t\t৩.৩ QR কোড: ওয়ালেট একটি QR কোড তৈরি করে যা আপনি এই স্ক্রিনের QR কোড বোতাম থেকে পড়তে পারবেন।</string>
|
||||
<string name="create">তৈরি করুন</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">বিপদজনক এলাকা</string>
|
||||
@@ -2699,11 +2682,8 @@
|
||||
<string name="proxy_section">প্রক্সি Relay</string>
|
||||
<string name="proxy_section_explainer">অ্যাগ্রিগেটর relay যা অ্যাপটিকে আপনার ফিড ডাউনলোড করতে অবশ্যই ব্যবহার করতে হবে, যেমন filter.nostr.wine। এটি আউটবক্স মডেলকে প্রতিস্থাপন করে এবং অ্যাপটিকে শুধুমাত্র আপনার তালিকার relay গুলোতে সংযুক্ত করবে।</string>
|
||||
<string name="public_chat">সার্বজনীন আলাপ</string>
|
||||
<string name="public_chat_explainer">পাবলিক চ্যাটগুলো Nostr-এর সবার কাছে দৃশ্যমান এবং যে কেউ
|
||||
এতে অংশগ্রহণ করতে পারে। নির্দিষ্ট বিষয়ের চারপাশে উন্মুক্ত সম্প্রদায়ের জন্য এগুলো দুর্দান্ত।
|
||||
এর relay-তে পোস্ট মুছে পরিচালনা নিয়ন্ত্রণ করা যায়</string>
|
||||
<string name="public_chat_relays_explainer">এই গ্রুপটি হোস্ট করে এমন ১-৩ টি relay যোগ করুন।
|
||||
Nostr ক্লায়েন্টগুলো এই সেটিং ব্যবহার করে জানে যে কোথা থেকে বার্তা ডাউনলোড করতে হবে এবং আপনার বার্তা কোথায় পাঠাতে হবে।</string>
|
||||
<string name="public_chat_explainer">পাবলিক চ্যাটগুলো Nostr-এর সবার কাছে দৃশ্যমান এবং যে কেউ এতে অংশগ্রহণ করতে পারে। নির্দিষ্ট বিষয়ের চারপাশে উন্মুক্ত সম্প্রদায়ের জন্য এগুলো দুর্দান্ত। এর relay-তে পোস্ট মুছে পরিচালনা নিয়ন্ত্রণ করা যায়</string>
|
||||
<string name="public_chat_relays_explainer">এই গ্রুপটি হোস্ট করে এমন ১-৩ টি relay যোগ করুন। Nostr ক্লায়েন্টগুলো এই সেটিং ব্যবহার করে জানে যে কোথা থেকে বার্তা ডাউনলোড করতে হবে এবং আপনার বার্তা কোথায় পাঠাতে হবে।</string>
|
||||
<string name="public_chat_relays_title">Relay-গুলি</string>
|
||||
<string name="public_chat_title">পাবলিক চ্যাট মেটাডেটা</string>
|
||||
<string name="public_chats">পাবলিক চ্যাট</string>
|
||||
@@ -2728,10 +2708,7 @@
|
||||
<string name="read_only_user">শুধু-পড়ার ব্যবহারকারী</string>
|
||||
<string name="record_a_message_description">একটি বার্তা রেকর্ড করতে ক্লিক করুন এবং ধরে রাখুন</string>
|
||||
<string name="relay_chat">Relay চ্যাট</string>
|
||||
<string name="relay_chat_explainer">Relay চ্যাটগুলো হলো চ্যাট গ্রুপ যা তাদের হোম relay দ্বারা নিয়ন্ত্রিত হয়।
|
||||
এগুলো Nostr-এর সবার কাছে দৃশ্যমান এবং যে কেউ এতে অংশগ্রহণ করতে পারে।
|
||||
নির্দিষ্ট বিষয়ের চারপাশে উন্মুক্ত সম্প্রদায়ের জন্য এগুলো দুর্দান্ত। এই গ্রুপগুলোর কিছু ক্ষণস্থায়ী
|
||||
এবং সেজন্য চ্যাট বার্তাগুলো সময়ের সাথে মুছে যায়</string>
|
||||
<string name="relay_chat_explainer">Relay চ্যাটগুলো হলো চ্যাট গ্রুপ যা তাদের হোম relay দ্বারা নিয়ন্ত্রিত হয়। এগুলো Nostr-এর সবার কাছে দৃশ্যমান এবং যে কেউ এতে অংশগ্রহণ করতে পারে। নির্দিষ্ট বিষয়ের চারপাশে উন্মুক্ত সম্প্রদায়ের জন্য এগুলো দুর্দান্ত। এই গ্রুপগুলোর কিছু ক্ষণস্থায়ী এবং সেজন্য চ্যাট বার্তাগুলো সময়ের সাথে মুছে যায়</string>
|
||||
<string name="relay_chat_title">Relay চ্যাট</string>
|
||||
<string name="relay_management_tab_events">ইভেন্ট</string>
|
||||
<string name="relay_management_tab_ips">আইপি</string>
|
||||
|
||||
@@ -473,13 +473,8 @@
|
||||
<string name="mark_all_known_as_read">Označit všechny známé jako přečtené</string>
|
||||
<string name="mark_all_new_as_read">Označit všechny nové jako přečtené</string>
|
||||
<string name="mark_all_as_read">Označit všechny jako přečtené</string>
|
||||
<string name="account_backup_tips2_md"> ## Tipy pro zálohování klíčů a bezpečnost
|
||||
\n\nVaše konto je zabezpečeno tajným klíčem. Klíč je dlouhá posloupnost znaků začínající s **nsec1**. Kdo má přístup k tomuto tajnému klíči, může přispívat a měnit vaši identitu.
|
||||
\n\n- **Nedávejte** svůj tajný klíč na žádnou webovou stránku nebo do žádného softwaru, kterému nedůvěřujete.
|
||||
\n- Vývojáři Amethystu nikdy **nebudou** žádat o váš tajný klíč.
|
||||
\n- **Udržujte** bezpečnou zálohu vašeho tajného klíče pro obnovení účtu. Doporučujeme použití správce hesel.</string>
|
||||
<string name="account_backup_tips3_md"> Pro další zabezpečení můžete svůj klíč zašifrovat heslem. Tento klíč začíná s **ncryptsec1** a nelze ho použít bez vašeho hesla.
|
||||
\n\nPokud zapomenete heslo, nebudete moci obnovit svůj klíč.</string>
|
||||
<string name="account_backup_tips2_md">## Tipy pro zálohování klíčů a bezpečnost \n\nVaše konto je zabezpečeno tajným klíčem. Klíč je dlouhá posloupnost znaků začínající s **nsec1**. Kdo má přístup k tomuto tajnému klíči, může přispívat a měnit vaši identitu. \n\n- **Nedávejte** svůj tajný klíč na žádnou webovou stránku nebo do žádného softwaru, kterému nedůvěřujete. \n- Vývojáři Amethystu nikdy **nebudou** žádat o váš tajný klíč. \n- **Udržujte** bezpečnou zálohu vašeho tajného klíče pro obnovení účtu. Doporučujeme použití správce hesel.</string>
|
||||
<string name="account_backup_tips3_md">Pro další zabezpečení můžete svůj klíč zašifrovat heslem. Tento klíč začíná s **ncryptsec1** a nelze ho použít bez vašeho hesla. \n\nPokud zapomenete heslo, nebudete moci obnovit svůj klíč.</string>
|
||||
<string name="backup_keys_nudge_title">Zálohujte si klíče</string>
|
||||
<string name="backup_keys_nudge_body">Váš tajný klíč je jediný způsob, jak se k tomuto účtu dostat. Pokud ho ztratíte, nelze ho už nikdy obnovit. Uložte si ho někam do bezpečí.</string>
|
||||
<string name="backup_keys_nudge_backup_now">Zálohovat nyní</string>
|
||||
@@ -1598,9 +1593,7 @@
|
||||
<string name="push_server_none_explainer">Zakázat Push oznámení</string>
|
||||
<string name="push_server_uses_app_explainer">Použít aplikaci %1$s</string>
|
||||
<string name="push_server_install_app">Nastavení Push-oznámení</string>
|
||||
<string name="push_server_install_app_description"> Pro příjem Push-oznámení nainstalujte libovolnou aplikaci, která podporuje [Unified Push](https://unifiedpush.org/), jako je [Ntfy](https://ntfy.sh/).
|
||||
Po instalaci vyberte aplikaci kterou chcete používat v Nastavení.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Pro příjem Push-oznámení nainstalujte libovolnou aplikaci, která podporuje [Unified Push](https://unifiedpush.org/), jako je [Ntfy](https://ntfy.sh/). Po instalaci vyberte aplikaci kterou chcete používat v Nastavení.</string>
|
||||
<string name="thread_title">Vlákno</string>
|
||||
<string name="send_the_seller_a_message">Poslat prodejci zprávu</string>
|
||||
<string name="hi_there_is_this_still_available">Ahoj, je to stále k dispozici?</string>
|
||||
@@ -3393,14 +3386,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Nelze získat fakturu z %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Nepodařilo se otevřít komprimovaný soubor</string>
|
||||
<string name="couldnt_find_nwc_wallets">Peněženka nebyla nalezená</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst nenašel žádné aplikace peněženek, které podporují Nostr Wallet Connect (NWC).
|
||||
\n\nCo můžete udělat:
|
||||
\n\t1. Ověřte podporu NWC: Zkontrolujte, že vaše oblíbená peněženka podporuje Nostr Wallet Connect.
|
||||
\n\t2. Vytvořte připojení: Otevřete svou peněženku a vytvořte nové NWC připojení.
|
||||
\n\t3. Propojte s Amethyst: Vaše peněženka obvykle nabídne tři možnosti:
|
||||
\n\t\t3.1 Automatické propojení: Tlačítko pro automatické otevření a připojení k Amethyst. Klikněte na něj, otevřete Amethyst a uložte na nové obrazovce.
|
||||
\n\t\t3.2 Ruční propojení: URI připojení, které můžete zkopírovat a vložit přes ikonu vložení na této obrazovce.
|
||||
\n\t\t3.3 QR kód: Peněženka vytvoří QR kód, který můžete naskenovat pomocí tlačítka QR kódu na této obrazovce.</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst nenašel žádné aplikace peněženek, které podporují Nostr Wallet Connect (NWC). \n\nCo můžete udělat: \n\t1. Ověřte podporu NWC: Zkontrolujte, že vaše oblíbená peněženka podporuje Nostr Wallet Connect. \n\t2. Vytvořte připojení: Otevřete svou peněženku a vytvořte nové NWC připojení. \n\t3. Propojte s Amethyst: Vaše peněženka obvykle nabídne tři možnosti: \n\t\t3.1 Automatické propojení: Tlačítko pro automatické otevření a připojení k Amethyst. Klikněte na něj, otevřete Amethyst a uložte na nové obrazovce. \n\t\t3.2 Ruční propojení: URI připojení, které můžete zkopírovat a vložit přes ikonu vložení na této obrazovce. \n\t\t3.3 QR kód: Peněženka vytvoří QR kód, který můžete naskenovat pomocí tlačítka QR kódu na této obrazovce.</string>
|
||||
<string name="create">Vytvořit</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">Nebezpečná zóna</string>
|
||||
@@ -4611,11 +4597,8 @@
|
||||
<string name="proxy_section">Proxy přenašeče</string>
|
||||
<string name="proxy_section_explainer">Agregační přenašeče, které aplikace používá ke stahování vašich zdrojů, jako např. filter.nostr.wine</string>
|
||||
<string name="public_chat">Veřejný chat</string>
|
||||
<string name="public_chat_explainer">Veřejné konverzace jsou viditelné pro všechny na Nostru a kdokoli
|
||||
se na nich může podílet. Jsou skvělé pro otevřené komunity kolem konkrétních témat.
|
||||
Moderaci lze ovládat smazáním příspěvků na relé</string>
|
||||
<string name="public_chat_relays_explainer">Vložte mezi 1–3 relé, které hostí tuto skupinu.
|
||||
Klienti Nostr používají toto nastavení, aby věděli, kam stahovat zprávy a odesílat zprávy.</string>
|
||||
<string name="public_chat_explainer">Veřejné konverzace jsou viditelné pro všechny na Nostru a kdokoli se na nich může podílet. Jsou skvělé pro otevřené komunity kolem konkrétních témat. Moderaci lze ovládat smazáním příspěvků na relé</string>
|
||||
<string name="public_chat_relays_explainer">Vložte mezi 1–3 relé, které hostí tuto skupinu. Klienti Nostr používají toto nastavení, aby věděli, kam stahovat zprávy a odesílat zprávy.</string>
|
||||
<string name="public_chat_relays_title">Rele</string>
|
||||
<string name="public_chat_title">Metadata veřejného chatu</string>
|
||||
<string name="public_chats">Veřejné chaty</string>
|
||||
@@ -4684,10 +4667,7 @@
|
||||
<string name="relay_auth_search_keywords">auth autentizace relay podepsat ověřit nip-42 identita</string>
|
||||
<string name="relay_auth_settings_title">Autentizace relay</string>
|
||||
<string name="relay_chat">Relé chat</string>
|
||||
<string name="relay_chat_explainer">Relay chaty jsou chatové skupiny ovládané jejich domácí relé.
|
||||
Jsou viditelné pro všechny na Nostru a každý se jich může zúčastnit.
|
||||
Jsou skvělé pro otevřené komunity kolem konkrétních témat. Některé z těchto skupin jsou efemérní
|
||||
a proto zprávy časem mizí</string>
|
||||
<string name="relay_chat_explainer">Relay chaty jsou chatové skupiny ovládané jejich domácí relé. Jsou viditelné pro všechny na Nostru a každý se jich může zúčastnit. Jsou skvělé pro otevřené komunity kolem konkrétních témat. Některé z těchto skupin jsou efemérní a proto zprávy časem mizí</string>
|
||||
<string name="relay_chat_title">Relé chaty</string>
|
||||
<string name="relay_explain_account_data">Váš vlastní profil, nastavení a koncepty na vašich domovských relayích.</string>
|
||||
<string name="relay_explain_community_chats">Relaye, na které každá komunita publikuje své roviny.</string>
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
<string name="copy_user_id">Benutzer-ID kopieren</string>
|
||||
<string name="unblock_user">Benutzer freigeben</string>
|
||||
<string name="user_is_blocked_hidden">Dieser Nutzer ist blockiert/stummgeschaltet. Seine Beiträge sind ausgeblendet.</string>
|
||||
<string name="npub_hex_username">npub, Benutzername, Text </string>
|
||||
<string name="npub_hex_username">npub, Benutzername, Text</string>
|
||||
<string name="clear">Löschen</string>
|
||||
<string name="app_logo">App-Logo</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec.. oder npub..</string>
|
||||
@@ -463,13 +463,8 @@
|
||||
<string name="mark_all_known_as_read">Alle Kontakte als gelesen markieren</string>
|
||||
<string name="mark_all_new_as_read">Alle Unbekannten als gelesen markieren</string>
|
||||
<string name="mark_all_as_read">Alle als gelesen markieren</string>
|
||||
<string name="account_backup_tips2_md"> ## Tipps zur Schlüsselsicherheit
|
||||
\n\nDein Konto ist durch einen privaten Schlüssel gesichert. Der Schlüssel ist eine lange Zeichenfolge, die mit **nsec1** beginnt. Jeder, der Zugriff auf diesen privaten Schlüssel hat, kann in deinem Namen posten und dein Profil ändern.
|
||||
\n\n- Lege deinen privaten Schlüssel **nicht** auf einer Website oder in einer Software ab, der du nicht vertraust.
|
||||
\n- Die Entwickler von Amethyst werden dich **niemals** nach deinem privaten Schlüssel fragen.
|
||||
\n- **Bewahre** eine sichere Kopie deines privaten Schlüssels zur Kontowiederherstellung auf. Wir empfehlen die Verwendung eines Passwort-Managers.</string>
|
||||
<string name="account_backup_tips3_md"> Für zusätzliche Sicherheit kannst du deinen Schlüssel mit einem Passwort verschlüsseln. Dieser Schlüssel beginnt mit **ncryptsec1** und kann ohne dein Passwort nicht verwendet werden.
|
||||
\n\nWenn du dein Passwort verlierst, kannst du deinen Schlüssel nicht wiederherstellen.</string>
|
||||
<string name="account_backup_tips2_md">## Tipps zur Schlüsselsicherheit \n\nDein Konto ist durch einen privaten Schlüssel gesichert. Der Schlüssel ist eine lange Zeichenfolge, die mit **nsec1** beginnt. Jeder, der Zugriff auf diesen privaten Schlüssel hat, kann in deinem Namen posten und dein Profil ändern. \n\n- Lege deinen privaten Schlüssel **nicht** auf einer Website oder in einer Software ab, der du nicht vertraust. \n- Die Entwickler von Amethyst werden dich **niemals** nach deinem privaten Schlüssel fragen. \n- **Bewahre** eine sichere Kopie deines privaten Schlüssels zur Kontowiederherstellung auf. Wir empfehlen die Verwendung eines Passwort-Managers.</string>
|
||||
<string name="account_backup_tips3_md">Für zusätzliche Sicherheit kannst du deinen Schlüssel mit einem Passwort verschlüsseln. Dieser Schlüssel beginnt mit **ncryptsec1** und kann ohne dein Passwort nicht verwendet werden. \n\nWenn du dein Passwort verlierst, kannst du deinen Schlüssel nicht wiederherstellen.</string>
|
||||
<string name="backup_keys_nudge_title">Sichere deine Schlüssel</string>
|
||||
<string name="backup_keys_nudge_body">Dein geheimer Schlüssel ist der einzige Weg zu diesem Konto. Wenn du ihn verlierst, kann er nie wiederhergestellt werden. Speichere ihn jetzt an einem sicheren Ort.</string>
|
||||
<string name="backup_keys_nudge_backup_now">Jetzt sichern</string>
|
||||
@@ -1584,9 +1579,7 @@
|
||||
<string name="push_server_none_explainer">Push-Benachrichtigungen deaktivieren</string>
|
||||
<string name="push_server_uses_app_explainer">Verwendet die App %1$s</string>
|
||||
<string name="push_server_install_app">Push-Benachrichtigungen einrichten</string>
|
||||
<string name="push_server_install_app_description"> Um Push-Benachrichtigungen zu erhalten, installiere eine App, die [Unified Push](https://unifiedpush.org/) unterstützt, wie zum Beispiel [Ntfy](https://ntfy.sh/).
|
||||
Nach der Installation wähle in den Einstellungen die App aus, die du verwenden möchtest.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Um Push-Benachrichtigungen zu erhalten, installiere eine App, die [Unified Push](https://unifiedpush.org/) unterstützt, wie zum Beispiel [Ntfy](https://ntfy.sh/). Nach der Installation wähle in den Einstellungen die App aus, die du verwenden möchtest.</string>
|
||||
<string name="thread_title">Faden</string>
|
||||
<string name="send_the_seller_a_message">Dem Verkäufer eine Nachricht senden</string>
|
||||
<string name="hi_there_is_this_still_available">Hallo, ist das noch verfügbar?</string>
|
||||
@@ -3323,14 +3316,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Rechnung konnte nicht von %1$s abgerufen werden: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Konnte die komprimierte Datei nicht öffnen</string>
|
||||
<string name="couldnt_find_nwc_wallets">Wallet nicht gefunden</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst konnte keine Wallet-Apps finden, die Nostr Wallet Connect (NWC) unterstützen.
|
||||
\n\nWas du tun kannst:
|
||||
\n\t1. NWC-Unterstützung überprüfen: Stelle sicher, dass deine bevorzugte Wallet-App mit Nostr Wallet Connect kompatibel ist.
|
||||
\n\t2. Verbindung erstellen: Öffne deine Wallet-App und erstelle eine neue NWC-Verbindung.
|
||||
\n\t3. Mit Amethyst verknüpfen: Deine Wallet bietet normalerweise drei Optionen:
|
||||
\n\t\t3.1 Automatische Verknüpfung: Eine Schaltfläche zum automatischen Öffnen und Verbinden mit Amethyst. Klicke darauf, öffne Amethyst und speichere auf dem neuen Bildschirm.
|
||||
\n\t\t3.2 Manuelle Verknüpfung: Eine Verbindungs-URI, die du kopieren und über das Einfügesymbol auf diesem Bildschirm einfügen kannst.
|
||||
\n\t\t3.3 QR-Code: Die Wallet erstellt einen QR-Code, den du über die QR-Schaltfläche auf diesem Bildschirm scannen kannst.</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst konnte keine Wallet-Apps finden, die Nostr Wallet Connect (NWC) unterstützen. \n\nWas du tun kannst: \n\t1. NWC-Unterstützung überprüfen: Stelle sicher, dass deine bevorzugte Wallet-App mit Nostr Wallet Connect kompatibel ist. \n\t2. Verbindung erstellen: Öffne deine Wallet-App und erstelle eine neue NWC-Verbindung. \n\t3. Mit Amethyst verknüpfen: Deine Wallet bietet normalerweise drei Optionen: \n\t\t3.1 Automatische Verknüpfung: Eine Schaltfläche zum automatischen Öffnen und Verbinden mit Amethyst. Klicke darauf, öffne Amethyst und speichere auf dem neuen Bildschirm. \n\t\t3.2 Manuelle Verknüpfung: Eine Verbindungs-URI, die du kopieren und über das Einfügesymbol auf diesem Bildschirm einfügen kannst. \n\t\t3.3 QR-Code: Die Wallet erstellt einen QR-Code, den du über die QR-Schaltfläche auf diesem Bildschirm scannen kannst.</string>
|
||||
<string name="create">Erstellen</string>
|
||||
<string name="d">t</string>
|
||||
<string name="danger_zone">Gefahrenzone</string>
|
||||
@@ -4427,11 +4413,8 @@
|
||||
<string name="proxy_section">Proxy-Relays</string>
|
||||
<string name="proxy_section_explainer">Aggregator-Relays wie filter.nostr.wine, von denen die App deine Feeds herunterlädt</string>
|
||||
<string name="public_chat">Öffentlicher Chat</string>
|
||||
<string name="public_chat_explainer">Öffentliche Chats sind für jeden auf Nostr sichtbar und jeder
|
||||
kann daran teilnehmen. Sie eignen sich hervorragend für offene Gemeinschaften rund um bestimmte Themen.
|
||||
Moderation kann durch Löschen von Beiträgen auf den Relays gesteuert werden</string>
|
||||
<string name="public_chat_relays_explainer">Füge zwischen 1–3 Relays ein, die diese Gruppe beherbergen.
|
||||
Nostr Clients verwenden diese Einstellung, um zu wissen, woher sie Nachrichten herunterladen und an welche gesendet werden sollen.</string>
|
||||
<string name="public_chat_explainer">Öffentliche Chats sind für jeden auf Nostr sichtbar und jeder kann daran teilnehmen. Sie eignen sich hervorragend für offene Gemeinschaften rund um bestimmte Themen. Moderation kann durch Löschen von Beiträgen auf den Relays gesteuert werden</string>
|
||||
<string name="public_chat_relays_explainer">Füge zwischen 1–3 Relays ein, die diese Gruppe beherbergen. Nostr Clients verwenden diese Einstellung, um zu wissen, woher sie Nachrichten herunterladen und an welche gesendet werden sollen.</string>
|
||||
<string name="public_chat_relays_title">Relays</string>
|
||||
<string name="public_chat_title">Öffentliche Chat Metadaten</string>
|
||||
<string name="public_chats">Öffentliche Chats</string>
|
||||
@@ -4496,10 +4479,7 @@
|
||||
<string name="relay_auth_search_keywords">auth authentifizierung relay signieren verifizieren nip-42 identität</string>
|
||||
<string name="relay_auth_settings_title">Relay-Authentifizierung</string>
|
||||
<string name="relay_chat">Relay-Chat</string>
|
||||
<string name="relay_chat_explainer">Relay-Chats sind Chatgruppen, die von ihrem Home-Relay gesteuert werden.
|
||||
Sie sind für jeden auf Nostr sichtbar und jeder kann an ihnen teilnehmen.
|
||||
Sie eignen sich hervorragend für offene Communities rund um bestimmte Themen. Einige dieser Gruppen sind kurzsichtig
|
||||
und daher verschwinden Chat-Nachrichten im Laufe der Zeit</string>
|
||||
<string name="relay_chat_explainer">Relay-Chats sind Chatgruppen, die von ihrem Home-Relay gesteuert werden. Sie sind für jeden auf Nostr sichtbar und jeder kann an ihnen teilnehmen. Sie eignen sich hervorragend für offene Communities rund um bestimmte Themen. Einige dieser Gruppen sind kurzsichtig und daher verschwinden Chat-Nachrichten im Laufe der Zeit</string>
|
||||
<string name="relay_chat_title">Relay-Chats</string>
|
||||
<string name="relay_explain_account_data">Dein eigenes Profil, deine Einstellungen und Entwürfe auf deinen Heim-Relays.</string>
|
||||
<string name="relay_explain_community_chats">Die Relays, auf denen jede Community ihre Planes veröffentlicht.</string>
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
<string name="copy_user_id">Benutzer-ID kopieren</string>
|
||||
<string name="unblock_user">Benutzer freigeben</string>
|
||||
<string name="user_is_blocked_hidden">Dieser Nutzer ist blockiert/stummgeschaltet. Seine Beiträge sind ausgeblendet.</string>
|
||||
<string name="npub_hex_username">Npub, Hex, Benutzername </string>
|
||||
<string name="npub_hex_username">Npub, Hex, Benutzername</string>
|
||||
<string name="clear">Löschen</string>
|
||||
<string name="app_logo">App-Logo</string>
|
||||
<string name="nsec_npub_hex_private_key">Nsec / Npub / Hex-Privatschlüssel</string>
|
||||
@@ -219,9 +219,7 @@
|
||||
<string name="show_password">Passwort anzeigen</string>
|
||||
<string name="i_accept_the">Ich akzeptiere die </string>
|
||||
<string name="terms_of_use">Nutzungsbedingungen</string>
|
||||
<string name="acceptance_of_terms_is_required">Die Akzept
|
||||
|
||||
anz der Bedingungen ist erforderlich</string>
|
||||
<string name="acceptance_of_terms_is_required">Die Akzept anz der Bedingungen ist erforderlich</string>
|
||||
<string name="login">Anmeldung</string>
|
||||
<string name="sign_up">Anmelden</string>
|
||||
<string name="create_account">Konto erstellen</string>
|
||||
@@ -261,13 +259,8 @@ anz der Bedingungen ist erforderlich</string>
|
||||
<string name="mark_all_known_as_read">Alle als bekannt markieren</string>
|
||||
<string name="mark_all_new_as_read">Alle als neu markieren</string>
|
||||
<string name="mark_all_as_read">Alle als gelesen markieren</string>
|
||||
<string name="account_backup_tips2_md"> ## Schlüsselsicherheits-Tipps
|
||||
\n\nIhr Konto ist durch einen geheimen Schlüssel gesichert. Der Schlüssel ist eine lange Zeichenfolge, die mit **nsec1** beginnt. Jeder, der Zugriff auf diesen geheimen Schlüssel hat, kann Ihre Identität posten und ändern.
|
||||
\n\n- Legen Sie Ihren geheimen Schlüssel **nicht** auf eine Website oder in eine Software, der Sie nicht vertrauen.
|
||||
\n- Die Entwickler von Amethyst werden Sie **niemals** nach Ihrem geheimen Schlüssel fragen.
|
||||
\n- **Bewahren Sie** eine sichere Sicherung Ihres geheimen Schlüssels zur Kontowiederherstellung auf. Wir empfehlen die Verwendung eines Passwort-Managers.</string>
|
||||
<string name="account_backup_tips3_md"> Für zusätzliche Sicherheit können Sie Ihren Schlüssel mit einem Passwort verschlüsseln. Dieser Schlüssel beginnt mit **ncryptsec1** und kann ohne Ihr Passwort nicht verwendet werden.
|
||||
\n\nWenn Sie Ihr Passwort verlieren, können Sie Ihren Schlüssel nicht wiederherstellen.</string>
|
||||
<string name="account_backup_tips2_md">## Schlüsselsicherheits-Tipps \n\nIhr Konto ist durch einen geheimen Schlüssel gesichert. Der Schlüssel ist eine lange Zeichenfolge, die mit **nsec1** beginnt. Jeder, der Zugriff auf diesen geheimen Schlüssel hat, kann Ihre Identität posten und ändern. \n\n- Legen Sie Ihren geheimen Schlüssel **nicht** auf eine Website oder in eine Software, der Sie nicht vertrauen. \n- Die Entwickler von Amethyst werden Sie **niemals** nach Ihrem geheimen Schlüssel fragen. \n- **Bewahren Sie** eine sichere Sicherung Ihres geheimen Schlüssels zur Kontowiederherstellung auf. Wir empfehlen die Verwendung eines Passwort-Managers.</string>
|
||||
<string name="account_backup_tips3_md">Für zusätzliche Sicherheit können Sie Ihren Schlüssel mit einem Passwort verschlüsseln. Dieser Schlüssel beginnt mit **ncryptsec1** und kann ohne Ihr Passwort nicht verwendet werden. \n\nWenn Sie Ihr Passwort verlieren, können Sie Ihren Schlüssel nicht wiederherstellen.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Verschlüsseln und kopieren Sie meinen geheimen Schlüssel</string>
|
||||
<string name="badge_award_image_for">Auszeichnungsbild für %1$s</string>
|
||||
<string name="badge_award_image">Auszeichnungsbild</string>
|
||||
@@ -960,9 +953,7 @@ anz der Bedingungen ist erforderlich</string>
|
||||
<string name="push_server_none_explainer">Push-Benachrichtigungen deaktivieren</string>
|
||||
<string name="push_server_uses_app_explainer">Verwendet die App %1$s</string>
|
||||
<string name="push_server_install_app">Push-Benachrichtigungen einrichten</string>
|
||||
<string name="push_server_install_app_description"> Um Push-Benachrichtigungen zu erhalten, installieren Sie eine App, die [Unified Push](https://unifiedpush.org/) unterstützt, wie zum Beispiel [Ntfy](https://ntfy.sh/).
|
||||
Nach der Installation wählen Sie die App aus, die Sie in den Einstellungen verwenden möchten.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Um Push-Benachrichtigungen zu erhalten, installieren Sie eine App, die [Unified Push](https://unifiedpush.org/) unterstützt, wie zum Beispiel [Ntfy](https://ntfy.sh/). Nach der Installation wählen Sie die App aus, die Sie in den Einstellungen verwenden möchten.</string>
|
||||
<string name="thread_title">Faden</string>
|
||||
<string name="send_the_seller_a_message">Dem Verkäufer eine Nachricht senden</string>
|
||||
<string name="hi_there_is_this_still_available">Hallo, ist das noch verfügbar?</string>
|
||||
@@ -2064,14 +2055,7 @@ anz der Bedingungen ist erforderlich</string>
|
||||
<string name="could_not_fetch_invoice_from_details">Rechnung konnte nicht von %1$s abgerufen werden: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Konnte die komprimierte Datei nicht öffnen</string>
|
||||
<string name="couldnt_find_nwc_wallets">Wallet nicht gefunden</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst konnte keine Wallet-Apps finden, die Nostr Wallet Connect (NWC) unterstützen.
|
||||
\n\nWas du tun kannst:
|
||||
\n\t1. NWC-Unterstützung überprüfen: Stelle sicher, dass deine bevorzugte Wallet-App mit Nostr Wallet Connect kompatibel ist.
|
||||
\n\t2. Verbindung erstellen: Öffne deine Wallet-App und erstelle eine neue NWC-Verbindung.
|
||||
\n\t3. Mit Amethyst verknüpfen: Deine Wallet bietet normalerweise drei Optionen:
|
||||
\n\t\t3.1 Automatische Verknüpfung: Eine Schaltfläche zum automatischen Öffnen und Verbinden mit Amethyst. Klicke darauf, öffne Amethyst und speichere auf dem neuen Bildschirm.
|
||||
\n\t\t3.2 Manuelle Verknüpfung: Eine Verbindungs-URI, die du kopieren und über das Einfügesymbol auf diesem Bildschirm einfügen kannst.
|
||||
\n\t\t3.3 QR-Code: Die Wallet erstellt einen QR-Code, den du über die QR-Schaltfläche auf diesem Bildschirm scannen kannst.</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst konnte keine Wallet-Apps finden, die Nostr Wallet Connect (NWC) unterstützen. \n\nWas du tun kannst: \n\t1. NWC-Unterstützung überprüfen: Stelle sicher, dass deine bevorzugte Wallet-App mit Nostr Wallet Connect kompatibel ist. \n\t2. Verbindung erstellen: Öffne deine Wallet-App und erstelle eine neue NWC-Verbindung. \n\t3. Mit Amethyst verknüpfen: Deine Wallet bietet normalerweise drei Optionen: \n\t\t3.1 Automatische Verknüpfung: Eine Schaltfläche zum automatischen Öffnen und Verbinden mit Amethyst. Klicke darauf, öffne Amethyst und speichere auf dem neuen Bildschirm. \n\t\t3.2 Manuelle Verknüpfung: Eine Verbindungs-URI, die du kopieren und über das Einfügesymbol auf diesem Bildschirm einfügen kannst. \n\t\t3.3 QR-Code: Die Wallet erstellt einen QR-Code, den du über die QR-Schaltfläche auf diesem Bildschirm scannen kannst.</string>
|
||||
<string name="create">Erstellen</string>
|
||||
<string name="d">t</string>
|
||||
<string name="danger_zone">Gefahrenzone</string>
|
||||
@@ -2274,9 +2258,7 @@ anz der Bedingungen ist erforderlich</string>
|
||||
<string name="http_status_508">Schleife erkannt - Der Server erkennt eine Endlosschleife, während er die Anfrage bearbeitet</string>
|
||||
<string name="http_status_511">Netzwerk-Authentifizierung erforderlich - Der Client muss authentifiziert werden, um auf das Netzwerk zuzugreifen</string>
|
||||
<string name="illegal_behavior">Illegales Verhalten</string>
|
||||
<string name="image_saved_to_the_gallery">Bild in der Gal
|
||||
|
||||
erie gespeichert</string>
|
||||
<string name="image_saved_to_the_gallery">Bild in der Gal erie gespeichert</string>
|
||||
<string name="impersonation">Vortäuschung</string>
|
||||
<string name="import_follows_search_keywords">Kontakte, folgen, Folgeliste, importieren</string>
|
||||
<string name="inbox_relays_title">Eingehende Relays</string>
|
||||
@@ -2777,11 +2759,8 @@ erie gespeichert</string>
|
||||
<string name="proxy_section">Proxy-Relays</string>
|
||||
<string name="proxy_section_explainer">Aggregator-Relays wie filter.nostr.wine, von denen die App deine Feeds herunterlädt</string>
|
||||
<string name="public_chat">Öffentlicher Chat</string>
|
||||
<string name="public_chat_explainer">Öffentliche Chats sind für jeden auf Nostr sichtbar und jeder
|
||||
kann daran teilnehmen. Sie eignen sich hervorragend für offene Gemeinschaften rund um bestimmte Themen.
|
||||
Moderation kann durch Löschen von Beiträgen auf den Relais gesteuert werden</string>
|
||||
<string name="public_chat_relays_explainer">Fügen Sie zwischen 1–3 Relais ein, die diese Gruppe beherbergen.
|
||||
Nostr Clients verwenden diese Einstellung, um zu wissen, woher sie Nachrichten herunterladen und an welche gesendet werden sollen.</string>
|
||||
<string name="public_chat_explainer">Öffentliche Chats sind für jeden auf Nostr sichtbar und jeder kann daran teilnehmen. Sie eignen sich hervorragend für offene Gemeinschaften rund um bestimmte Themen. Moderation kann durch Löschen von Beiträgen auf den Relais gesteuert werden</string>
|
||||
<string name="public_chat_relays_explainer">Fügen Sie zwischen 1–3 Relais ein, die diese Gruppe beherbergen. Nostr Clients verwenden diese Einstellung, um zu wissen, woher sie Nachrichten herunterladen und an welche gesendet werden sollen.</string>
|
||||
<string name="public_chat_relays_title">Relais</string>
|
||||
<string name="public_chat_title">Öffentliche Chat Metadaten</string>
|
||||
<string name="public_chats">Öffentliche Chats</string>
|
||||
@@ -2808,10 +2787,7 @@ erie gespeichert</string>
|
||||
<string name="read_only_user">Nur-Lese-Benutzer</string>
|
||||
<string name="record_a_message_description">Zum Aufnehmen einer Nachricht gedrückt halten</string>
|
||||
<string name="relay_chat">Relay-Chat</string>
|
||||
<string name="relay_chat_explainer">Relaischats sind Chatgruppen, die von ihrem Home-Relais gesteuert werden.
|
||||
Sie sind für jeden auf Nostr sichtbar und jeder kann an ihnen teilnehmen.
|
||||
Sie eignen sich hervorragend für offene Communities rund um bestimmte Themen. Einige dieser Gruppen sind kurzsichtig
|
||||
und daher verschwinden Chat-Nachrichten im Laufe der Zeit</string>
|
||||
<string name="relay_chat_explainer">Relaischats sind Chatgruppen, die von ihrem Home-Relais gesteuert werden. Sie sind für jeden auf Nostr sichtbar und jeder kann an ihnen teilnehmen. Sie eignen sich hervorragend für offene Communities rund um bestimmte Themen. Einige dieser Gruppen sind kurzsichtig und daher verschwinden Chat-Nachrichten im Laufe der Zeit</string>
|
||||
<string name="relay_chat_title">Relay-Chats</string>
|
||||
<string name="relay_management_tab_events">Ereignisse</string>
|
||||
<string name="relay_management_tab_ips">IPs</string>
|
||||
|
||||
@@ -271,15 +271,8 @@
|
||||
<string name="mark_all_known_as_read">Σήμανση όλων των γνωστοποιήσεων ως αναγνωσμένων</string>
|
||||
<string name="mark_all_new_as_read">Σήμανση όλων ως αναγνωσμένων</string>
|
||||
<string name="mark_all_as_read">Σήμανση όλων ως αναγνωσμένα</string>
|
||||
<string name="account_backup_tips2_md"> ## Συμβουλές ασφαλείας και δημιουργίας αντιγράφων ασφαλείας κλειδιού
|
||||
\n\nΟ λογαριασμός σου ασφαλίζεται με ένα μυστικό κλειδί. Το κλειδί είναι μια μακρά ακολουθία χαρακτήρων που ξεκινά με **nsec1**. Όποιος έχει πρόσβαση σε αυτό το μυστικό κλειδί μπορεί να δημοσιεύει και να αλλάζει την ταυτότητά σου.
|
||||
\n\n- **Μην** βάζεις το μυστικό σου κλειδί σε κανέναν ιστότοπο ή λογισμικό που δεν εμπιστεύεσαι.
|
||||
\n- Οι προγραμματιστές του Amethyst **δεν** θα ζητήσουν ποτέ το μυστικό σου κλειδί.
|
||||
\n- **Διατήρησε** ένα ασφαλές αντίγραφο ασφαλείας του μυστικού σου κλειδιού για ανάκτηση λογαριασμού. Συνιστούμε τη χρήση διαχειριστή κωδικών πρόσβασης.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Για πρόσθετη ασφάλεια, μπορείς να κρυπτογραφήσεις το κλειδί σου με κωδικό πρόσβασης. Αυτό το κλειδί ξεκινά με **ncryptsec1** και δεν μπορεί να χρησιμοποιηθεί χωρίς τον κωδικό σου.
|
||||
\n\nΑν χάσεις τον κωδικό σου, δεν θα μπορείς να ανακτήσεις το κλειδί σου.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Συμβουλές ασφαλείας και δημιουργίας αντιγράφων ασφαλείας κλειδιού \n\nΟ λογαριασμός σου ασφαλίζεται με ένα μυστικό κλειδί. Το κλειδί είναι μια μακρά ακολουθία χαρακτήρων που ξεκινά με **nsec1**. Όποιος έχει πρόσβαση σε αυτό το μυστικό κλειδί μπορεί να δημοσιεύει και να αλλάζει την ταυτότητά σου. \n\n- **Μην** βάζεις το μυστικό σου κλειδί σε κανέναν ιστότοπο ή λογισμικό που δεν εμπιστεύεσαι. \n- Οι προγραμματιστές του Amethyst **δεν** θα ζητήσουν ποτέ το μυστικό σου κλειδί. \n- **Διατήρησε** ένα ασφαλές αντίγραφο ασφαλείας του μυστικού σου κλειδιού για ανάκτηση λογαριασμού. Συνιστούμε τη χρήση διαχειριστή κωδικών πρόσβασης.</string>
|
||||
<string name="account_backup_tips3_md">Για πρόσθετη ασφάλεια, μπορείς να κρυπτογραφήσεις το κλειδί σου με κωδικό πρόσβασης. Αυτό το κλειδί ξεκινά με **ncryptsec1** και δεν μπορεί να χρησιμοποιηθεί χωρίς τον κωδικό σου. \n\nΑν χάσεις τον κωδικό σου, δεν θα μπορείς να ανακτήσεις το κλειδί σου.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Κρυπτογράφηση και αντιγραφή του μυστικού μου κλειδιού</string>
|
||||
<string name="badge_award_image_for">Σήμα βράβευσης για %1$s</string>
|
||||
<string name="badge_award_image">"Εικόνα βραβείου παρασήμου</string>
|
||||
@@ -934,8 +927,7 @@
|
||||
<string name="moderators">Συντονιστές</string>
|
||||
<string name="login_with_external_signer">Σύνδεση με Amber</string>
|
||||
<string name="status_update">Ενημέρωση κατάστασης</string>
|
||||
<string name="poll_zap_value_min_max_explainer">Η ψηφοφορία σε μια δημοσίευση Δημοσκόπησης γίνεται με zaps. Τα zaps είναι μικροπληρωμές σε satoshi (sats). Τα sats είναι υποδιαίρεση του Bitcoin. Κάθε Bitcoin έχει 100.000.000 sats.
|
||||
Η επιλογή με τα περισσότερα zaps (δηλαδή τα περισσότερα sats) είναι η επικρατέστερη. Μπορείτε να ορίσετε ένα ελάχιστο ποσό zap για να αποφύγετε την ψήφο spammers αλλά και ένα μέγιστο ποσό ώστε να αποφύγετε μεγάλους zappers (χρήστες που στέλνουν zaps) που επιθυμούν να χειραγωγήσουν την ψηφοφορία. Χρησιμοποιήστε το ίδιο ποσό και στα δύο πεδία για να βεβαιωθείτε ότι κάθε ψήφος αποτιμάται το ίδιο. Ή αφήστε τα πεδία κενά για να αποδεχτείτε οποιοδήποτε ποσό.</string>
|
||||
<string name="poll_zap_value_min_max_explainer">Η ψηφοφορία σε μια δημοσίευση Δημοσκόπησης γίνεται με zaps. Τα zaps είναι μικροπληρωμές σε satoshi (sats). Τα sats είναι υποδιαίρεση του Bitcoin. Κάθε Bitcoin έχει 100.000.000 sats. Η επιλογή με τα περισσότερα zaps (δηλαδή τα περισσότερα sats) είναι η επικρατέστερη. Μπορείτε να ορίσετε ένα ελάχιστο ποσό zap για να αποφύγετε την ψήφο spammers αλλά και ένα μέγιστο ποσό ώστε να αποφύγετε μεγάλους zappers (χρήστες που στέλνουν zaps) που επιθυμούν να χειραγωγήσουν την ψηφοφορία. Χρησιμοποιήστε το ίδιο ποσό και στα δύο πεδία για να βεβαιωθείτε ότι κάθε ψήφος αποτιμάται το ίδιο. Ή αφήστε τα πεδία κενά για να αποδεχτείτε οποιοδήποτε ποσό.</string>
|
||||
<string name="error_dialog_talk_to_user">Μήνυμα στον Χρήστη</string>
|
||||
<string name="error_dialog_talk_to_user_name">Μήνυμα σε %1$s</string>
|
||||
<string name="error_dialog_button_ok">ΟΚ</string>
|
||||
@@ -963,9 +955,7 @@
|
||||
<string name="push_server_none_explainer">Απενεργοποίηση Ειδοποιήσεων Push</string>
|
||||
<string name="push_server_uses_app_explainer">Χρήση εφαρμογής %1$s</string>
|
||||
<string name="push_server_install_app">Ρυθμίσεις Ειδοποιήσεων Push</string>
|
||||
<string name="push_server_install_app_description"> Για να λαμβάνετε ειδοποιήσεις Push, εγκαταστήστε οποιαδήποτε εφαρμογή τις υποστηρίζει [Unified Push](https://unifiedpush.org/), όπως πχ το [Ntfy](https://ntfy.sh/).
|
||||
Μετά την εγκατάσταση, επιλέξτε την εφαρμογή που θέλετε να χρησιμοποιήσετε από τις Ρυθμίσεις.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Για να λαμβάνετε ειδοποιήσεις Push, εγκαταστήστε οποιαδήποτε εφαρμογή τις υποστηρίζει [Unified Push](https://unifiedpush.org/), όπως πχ το [Ntfy](https://ntfy.sh/). Μετά την εγκατάσταση, επιλέξτε την εφαρμογή που θέλετε να χρησιμοποιήσετε από τις Ρυθμίσεις.</string>
|
||||
<string name="thread_title">Νήμα</string>
|
||||
<string name="send_the_seller_a_message">Στείλτε μήνυμα στον πωλητή</string>
|
||||
<string name="hi_there_is_this_still_available">Γεια σου, είναι ακόμα διαθέσιμο;</string>
|
||||
@@ -2008,15 +1998,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Δεν ήταν δυνατή η λήψη τιμολογίου από %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Δεν ήταν δυνατό το άνοιγμα του συμπιεσμένου αρχείου</string>
|
||||
<string name="couldnt_find_nwc_wallets">Το πορτοφόλι δεν βρέθηκε</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Το Amethyst δεν βρήκε εφαρμογές πορτοφολιού που υποστηρίζουν Nostr Wallet Connect (NWC).
|
||||
\n\nΤι μπορείτε να κάνετε:
|
||||
\n\t1. Επαλήθευση υποστήριξης NWC: Βεβαιωθείτε ότι η προτιμώμενη εφαρμογή πορτοφολιού σας είναι συμβατή με Nostr Wallet Connect.
|
||||
\n\t2. Δημιουργία σύνδεσης: Μεταβείτε στην εφαρμογή πορτοφολιού σας και δημιουργήστε μια νέα σύνδεση NWC.
|
||||
\n\t3. Σύνδεση με το Amethyst: Το πορτοφόλι σας συνήθως θα σας δώσει τρεις επιλογές:
|
||||
\n\t\t3.1 Αυτόματη σύνδεση: Ένα κουμπί για αυτόματο άνοιγμα και σύνδεση με το Amethyst. Αν ναι, κάντε κλικ σε αυτό το κουμπί, ανοίξτε το Amethyst και πατήστε αποθήκευση στη νέα οθόνη.
|
||||
\n\t\t3.2 Χειροκίνητη σύνδεση: Ένα URI σύνδεσης που μπορείτε να αντιγράψετε και να κάνετε κλικ στο εικονίδιο επικόλλησης σε αυτή την οθόνη για απευθείας εισαγωγή.
|
||||
\n\t\t3.3 Κωδικός QR: Το πορτοφόλι δημιουργεί κωδικό QR τον οποίο μπορείτε να σαρώσετε από το κουμπί κωδικού QR σε αυτή την οθόνη.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Το Amethyst δεν βρήκε εφαρμογές πορτοφολιού που υποστηρίζουν Nostr Wallet Connect (NWC). \n\nΤι μπορείτε να κάνετε: \n\t1. Επαλήθευση υποστήριξης NWC: Βεβαιωθείτε ότι η προτιμώμενη εφαρμογή πορτοφολιού σας είναι συμβατή με Nostr Wallet Connect. \n\t2. Δημιουργία σύνδεσης: Μεταβείτε στην εφαρμογή πορτοφολιού σας και δημιουργήστε μια νέα σύνδεση NWC. \n\t3. Σύνδεση με το Amethyst: Το πορτοφόλι σας συνήθως θα σας δώσει τρεις επιλογές: \n\t\t3.1 Αυτόματη σύνδεση: Ένα κουμπί για αυτόματο άνοιγμα και σύνδεση με το Amethyst. Αν ναι, κάντε κλικ σε αυτό το κουμπί, ανοίξτε το Amethyst και πατήστε αποθήκευση στη νέα οθόνη. \n\t\t3.2 Χειροκίνητη σύνδεση: Ένα URI σύνδεσης που μπορείτε να αντιγράψετε και να κάνετε κλικ στο εικονίδιο επικόλλησης σε αυτή την οθόνη για απευθείας εισαγωγή. \n\t\t3.3 Κωδικός QR: Το πορτοφόλι δημιουργεί κωδικό QR τον οποίο μπορείτε να σαρώσετε από το κουμπί κωδικού QR σε αυτή την οθόνη.</string>
|
||||
<string name="create">Δημιουργία</string>
|
||||
<string name="d">η</string>
|
||||
<string name="danger_zone">Επικίνδυνη ζώνη</string>
|
||||
@@ -2653,11 +2635,8 @@
|
||||
<string name="proxy_section">Relay Διαμεσολαβητή</string>
|
||||
<string name="proxy_section_explainer">Relay συγκεντρωτές που η εφαρμογή πρέπει να χρησιμοποιεί για να κατεβάσει τις τροφοδοσίες σας, όπως filter.nostr.wine. Αυτό αντικαθιστά το μοντέλο outbox και θα κάνει την εφαρμογή να συνδέεται μόνο στα relay στις λίστες σας.</string>
|
||||
<string name="public_chat">Δημόσια Συζήτηση</string>
|
||||
<string name="public_chat_explainer">Οι δημόσιες συνομιλίες είναι ορατές σε όλους στο Nostr και οποιοσδήποτε
|
||||
μπορεί να συμμετάσχει σε αυτές. Είναι ιδανικές για ανοιχτές κοινότητες γύρω από συγκεκριμένα θέματα.
|
||||
Η εποπτεία μπορεί να ελεγχθεί με διαγραφή αναρτήσεων στα relay της</string>
|
||||
<string name="public_chat_relays_explainer">Εισάγετε 1–3 relay που φιλοξενούν αυτή την ομάδα.
|
||||
Οι πελάτες Nostr χρησιμοποιούν αυτή τη ρύθμιση για να γνωρίζουν πού να κατεβάσουν μηνύματα και πού να στέλνουν τα μηνύματά σου.</string>
|
||||
<string name="public_chat_explainer">Οι δημόσιες συνομιλίες είναι ορατές σε όλους στο Nostr και οποιοσδήποτε μπορεί να συμμετάσχει σε αυτές. Είναι ιδανικές για ανοιχτές κοινότητες γύρω από συγκεκριμένα θέματα. Η εποπτεία μπορεί να ελεγχθεί με διαγραφή αναρτήσεων στα relay της</string>
|
||||
<string name="public_chat_relays_explainer">Εισάγετε 1–3 relay που φιλοξενούν αυτή την ομάδα. Οι πελάτες Nostr χρησιμοποιούν αυτή τη ρύθμιση για να γνωρίζουν πού να κατεβάσουν μηνύματα και πού να στέλνουν τα μηνύματά σου.</string>
|
||||
<string name="public_chat_title">Μεταδεδομένα δημόσιας συνομιλίας</string>
|
||||
<string name="public_chats">Δημόσιες Συνομιλίες</string>
|
||||
<string name="public_home_section">Δημόσια Relay Εξερχόμενων/Αρχικής</string>
|
||||
@@ -2681,10 +2660,7 @@
|
||||
<string name="read_only_user">Χρήστης μόνο για ανάγνωση</string>
|
||||
<string name="record_a_message_description">Πάτα παρατεταμένα για να καταγράψεις ένα μήνυμα</string>
|
||||
<string name="relay_chat">Συνομιλία relay</string>
|
||||
<string name="relay_chat_explainer">Οι συνομιλίες relay είναι ομάδες συνομιλίας που ελέγχονται από το αρχικό τους relay.
|
||||
Είναι ορατές σε όλους στο Nostr και οποιοσδήποτε μπορεί να συμμετάσχει σε αυτές.
|
||||
Είναι ιδανικές για ανοιχτές κοινότητες γύρω από συγκεκριμένα θέματα. Ορισμένες από αυτές τις ομάδες είναι εφήμερες
|
||||
και έτσι τα μηνύματα συνομιλίας εξαφανίζονται με την πάροδο του χρόνου</string>
|
||||
<string name="relay_chat_explainer">Οι συνομιλίες relay είναι ομάδες συνομιλίας που ελέγχονται από το αρχικό τους relay. Είναι ορατές σε όλους στο Nostr και οποιοσδήποτε μπορεί να συμμετάσχει σε αυτές. Είναι ιδανικές για ανοιχτές κοινότητες γύρω από συγκεκριμένα θέματα. Ορισμένες από αυτές τις ομάδες είναι εφήμερες και έτσι τα μηνύματα συνομιλίας εξαφανίζονται με την πάροδο του χρόνου</string>
|
||||
<string name="relay_chat_title">Συνομιλίες relay</string>
|
||||
<string name="relay_management_tab_events">Συμβάντα</string>
|
||||
<string name="relay_management_tab_pubkeys">Χρήστες</string>
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<string name="copy_user_id">Kopii ID de uzanto</string>
|
||||
<string name="unblock_user">Malbloki Uzanton</string>
|
||||
<string name="user_is_blocked_hidden">Tiu ĉi uzanto estas blokita/silentita. Iliaj afiŝoj estas kaŝitaj.</string>
|
||||
<string name="npub_hex_username">npub, hekso, uzantnomo </string>
|
||||
<string name="npub_hex_username">npub, hekso, uzantnomo</string>
|
||||
<string name="clear">Klarigi</string>
|
||||
<string name="app_logo">Logo de Apo</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / heksa privata ŝlosilo</string>
|
||||
@@ -273,15 +273,8 @@
|
||||
<string name="mark_all_known_as_read">Marki ĉiujn Konatajn legitaj</string>
|
||||
<string name="mark_all_new_as_read">Marki ĉiujn Novajn legitaj</string>
|
||||
<string name="mark_all_as_read">Marki ĉiujn legitajn</string>
|
||||
<string name="account_backup_tips2_md"> ## Konsiletoj pri Ŝlosila Sekurkopiao kaj Sekureco
|
||||
\n\nVia konto estas sekurigita per sekreta ŝlosilo. La ŝlosilo estas longa sinsekvo de signoj komencanta per **nsec1**. Ĉiu kiu havas aliron al ĉi tiu sekreta ŝlosilo povas afiŝi kaj ŝanĝi vian identecon.
|
||||
\n\n- **Ne** metu vian sekretan ŝlosilon en ajnan retejon aŭ programaron, kiun vi ne fidas.
|
||||
\n- Amethyst-programistoj **neniam** petos vian sekretan ŝlosilon.
|
||||
\n- **Faru** sekuran sekurkopion de via sekreta ŝlosilo por reakiro de konto. Ni rekomendas uzi pasvortan administrilon.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Por plia sekureco, vi povas ĉifri vian ŝlosilon per pasvorto. Ĉi tiu ŝlosilo komenciĝas per **ncryptsec1** kaj ne povas esti uzata sen via pasvorto.
|
||||
\n\nSe vi perdas vian pasvorton, vi ne povos reakiri vian ŝlosilon.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Konsiletoj pri Ŝlosila Sekurkopiao kaj Sekureco \n\nVia konto estas sekurigita per sekreta ŝlosilo. La ŝlosilo estas longa sinsekvo de signoj komencanta per **nsec1**. Ĉiu kiu havas aliron al ĉi tiu sekreta ŝlosilo povas afiŝi kaj ŝanĝi vian identecon. \n\n- **Ne** metu vian sekretan ŝlosilon en ajnan retejon aŭ programaron, kiun vi ne fidas. \n- Amethyst-programistoj **neniam** petos vian sekretan ŝlosilon. \n- **Faru** sekuran sekurkopion de via sekreta ŝlosilo por reakiro de konto. Ni rekomendas uzi pasvortan administrilon.</string>
|
||||
<string name="account_backup_tips3_md">Por plia sekureco, vi povas ĉifri vian ŝlosilon per pasvorto. Ĉi tiu ŝlosilo komenciĝas per **ncryptsec1** kaj ne povas esti uzata sen via pasvorto. \n\nSe vi perdas vian pasvorton, vi ne povos reakiri vian ŝlosilon.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Ĉifri kaj kopii mian seketan ŝlosilon</string>
|
||||
<string name="badge_award_image_for">Ŝildeto-premia bildo por %1$s</string>
|
||||
<string name="badge_award_image">"Insigna premibildeto</string>
|
||||
@@ -971,9 +964,7 @@
|
||||
<string name="push_server_none_explainer">Malaktivigi Puŝajn Sciigojn</string>
|
||||
<string name="push_server_uses_app_explainer">Uzas aplikaĵon %1$s</string>
|
||||
<string name="push_server_install_app">Puŝa Sciig-Agordo</string>
|
||||
<string name="push_server_install_app_description"> Por ricevi puŝajn sciigojn, instalu ajnan aplikaĵon kiu subtenas [Unified Push](https://unifiedpush.org/), kiel ekzemple [Ntfy](https://ntfy.sh/).
|
||||
Post instalado, elektu la aplikaĵon, kiun vi volas uzi en la Agordoj.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Por ricevi puŝajn sciigojn, instalu ajnan aplikaĵon kiu subtenas [Unified Push](https://unifiedpush.org/), kiel ekzemple [Ntfy](https://ntfy.sh/). Post instalado, elektu la aplikaĵon, kiun vi volas uzi en la Agordoj.</string>
|
||||
<string name="thread_title">Fadeno</string>
|
||||
<string name="send_the_seller_a_message">Sendi mesaĝon al la vendisto</string>
|
||||
<string name="hi_there_is_this_still_available">Saluton, ĉu ĉi tio ankoraŭ disponeblas?</string>
|
||||
@@ -2031,15 +2022,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Ne eblis preni fakturon de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Ne eblis malfermi la kunpremitan dosieron</string>
|
||||
<string name="couldnt_find_nwc_wallets">Monujo ne trovita</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ne povis trovi ajnajn monujo-aplikojn, kiuj subtenas Nostr Wallet Connect (NWC).
|
||||
\n\nKion vi povas fari:
|
||||
\n\t1. Kontrolu NWC-subtenon: Duoble kontrolu, ĉu via preferata monujo-aplikaĵo estas kongrua kun Nostr Wallet Connect.
|
||||
\n\t2. Krei Konekton: Iru al via monujo-aplikaĵo kaj kreu novan NWC-konekton.
|
||||
\n\t3. Ligi al Amethyst: Via monujo kutime donos al vi tri opciojn:
|
||||
\n\t\t3.1 Aŭtomata Ligo: Butono por aŭtomate malfermi kaj konekti al Amethyst. Se jes, alklaku tiun butonon, malfermu Amethyst kaj alklaku konservi sur la nova ekrano.
|
||||
\n\t\t3.2 Mana Ligo: Konekta URI, kiun vi povas kopii kaj alklaki la algluu-ikonon sur ĉi tiu ekrano por rekte enigi ĝin.
|
||||
\n\t\t3.3 QR-Kodo: La monujo kreas QR-kodon, kiun vi povas legi per la QR-koda butono sur ĉi tiu ekrano.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ne povis trovi ajnajn monujo-aplikojn, kiuj subtenas Nostr Wallet Connect (NWC). \n\nKion vi povas fari: \n\t1. Kontrolu NWC-subtenon: Duoble kontrolu, ĉu via preferata monujo-aplikaĵo estas kongrua kun Nostr Wallet Connect. \n\t2. Krei Konekton: Iru al via monujo-aplikaĵo kaj kreu novan NWC-konekton. \n\t3. Ligi al Amethyst: Via monujo kutime donos al vi tri opciojn: \n\t\t3.1 Aŭtomata Ligo: Butono por aŭtomate malfermi kaj konekti al Amethyst. Se jes, alklaku tiun butonon, malfermu Amethyst kaj alklaku konservi sur la nova ekrano. \n\t\t3.2 Mana Ligo: Konekta URI, kiun vi povas kopii kaj alklaki la algluu-ikonon sur ĉi tiu ekrano por rekte enigi ĝin. \n\t\t3.3 QR-Kodo: La monujo kreas QR-kodon, kiun vi povas legi per la QR-koda butono sur ĉi tiu ekrano.</string>
|
||||
<string name="create">Krei</string>
|
||||
<string name="d">t</string>
|
||||
<string name="danger_zone">Danĝera Zono</string>
|
||||
@@ -2701,11 +2684,8 @@
|
||||
<string name="proxy_section">Prokuro-Relay-oj</string>
|
||||
<string name="proxy_section_explainer">Agregataj relay-oj, kiujn la aplikaĵo devas uzi por elŝuti viajn fluojn, ekzemple filter.nostr.wine. Ĉi tio anstataŭas la sendkesta modelon kaj igos la aplikaĵon konektiĝi nur al la relay-oj en viaj listoj.</string>
|
||||
<string name="public_chat">Publika Babilado</string>
|
||||
<string name="public_chat_explainer">Publikaj babilejoj estas videblaj al ĉiuj en Nostr kaj ĉiu ajn
|
||||
povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj.
|
||||
Moderado povas esti kontrolata per forigo de afiŝoj sur siaj relays</string>
|
||||
<string name="public_chat_relays_explainer">Enigu inter 1–3 relays, kiuj gastigas ĉi tiun grupon.
|
||||
Nostr-klientoj uzas ĉi tiun agordon por scii, kie elŝuti mesaĝojn kaj kien sendi viajn mesaĝojn.</string>
|
||||
<string name="public_chat_explainer">Publikaj babilejoj estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Moderado povas esti kontrolata per forigo de afiŝoj sur siaj relays</string>
|
||||
<string name="public_chat_relays_explainer">Enigu inter 1–3 relays, kiuj gastigas ĉi tiun grupon. Nostr-klientoj uzas ĉi tiun agordon por scii, kie elŝuti mesaĝojn kaj kien sendi viajn mesaĝojn.</string>
|
||||
<string name="public_chat_relays_title">Relay-oj</string>
|
||||
<string name="public_chat_title">Publikaj Babilejaj Metadatenoj</string>
|
||||
<string name="public_chats">Publikaj Babilejoj</string>
|
||||
@@ -2730,10 +2710,7 @@
|
||||
<string name="read_only_user">Nur-lega uzanto</string>
|
||||
<string name="record_a_message_description">Alklaku kaj tenu por registri mesaĝon</string>
|
||||
<string name="relay_chat">Relay-Babilejo</string>
|
||||
<string name="relay_chat_explainer">Relay-babilejoj estas babilaj grupoj kontrolataj de sia hejma relay.
|
||||
Ili estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili.
|
||||
Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Kelkaj el ĉi tiuj grupoj estas efemeraj
|
||||
kaj tial babilmesaĝoj malaperas kun la tempo</string>
|
||||
<string name="relay_chat_explainer">Relay-babilejoj estas babilaj grupoj kontrolataj de sia hejma relay. Ili estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Kelkaj el ĉi tiuj grupoj estas efemeraj kaj tial babilmesaĝoj malaperas kun la tempo</string>
|
||||
<string name="relay_chat_title">Relay-Babilejaroj</string>
|
||||
<string name="relay_management_tab_events">Eventoj</string>
|
||||
<string name="relay_management_tab_ips">IP-oj</string>
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
<string name="copy_user_id">Kopii ID de uzanto</string>
|
||||
<string name="unblock_user">Malbloki Uzanton</string>
|
||||
<string name="user_is_blocked_hidden">Tiu ĉi uzanto estas blokita/silentita. Iliaj afiŝoj estas kaŝitaj.</string>
|
||||
<string name="npub_hex_username">npub, hekso, uzantnomo </string>
|
||||
<string name="npub_hex_username">npub, hekso, uzantnomo</string>
|
||||
<string name="clear">Klarigi</string>
|
||||
<string name="app_logo">Logo de Apo</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / heksa privata ŝlosilo</string>
|
||||
@@ -259,17 +259,8 @@
|
||||
<string name="mark_all_known_as_read">Marki ĉiujn Konatajn legitaj</string>
|
||||
<string name="mark_all_new_as_read">Marki ĉiujn Novajn legitaj</string>
|
||||
<string name="mark_all_as_read">Marki ĉiujn legitajn</string>
|
||||
<string name="account_backup_tips2_md">
|
||||
## Konsiletoj pri Ŝlosila Sekurkopiao kaj Sekureco
|
||||
\n\nVia konto estas sekurigita per sekreta ŝlosilo. La ŝlosilo estas longa sinsekvo de signoj komencanta per **nsec1**. Ĉiu kiu havas aliron al ĉi tiu sekreta ŝlosilo povas afiŝi kaj ŝanĝi vian identecon.
|
||||
\n\n- **Ne** metu vian sekretan ŝlosilon en ajnan retejon aŭ programaron, kiun vi ne fidas.
|
||||
\n- Amethyst-programistoj **neniam** petos vian sekretan ŝlosilon.
|
||||
\n- **Faru** sekuran sekurkopion de via sekreta ŝlosilo por reakiro de konto. Ni rekomendas uzi pasvortan administrilon.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md">
|
||||
Por plia sekureco, vi povas ĉifri vian ŝlosilon per pasvorto. Ĉi tiu ŝlosilo komenciĝas per **ncryptsec1** kaj ne povas esti uzata sen via pasvorto.
|
||||
\n\nSe vi perdas vian pasvorton, vi ne povos reakiri vian ŝlosilon.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Konsiletoj pri Ŝlosila Sekurkopiao kaj Sekureco \n\nVia konto estas sekurigita per sekreta ŝlosilo. La ŝlosilo estas longa sinsekvo de signoj komencanta per **nsec1**. Ĉiu kiu havas aliron al ĉi tiu sekreta ŝlosilo povas afiŝi kaj ŝanĝi vian identecon. \n\n- **Ne** metu vian sekretan ŝlosilon en ajnan retejon aŭ programaron, kiun vi ne fidas. \n- Amethyst-programistoj **neniam** petos vian sekretan ŝlosilon. \n- **Faru** sekuran sekurkopion de via sekreta ŝlosilo por reakiro de konto. Ni rekomendas uzi pasvortan administrilon.</string>
|
||||
<string name="account_backup_tips3_md">Por plia sekureco, vi povas ĉifri vian ŝlosilon per pasvorto. Ĉi tiu ŝlosilo komenciĝas per **ncryptsec1** kaj ne povas esti uzata sen via pasvorto. \n\nSe vi perdas vian pasvorton, vi ne povos reakiri vian ŝlosilon.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Ĉifri kaj kopii mian seketan ŝlosilon</string>
|
||||
<string name="badge_award_image_for">Ŝildeto-premia bildo por %1$s</string>
|
||||
<string name="badge_award_image">"Insigna premibildeto</string>
|
||||
@@ -962,10 +953,7 @@
|
||||
<string name="push_server_none_explainer">Malaktivigi Puŝajn Sciigojn</string>
|
||||
<string name="push_server_uses_app_explainer">Uzas aplikaĵon %1$s</string>
|
||||
<string name="push_server_install_app">Puŝa Sciig-Agordo</string>
|
||||
<string name="push_server_install_app_description">
|
||||
Por ricevi puŝajn sciigojn, instalu ajnan aplikaĵon kiu subtenas [Unified Push](https://unifiedpush.org/), kiel ekzemple [Ntfy](https://ntfy.sh/).
|
||||
Post instalado, elektu la aplikaĵon, kiun vi volas uzi en la Agordoj.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Por ricevi puŝajn sciigojn, instalu ajnan aplikaĵon kiu subtenas [Unified Push](https://unifiedpush.org/), kiel ekzemple [Ntfy](https://ntfy.sh/). Post instalado, elektu la aplikaĵon, kiun vi volas uzi en la Agordoj.</string>
|
||||
<string name="thread_title">Fadeno</string>
|
||||
<string name="send_the_seller_a_message">Sendi mesaĝon al la vendisto</string>
|
||||
<string name="hi_there_is_this_still_available">Saluton, ĉu ĉi tio ankoraŭ disponeblas?</string>
|
||||
@@ -2058,15 +2046,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Ne eblis preni fakturon de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Ne eblis malfermi la kunpremitan dosieron</string>
|
||||
<string name="couldnt_find_nwc_wallets">Monujo ne trovita</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ne povis trovi ajnajn monujo-aplikojn, kiuj subtenas Nostr Wallet Connect (NWC).
|
||||
\n\nKion vi povas fari:
|
||||
\n\t1. Kontrolu NWC-subtenon: Duoble kontrolu, ĉu via preferata monujo-aplikaĵo estas kongrua kun Nostr Wallet Connect.
|
||||
\n\t2. Krei Konekton: Iru al via monujo-aplikaĵo kaj kreu novan NWC-konekton.
|
||||
\n\t3. Ligi al Amethyst: Via monujo kutime donos al vi tri opciojn:
|
||||
\n\t\t3.1 Aŭtomata Ligo: Butono por aŭtomate malfermi kaj konekti al Amethyst. Se jes, alklaku tiun butonon, malfermu Amethyst kaj alklaku konservi sur la nova ekrano.
|
||||
\n\t\t3.2 Mana Ligo: Konekta URI, kiun vi povas kopii kaj alklaki la algluu-ikonon sur ĉi tiu ekrano por rekte enigi ĝin.
|
||||
\n\t\t3.3 QR-Kodo: La monujo kreas QR-kodon, kiun vi povas legi per la QR-koda butono sur ĉi tiu ekrano.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ne povis trovi ajnajn monujo-aplikojn, kiuj subtenas Nostr Wallet Connect (NWC). \n\nKion vi povas fari: \n\t1. Kontrolu NWC-subtenon: Duoble kontrolu, ĉu via preferata monujo-aplikaĵo estas kongrua kun Nostr Wallet Connect. \n\t2. Krei Konekton: Iru al via monujo-aplikaĵo kaj kreu novan NWC-konekton. \n\t3. Ligi al Amethyst: Via monujo kutime donos al vi tri opciojn: \n\t\t3.1 Aŭtomata Ligo: Butono por aŭtomate malfermi kaj konekti al Amethyst. Se jes, alklaku tiun butonon, malfermu Amethyst kaj alklaku konservi sur la nova ekrano. \n\t\t3.2 Mana Ligo: Konekta URI, kiun vi povas kopii kaj alklaki la algluu-ikonon sur ĉi tiu ekrano por rekte enigi ĝin. \n\t\t3.3 QR-Kodo: La monujo kreas QR-kodon, kiun vi povas legi per la QR-koda butono sur ĉi tiu ekrano.</string>
|
||||
<string name="create">Krei</string>
|
||||
<string name="d">t</string>
|
||||
<string name="danger_zone">Danĝera Zono</string>
|
||||
@@ -2754,11 +2734,8 @@
|
||||
<string name="proxy_section">Prokuro-Relay-oj</string>
|
||||
<string name="proxy_section_explainer">Agregataj relay-oj, kiujn la aplikaĵo devas uzi por elŝuti viajn fluojn, ekzemple filter.nostr.wine. Ĉi tio anstataŭas la sendkesta modelon kaj igos la aplikaĵon konektiĝi nur al la relay-oj en viaj listoj.</string>
|
||||
<string name="public_chat">Publika Babilado</string>
|
||||
<string name="public_chat_explainer">Publikaj babilejoj estas videblaj al ĉiuj en Nostr kaj ĉiu ajn
|
||||
povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj.
|
||||
Moderado povas esti kontrolata per forigo de afiŝoj sur siaj relays</string>
|
||||
<string name="public_chat_relays_explainer">Enigu inter 1–3 relays, kiuj gastigas ĉi tiun grupon.
|
||||
Nostr-klientoj uzas ĉi tiun agordon por scii, kie elŝuti mesaĝojn kaj kien sendi viajn mesaĝojn.</string>
|
||||
<string name="public_chat_explainer">Publikaj babilejoj estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Moderado povas esti kontrolata per forigo de afiŝoj sur siaj relays</string>
|
||||
<string name="public_chat_relays_explainer">Enigu inter 1–3 relays, kiuj gastigas ĉi tiun grupon. Nostr-klientoj uzas ĉi tiun agordon por scii, kie elŝuti mesaĝojn kaj kien sendi viajn mesaĝojn.</string>
|
||||
<string name="public_chat_relays_title">Relay-oj</string>
|
||||
<string name="public_chat_title">Publikaj Babilejaj Metadatenoj</string>
|
||||
<string name="public_chats">Publikaj Babilejoj</string>
|
||||
@@ -2783,10 +2760,7 @@
|
||||
<string name="read_only_user">Nur-lega uzanto</string>
|
||||
<string name="record_a_message_description">Alklaku kaj tenu por registri mesaĝon</string>
|
||||
<string name="relay_chat">Relay-Babilejo</string>
|
||||
<string name="relay_chat_explainer">Relay-babilejoj estas babilaj grupoj kontrolataj de sia hejma relay.
|
||||
Ili estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili.
|
||||
Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Kelkaj el ĉi tiuj grupoj estas efemeraj
|
||||
kaj tial babilmesaĝoj malaperas kun la tempo</string>
|
||||
<string name="relay_chat_explainer">Relay-babilejoj estas babilaj grupoj kontrolataj de sia hejma relay. Ili estas videblaj al ĉiuj en Nostr kaj ĉiu ajn povas partopreni en ili. Ili estas bonegaj por malfermitaj komunumoj pri specifaj temoj. Kelkaj el ĉi tiuj grupoj estas efemeraj kaj tial babilmesaĝoj malaperas kun la tempo</string>
|
||||
<string name="relay_chat_title">Relay-Babilejaroj</string>
|
||||
<string name="relay_management_tab_events">Eventoj</string>
|
||||
<string name="relay_management_tab_ips">IP-oj</string>
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
<string name="copy_user_id">Copiar ID de usuario</string>
|
||||
<string name="unblock_user">Desbloquear usuario</string>
|
||||
<string name="user_is_blocked_hidden">Este usuario está bloqueado/silenciado. Sus publicaciones están ocultas.</string>
|
||||
<string name="npub_hex_username">npub, hex, username </string>
|
||||
<string name="npub_hex_username">npub, hex, username</string>
|
||||
<string name="clear">Limpiar</string>
|
||||
<string name="app_logo">Logo de la app</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec o npub</string>
|
||||
@@ -272,15 +272,8 @@
|
||||
<string name="mark_all_known_as_read">Marcar los conocidos como leídos</string>
|
||||
<string name="mark_all_new_as_read">Marcar los nuevos como leídos</string>
|
||||
<string name="mark_all_as_read">Marcar todos como leídos</string>
|
||||
<string name="account_backup_tips2_md"> ## Consejos sobre la protección y la copia de seguridad de las claves
|
||||
\n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad.
|
||||
\n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes.
|
||||
\n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta.
|
||||
\n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña.
|
||||
\n\nSi pierdes la contraseña, no podrás recuperar tu clave.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Consejos sobre la protección y la copia de seguridad de las claves \n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad. \n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes. \n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta. \n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.</string>
|
||||
<string name="account_backup_tips3_md">Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña. \n\nSi pierdes la contraseña, no podrás recuperar tu clave.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Cifrar y copiar mi clave secreta</string>
|
||||
<string name="badge_award_image_for">Imagen del Badge para %1$s</string>
|
||||
<string name="badge_award_image">"Imagen de premio de insignia</string>
|
||||
@@ -962,9 +955,7 @@
|
||||
<string name="push_server_none_explainer">Desactiva las notificaciones push</string>
|
||||
<string name="push_server_uses_app_explainer">Usa la app %1$s</string>
|
||||
<string name="push_server_install_app">Configuración de notificaciones push</string>
|
||||
<string name="push_server_install_app_description"> Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/).
|
||||
Tras la instalación, selecciona la aplicación que deseas usar en la configuración.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/). Tras la instalación, selecciona la aplicación que deseas usar en la configuración.</string>
|
||||
<string name="thread_title">Conversación</string>
|
||||
<string name="send_the_seller_a_message">Envía un mensaje al vendedor</string>
|
||||
<string name="hi_there_is_this_still_available">Hola, ¿esto todavía está disponible?</string>
|
||||
@@ -2028,15 +2019,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">No se ha podido obtener la factura de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">No se pudo abrir el archivo comprimido</string>
|
||||
<string name="couldnt_find_nwc_wallets">Cartera no encontrada</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC).
|
||||
\n\nQué puedes hacer:
|
||||
\n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect.
|
||||
\n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC.
|
||||
\n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones:
|
||||
\n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla.
|
||||
\n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente.
|
||||
\n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC). \n\nQué puedes hacer: \n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect. \n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC. \n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones: \n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla. \n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente. \n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.</string>
|
||||
<string name="create">Crear</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">Zona peligrosa</string>
|
||||
@@ -2715,11 +2698,8 @@
|
||||
<string name="proxy_section">Relés de proxy</string>
|
||||
<string name="proxy_section_explainer">Relés recopiladores que la app debe usar para descargar tus fuentes, como filter.nostr.wine. Esto reemplaza el modelo de bandeja de salida y hará que la app se conecte solo a los relés de tus listas.</string>
|
||||
<string name="public_chat">Chat público</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera
|
||||
puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos.
|
||||
La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo.
|
||||
Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos. La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo. Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_relays_title">Relés</string>
|
||||
<string name="public_chat_title">Metadatos públicos del chat</string>
|
||||
<string name="public_chats">Chats públicos</string>
|
||||
@@ -2744,10 +2724,7 @@
|
||||
<string name="read_only_user">Usuario de solo lectura</string>
|
||||
<string name="record_a_message_description">Haz clic y mantén pulsado para grabar un mensaje</string>
|
||||
<string name="relay_chat">Chat en relé</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen.
|
||||
Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos.
|
||||
Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros
|
||||
y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen. Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_title">Chats en relé</string>
|
||||
<string name="relay_management_tab_events">Eventos</string>
|
||||
<string name="relay_management_tab_kinds">Tipos</string>
|
||||
|
||||
@@ -272,15 +272,8 @@
|
||||
<string name="mark_all_known_as_read">Marcar todos los conocidos como leídos</string>
|
||||
<string name="mark_all_new_as_read">Marcar todos los nuevos como leídos</string>
|
||||
<string name="mark_all_as_read">Marcar todos como leídos</string>
|
||||
<string name="account_backup_tips2_md"> ## Consejos sobre la protección y la copia de seguridad de las claves
|
||||
\n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad.
|
||||
\n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes.
|
||||
\n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta.
|
||||
\n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña.
|
||||
\n\nSi pierdes la contraseña, no podrás recuperar tu clave.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Consejos sobre la protección y la copia de seguridad de las claves \n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad. \n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes. \n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta. \n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.</string>
|
||||
<string name="account_backup_tips3_md">Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña. \n\nSi pierdes la contraseña, no podrás recuperar tu clave.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Cifrar y copiar mi clave secreta</string>
|
||||
<string name="badge_award_image_for">Imagen de premio de insignia por %1$s</string>
|
||||
<string name="badge_award_image">"Imagen de premio de insignia</string>
|
||||
@@ -961,9 +954,7 @@
|
||||
<string name="push_server_none_explainer">Desactiva las notificaciones push</string>
|
||||
<string name="push_server_uses_app_explainer">Usa la app %1$s</string>
|
||||
<string name="push_server_install_app">Configuración de notificaciones push</string>
|
||||
<string name="push_server_install_app_description"> Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/).
|
||||
Tras la instalación, selecciona la aplicación que deseas usar en la configuración.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/). Tras la instalación, selecciona la aplicación que deseas usar en la configuración.</string>
|
||||
<string name="thread_title">Hilo</string>
|
||||
<string name="send_the_seller_a_message">Envía un mensaje al vendedor</string>
|
||||
<string name="hi_there_is_this_still_available">Hola, ¿esto todavía está disponible?</string>
|
||||
@@ -2027,15 +2018,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">No se pudo obtener la factura de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">No se pudo abrir el archivo comprimido</string>
|
||||
<string name="couldnt_find_nwc_wallets">Billetera no encontrada</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC).
|
||||
\n\nQué puedes hacer:
|
||||
\n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect.
|
||||
\n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC.
|
||||
\n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones:
|
||||
\n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla.
|
||||
\n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente.
|
||||
\n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC). \n\nQué puedes hacer: \n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect. \n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC. \n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones: \n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla. \n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente. \n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.</string>
|
||||
<string name="create">Crear</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">Zona peligrosa</string>
|
||||
@@ -2708,11 +2691,8 @@
|
||||
<string name="proxy_section">Relés de proxy</string>
|
||||
<string name="proxy_section_explainer">Relés recopiladores que la app debe usar para descargar tus feeds, como filter.nostr.wine. Esto reemplaza el modelo de bandeja de salida y hará que la app se conecte solo a los relés de tus listas.</string>
|
||||
<string name="public_chat">Chat público</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera
|
||||
puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos.
|
||||
La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo.
|
||||
Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos. La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo. Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_relays_title">Relés</string>
|
||||
<string name="public_chat_title">Metadatos públicos del chat</string>
|
||||
<string name="public_chats">Chats públicos</string>
|
||||
@@ -2737,10 +2717,7 @@
|
||||
<string name="read_only_user">Usuario de solo lectura</string>
|
||||
<string name="record_a_message_description">Haz clic y mantén presionado para grabar un mensaje</string>
|
||||
<string name="relay_chat">Chat en relé</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen.
|
||||
Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos.
|
||||
Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros
|
||||
y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen. Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_title">Chats en relé</string>
|
||||
<string name="relay_management_tab_events">Eventos</string>
|
||||
<string name="relay_management_tab_kinds">Tipos</string>
|
||||
|
||||
@@ -272,15 +272,8 @@
|
||||
<string name="mark_all_known_as_read">Marcar todos los conocidos como leídos</string>
|
||||
<string name="mark_all_new_as_read">Marcar todos los nuevos como leídos</string>
|
||||
<string name="mark_all_as_read">Marcar todos como leídos</string>
|
||||
<string name="account_backup_tips2_md"> ## Consejos sobre la protección y la copia de seguridad de las claves
|
||||
\n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad.
|
||||
\n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes.
|
||||
\n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta.
|
||||
\n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña.
|
||||
\n\nSi pierdes la contraseña, no podrás recuperar tu clave.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Consejos sobre la protección y la copia de seguridad de las claves \n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad. \n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes. \n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta. \n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.</string>
|
||||
<string name="account_backup_tips3_md">Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña. \n\nSi pierdes la contraseña, no podrás recuperar tu clave.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Cifrar y copiar mi clave secreta</string>
|
||||
<string name="badge_award_image_for">Imagen de premio de insignia por %1$s</string>
|
||||
<string name="badge_award_image">"Imagen de premio de insignia</string>
|
||||
@@ -961,9 +954,7 @@
|
||||
<string name="push_server_none_explainer">Desactiva las notificaciones push</string>
|
||||
<string name="push_server_uses_app_explainer">Usa la app %1$s</string>
|
||||
<string name="push_server_install_app">Configuración de notificaciones push</string>
|
||||
<string name="push_server_install_app_description"> Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/).
|
||||
Tras la instalación, selecciona la aplicación que deseas usar en la configuración.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/). Tras la instalación, selecciona la aplicación que deseas usar en la configuración.</string>
|
||||
<string name="thread_title">Hilo</string>
|
||||
<string name="send_the_seller_a_message">Envía un mensaje al vendedor</string>
|
||||
<string name="hi_there_is_this_still_available">Hola, ¿esto todavía está disponible?</string>
|
||||
@@ -2027,15 +2018,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">No se pudo obtener la factura de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">No se pudo abrir el archivo comprimido</string>
|
||||
<string name="couldnt_find_nwc_wallets">Billetera no encontrada</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC).
|
||||
\n\nQué puedes hacer:
|
||||
\n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect.
|
||||
\n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC.
|
||||
\n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones:
|
||||
\n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla.
|
||||
\n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente.
|
||||
\n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC). \n\nQué puedes hacer: \n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect. \n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC. \n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones: \n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla. \n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente. \n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.</string>
|
||||
<string name="create">Crear</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">Zona peligrosa</string>
|
||||
@@ -2708,11 +2691,8 @@
|
||||
<string name="proxy_section">Relés de proxy</string>
|
||||
<string name="proxy_section_explainer">Relés recopiladores que la app debe usar para descargar tus feeds, como filter.nostr.wine. Esto reemplaza el modelo de bandeja de salida y hará que la app se conecte solo a los relés de tus listas.</string>
|
||||
<string name="public_chat">Chat público</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera
|
||||
puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos.
|
||||
La moderación puede controlarse eliminando mensajes en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo.
|
||||
Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos. La moderación puede controlarse eliminando mensajes en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo. Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_relays_title">Relés</string>
|
||||
<string name="public_chat_title">Metadatos públicos del chat</string>
|
||||
<string name="public_chats">Chats públicos</string>
|
||||
@@ -2737,10 +2717,7 @@
|
||||
<string name="read_only_user">Usuario de solo lectura</string>
|
||||
<string name="record_a_message_description">Haz clic y mantén presionado para grabar un mensaje</string>
|
||||
<string name="relay_chat">Chat en relé</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen.
|
||||
Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos.
|
||||
Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros
|
||||
y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen. Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_title">Chats en relé</string>
|
||||
<string name="relay_management_tab_events">Eventos</string>
|
||||
<string name="relay_management_tab_kinds">Tipos</string>
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
<string name="copy_user_id">Copiar ID de usuario</string>
|
||||
<string name="unblock_user">Desbloquear usuario</string>
|
||||
<string name="user_is_blocked_hidden">Este usuario está bloqueado/silenciado. Sus publicaciones están ocultas.</string>
|
||||
<string name="npub_hex_username">npub, hex, username </string>
|
||||
<string name="npub_hex_username">npub, hex, username</string>
|
||||
<string name="clear">Limpiar</string>
|
||||
<string name="app_logo">Logo de la app</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex private key</string>
|
||||
@@ -951,9 +951,7 @@
|
||||
<string name="push_server_none_explainer">Desactiva las notificaciones push</string>
|
||||
<string name="push_server_uses_app_explainer">Usa la app %1$s</string>
|
||||
<string name="push_server_install_app">Configuración de notificaciones push</string>
|
||||
<string name="push_server_install_app_description"> Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/).
|
||||
Tras la instalación, selecciona la aplicación que deseas usar en la configuración.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Para recibir notificaciones push, instala cualquier aplicación compatible con [Unified Push](https://unifiedpush.org/), como [Ntfy](https://ntfy.sh/). Tras la instalación, selecciona la aplicación que deseas usar en la configuración.</string>
|
||||
<string name="thread_title">Conversación</string>
|
||||
<string name="send_the_seller_a_message">Envía un mensaje al vendedor</string>
|
||||
<string name="hi_there_is_this_still_available">Hola, ¿esto todavía está disponible?</string>
|
||||
@@ -1802,15 +1800,8 @@
|
||||
<string name="ots_explorer_api_label">URL base de la API del explorador</string>
|
||||
<string name="dvm_pay_invoice_from_dvm">Pagar factura del DVM</string>
|
||||
<string name="dvm_pay_amount_to_dvm">Pagar %1$s sats al DVM</string>
|
||||
<string xmlns:ns0="http://schemas.android.com/tools" name="account_backup_tips2_md" ns0:ignore="Typos"> ## Consejos sobre la protección y la copia de seguridad de las claves
|
||||
\n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad.
|
||||
\n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes.
|
||||
\n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta.
|
||||
\n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.
|
||||
</string>
|
||||
<string xmlns:ns0="http://schemas.android.com/tools" name="account_backup_tips3_md" ns0:ignore="Typos"> Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña.
|
||||
\n\nSi pierdes la contraseña, no podrás recuperar tu clave.
|
||||
</string>
|
||||
<string xmlns:ns0="http://schemas.android.com/tools" name="account_backup_tips2_md" ns0:ignore="Typos">## Consejos sobre la protección y la copia de seguridad de las claves \n\nTu cuenta está protegida por una clave secreta. La clave es una larga secuencia de caracteres que empieza por **nsec1**. Cualquiera que tenga acceso a esta clave secreta puede publicar y cambiar tu identidad. \n\n- **No** guardes la clave secreta en ningún sitio web o software en los que no confíes. \n- Los desarrolladores de Amethyst **nunca** te pedirán la clave secreta. \n- **Sí** puedes realizar una copia de seguridad de la clave secreta para recuperar la cuenta. Para ello, te recomendamos usar un gestor de contraseñas.</string>
|
||||
<string xmlns:ns0="http://schemas.android.com/tools" name="account_backup_tips3_md" ns0:ignore="Typos">Para mayor seguridad, puedes cifrar la clave con una contraseña. Esta clave empieza por **ncryptsec1** y no puede utilizarse sin tu contraseña. \n\nSi pierdes la contraseña, no podrás recuperar tu clave.</string>
|
||||
<string name="use_direct_url">Usar URL directa</string>
|
||||
<string name="nsite_title">nSite: %1$s</string>
|
||||
<string name="napplet_card_title">nApplet: %1$s</string>
|
||||
@@ -2055,15 +2046,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">No se ha podido obtener la factura de %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">No se pudo abrir el archivo comprimido</string>
|
||||
<string name="couldnt_find_nwc_wallets">Cartera no encontrada</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC).
|
||||
\n\nQué puedes hacer:
|
||||
\n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect.
|
||||
\n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC.
|
||||
\n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones:
|
||||
\n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla.
|
||||
\n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente.
|
||||
\n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst no encontró ninguna aplicación de cartera compatible con Nostr Wallet Connect (NWC). \n\nQué puedes hacer: \n\t1. Verificar la compatibilidad con NWC: Comprueba que tu aplicación de cartera preferida es compatible con Nostr Wallet Connect. \n\t2. Crear conexión: Ve a tu aplicación de cartera y crea una nueva conexión NWC. \n\t3. Vincular con Amethyst: Tu cartera normalmente te ofrecerá tres opciones: \n\t\t3.1 Enlace automático: Un botón para abrir y conectar automáticamente a Amethyst. Si es así, pulsa ese botón, abre Amethyst y guarda en la nueva pantalla. \n\t\t3.2 Enlace manual: Un URI de conexión que puedes copiar y pegar usando el icono de pegado en esta pantalla para introducirlo directamente. \n\t\t3.3 Código QR: La cartera genera un código QR que puedes leer con el botón de código QR en esta pantalla.</string>
|
||||
<string name="create">Crear</string>
|
||||
<string name="d">d</string>
|
||||
<string name="danger_zone">Zona peligrosa</string>
|
||||
@@ -2751,11 +2734,8 @@
|
||||
<string name="proxy_section">Relés de proxy</string>
|
||||
<string name="proxy_section_explainer">Relés recopiladores que la app debe usar para descargar tus fuentes, como filter.nostr.wine. Esto reemplaza el modelo de bandeja de salida y hará que la app se conecte solo a los relés de tus listas.</string>
|
||||
<string name="public_chat">Chat público</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera
|
||||
puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos.
|
||||
La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo.
|
||||
Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_explainer">Los chats públicos son visibles para todos en Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas alrededor de temas específicos. La moderación puede controlarse eliminando publicaciones en sus relés.</string>
|
||||
<string name="public_chat_relays_explainer">Inserta entre 1 y 3 relés que alojan este grupo. Los clientes de Nostr utilizan esta configuración para saber de dónde descargar y adónde enviar los mensajes.</string>
|
||||
<string name="public_chat_relays_title">Relés</string>
|
||||
<string name="public_chat_title">Metadatos públicos del chat</string>
|
||||
<string name="public_chats">Chats públicos</string>
|
||||
@@ -2780,10 +2760,7 @@
|
||||
<string name="read_only_user">Usuario de solo lectura</string>
|
||||
<string name="record_a_message_description">Haz clic y mantén pulsado para grabar un mensaje</string>
|
||||
<string name="relay_chat">Chat en relé</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen.
|
||||
Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos.
|
||||
Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros
|
||||
y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_explainer">Los chats en relé son grupos de chat controlados por su relé de origen. Son visibles para todos los usuarios de Nostr y cualquiera puede participar en ellos. Son ideales para comunidades abiertas en torno a temas específicos. Algunos de estos grupos son efímeros y, por lo tanto, los mensajes del chat desaparecen con el tiempo</string>
|
||||
<string name="relay_chat_title">Chats en relé</string>
|
||||
<string name="relay_management_tab_events">Eventos</string>
|
||||
<string name="relay_management_tab_ips">IPs</string>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<!-- Accessibility -->
|
||||
<!-- Relay history paging (shared feed markers + status card) -->
|
||||
<!-- Notes & Replies -->
|
||||
<string name="replying_to"> پاسخ به</string>
|
||||
<string name="replying_to">پاسخ به</string>
|
||||
<!-- Static sites (NIP-5A) & napplets (NIP-5D) feed card -->
|
||||
<string name="napplet_card_permissions">مجوزها:</string>
|
||||
<string name="nsite_root_site">سایت اصلی</string>
|
||||
@@ -226,7 +226,7 @@
|
||||
<string name="copy_user_id">کپی شناسه کاربر</string>
|
||||
<string name="unblock_user">از بلاک درآوردن کاربر</string>
|
||||
<string name="user_is_blocked_hidden">این کاربر مسدود/بیصدا شده است. پستهای آنها مخفی است.</string>
|
||||
<string name="npub_hex_username">npub, hex, نام کاربری </string>
|
||||
<string name="npub_hex_username">npub, hex, نام کاربری</string>
|
||||
<string name="clear">پاک کردن</string>
|
||||
<string name="app_logo">لوگوی اپ</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex کلید خصوصی</string>
|
||||
@@ -248,7 +248,7 @@
|
||||
<string name="chats_reply_searching_history">در حال جستجوی پیام اصلی…</string>
|
||||
<string name="chats_reply_not_found">این پیام پیدا نشد</string>
|
||||
<string name="chats_reply_searched">همه relay ها جستجو شد · برای مشاهده ضربه بزنید</string>
|
||||
<string name="error_loading_replies"> :خطا در بارگیری پاسخ ها</string>
|
||||
<string name="error_loading_replies">:خطا در بارگیری پاسخ ها</string>
|
||||
<string name="try_again">دوباره تلاش کنید</string>
|
||||
<string name="notification_feed_is_empty">هنوز هیچ اعلانی نیست.</string>
|
||||
<string name="open_poll">نظرسنجی باز</string>
|
||||
@@ -274,14 +274,8 @@
|
||||
<string name="mark_all_known_as_read">همه شناس ها خوانده شده کن</string>
|
||||
<string name="mark_all_new_as_read">همه جدیدها را خوانده شده کن</string>
|
||||
<string name="mark_all_as_read">همه را خوانده شده کن</string>
|
||||
<string name="account_backup_tips2_md">نکات ایمنی و ذخیره کلید
|
||||
|
||||
حساب کاربری شما با یک کلید خصوصی محافظت می شود. این کلید دنباله ای بلند از کاراکترها است که با **nsec1** آغاز می گردد. هر کس به این کلید خصوصی دسترسی داشته باشد می تواند بجای شما یادداشت پست کرده یا هویت شما را تغییر دهد.
|
||||
هرگز کلید خصوصی خود را در هیچ وبسایت با نرم افزاری که به آن اطمینان ندارید **وارد نکنید**.
|
||||
سازندگان امتیست **هرگز** کلیدتان را از شما نمی خواهند.
|
||||
یک پشتیبان یدکی مخفی از کلید خود به منظور بازیابی **نگه دارید**. ما استفاده از نرم افزار مدیریت پسورد را توصیه می کنیم.</string>
|
||||
<string name="account_backup_tips3_md">برای ایمنی بیشتر، می توانید کلید خود را با یک رمزعبور رمزنگاری کنید. این نوع کلید با **ncryptsec1** آغاز می شود و نمی تواند بدون رمز عبور شما استفاده شود.
|
||||
اگر پسوردتان را گم کنید، نخواهید توانست کلیدتان را بازیابی کنید.</string>
|
||||
<string name="account_backup_tips2_md">نکات ایمنی و ذخیره کلید حساب کاربری شما با یک کلید خصوصی محافظت می شود. این کلید دنباله ای بلند از کاراکترها است که با **nsec1** آغاز می گردد. هر کس به این کلید خصوصی دسترسی داشته باشد می تواند بجای شما یادداشت پست کرده یا هویت شما را تغییر دهد. هرگز کلید خصوصی خود را در هیچ وبسایت با نرم افزاری که به آن اطمینان ندارید **وارد نکنید**. سازندگان امتیست **هرگز** کلیدتان را از شما نمی خواهند. یک پشتیبان یدکی مخفی از کلید خود به منظور بازیابی **نگه دارید**. ما استفاده از نرم افزار مدیریت پسورد را توصیه می کنیم.</string>
|
||||
<string name="account_backup_tips3_md">برای ایمنی بیشتر، می توانید کلید خود را با یک رمزعبور رمزنگاری کنید. این نوع کلید با **ncryptsec1** آغاز می شود و نمی تواند بدون رمز عبور شما استفاده شود. اگر پسوردتان را گم کنید، نخواهید توانست کلیدتان را بازیابی کنید.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">رمزنگاری و کپی کلید من</string>
|
||||
<string name="badge_award_image_for">تصویر مدال پاداش برای %1$s</string>
|
||||
<string name="badge_award_image">تصویر جایزه نشان</string>
|
||||
@@ -301,7 +295,7 @@
|
||||
<string name="quick_action_request_deletion_gallery_title">حذف از گالری</string>
|
||||
<string name="quick_action_request_deletion_gallery_alert_body_v2">این رسانه را از گالری خود حذف کنید.</string>
|
||||
<string name="quick_action_request_deletion_alert_title">درخواست حذف</string>
|
||||
<string name="quick_action_request_deletion_alert_body">آماتیست درخواست می کند که یادداشت شما از رله هایی که درحال حاضر به آن متصل هستید حذف شود. هیچ تضمینی نیست که یادداشت شما برای همیشه از آن رله ها یا از رله های دیگری که ممکن است در آنها ذخیره شده باشد حذف خواهد شد.. </string>
|
||||
<string name="quick_action_request_deletion_alert_body">آماتیست درخواست می کند که یادداشت شما از رله هایی که درحال حاضر به آن متصل هستید حذف شود. هیچ تضمینی نیست که یادداشت شما برای همیشه از آن رله ها یا از رله های دیگری که ممکن است در آنها ذخیره شده باشد حذف خواهد شد..</string>
|
||||
<string name="quick_action_block_dialog_btn">بلاک</string>
|
||||
<string name="quick_action_delete_dialog_btn">حذف</string>
|
||||
<string name="quick_action_block">بلاک</string>
|
||||
@@ -970,9 +964,7 @@
|
||||
<string name="push_server_none_explainer">غیرفعال سازی اعلان ها</string>
|
||||
<string name="push_server_uses_app_explainer">از اپلیکیشن %1$s استفاده می کند</string>
|
||||
<string name="push_server_install_app">تنظیمات اعلان ها</string>
|
||||
<string name="push_server_install_app_description">برای دریافت اعلان ها، می توانید هر اپلیکیشنی که از [Unified Push](https://unifiedpush.org/) پشتیبانی می کند نصب کنید، مانند[Ntfy](https://ntfy.sh/).
|
||||
پس از نصب، اپلیکیشنی را که می خواهید استفاده کنید در تنظیمات انتخاب کنید.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">برای دریافت اعلان ها، می توانید هر اپلیکیشنی که از [Unified Push](https://unifiedpush.org/) پشتیبانی می کند نصب کنید، مانند[Ntfy](https://ntfy.sh/). پس از نصب، اپلیکیشنی را که می خواهید استفاده کنید در تنظیمات انتخاب کنید.</string>
|
||||
<string name="thread_title">رسته</string>
|
||||
<string name="send_the_seller_a_message">به فروشنده پیغام دهید</string>
|
||||
<string name="hi_there_is_this_still_available">سلام، هنوز موجوده؟</string>
|
||||
@@ -1315,10 +1307,7 @@
|
||||
<string name="show_nprofile_as_a_qr_code">نمایش nprofile به عنوان کد QR</string>
|
||||
<string name="dm_relays_not_found">تنظیم رله های صندوق دریافت خصوصی</string>
|
||||
<string name="dm_relays_not_found_description">با این تنظیمات همه می توانند بدانند که هنگام ارسال پیام به شما از کدام رله ها استفاده کنند. بدون این تنظیمات ممکن است برخی پیام ها را از دست بدهید.</string>
|
||||
<string name="dm_relays_not_found_examples2">گزینه های خوب:
|
||||
- inbox.nostr.wine (پولی)
|
||||
- auth.nostr1.com (رایگان)
|
||||
- you.nostr1.com (رله شخصی - پولی)</string>
|
||||
<string name="dm_relays_not_found_examples2">گزینه های خوب: - inbox.nostr.wine (پولی) - auth.nostr1.com (رایگان) - you.nostr1.com (رله شخصی - پولی)</string>
|
||||
<string name="dm_relays_not_found_editing">از ۱ تا ۳ رله به عنوان رله خصوصی وارد کنید. رله های صندوق دربافت پیام های خصوصی می بایست هر پیامی از هرکس را بپذیرند، ولی تنها به شما اجازه بارگیری پیام ها را می دهند.</string>
|
||||
<string name="dm_relays_not_found_create_now">هم اکنون تنظیم شود</string>
|
||||
<string name="recipient_missing_dm_relays">relay های صندوق ورودی DM یافت نشد. پیامها تحویل داده نمیشوند تا زمانی که لیست relay خود را پیکربندی کنند.</string>
|
||||
@@ -1345,7 +1334,7 @@
|
||||
<string name="zap_the_devs_title">به توسعه دهندگان رپ دهید!</string>
|
||||
<string name="zap_the_devs_description">هدیه شما به ما برای تاثیرگذاری کمک می کند. هر ساتوشی به حساب می آید!</string>
|
||||
<string name="donate_now">اکنون کمک کنید</string>
|
||||
<string name="brought_to_you_by">تقدیم از طرف: </string>
|
||||
<string name="brought_to_you_by">تقدیم از طرف:</string>
|
||||
<string name="this_version_brought_to_you_by">این نسخه نرمافزار پیشکش از:</string>
|
||||
<string name="version_name">نسخه %1$s</string>
|
||||
<string name="thank_you">متشکریم!</string>
|
||||
@@ -2025,7 +2014,7 @@
|
||||
<string name="copied_note_id_to_clipboard">(@note1)شناسه یادداشت در کلیپبورد کپی شد</string>
|
||||
<string name="copied_note_text_to_clipboard">یادداشت در کلیپبورد کپی شد</string>
|
||||
<string name="copied_to_clipboard">در کلیپبورد کپی شد</string>
|
||||
<string name="copied_user_id_to_clipboard">@npubنویسنده در کلیپبورد کپی شد </string>
|
||||
<string name="copied_user_id_to_clipboard">@npubنویسنده در کلیپبورد کپی شد</string>
|
||||
<string name="copy_my_secret_key">کلید خصوصیم را کپی کن</string>
|
||||
<string name="copy_to_clipboard">کپی به کلیپبورد</string>
|
||||
<string name="could_not_assemble_lnurl_from_lightning_address_check_the_user_s_setup">LNUrl از آدرس لایتنینگ "%1$s" بدست نیامد. تنظیمات کاربر را بررسی کنید.</string>
|
||||
@@ -2034,15 +2023,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">صورتحساب از %1$s گرفته نشد: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">فایل فشرده باز نشد</string>
|
||||
<string name="couldnt_find_nwc_wallets">کیف پول یافت نشد</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst هیچ برنامه کیف پولی که از Nostr Wallet Connect (NWC) پشتیبانی کند پیدا نکرد.
|
||||
\n\nکارهایی که میتوانید انجام دهید:
|
||||
\n\t1. بررسی پشتیبانی NWC: مطمئن شوید که برنامه کیف پول مورد نظر شما با Nostr Wallet Connect سازگار است.
|
||||
\n\t2. ایجاد اتصال: به برنامه کیف پول خود بروید و یک اتصال NWC جدید ایجاد کنید.
|
||||
\n\t3. اتصال به Amethyst: کیف پول شما معمولاً سه گزینه ارائه میدهد:
|
||||
\n\t\t3.1 اتصال خودکار: دکمهای برای باز کردن و اتصال خودکار به Amethyst. اگر این گزینه وجود دارد، آن دکمه را بزنید، Amethyst را باز کنید و روی صفحه جدید ذخیره کنید.
|
||||
\n\t\t3.2 اتصال دستی: یک URI اتصال که میتوانید کپی کنید و با کلیک روی آیکون paste در این صفحه مستقیماً وارد کنید.
|
||||
\n\t\t3.3 کد QR: کیف پول یک کد QR ایجاد میکند که میتوانید با دکمه کد QR در این صفحه آن را بخوانید.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst هیچ برنامه کیف پولی که از Nostr Wallet Connect (NWC) پشتیبانی کند پیدا نکرد. \n\nکارهایی که میتوانید انجام دهید: \n\t1. بررسی پشتیبانی NWC: مطمئن شوید که برنامه کیف پول مورد نظر شما با Nostr Wallet Connect سازگار است. \n\t2. ایجاد اتصال: به برنامه کیف پول خود بروید و یک اتصال NWC جدید ایجاد کنید. \n\t3. اتصال به Amethyst: کیف پول شما معمولاً سه گزینه ارائه میدهد: \n\t\t3.1 اتصال خودکار: دکمهای برای باز کردن و اتصال خودکار به Amethyst. اگر این گزینه وجود دارد، آن دکمه را بزنید، Amethyst را باز کنید و روی صفحه جدید ذخیره کنید. \n\t\t3.2 اتصال دستی: یک URI اتصال که میتوانید کپی کنید و با کلیک روی آیکون paste در این صفحه مستقیماً وارد کنید. \n\t\t3.3 کد QR: کیف پول یک کد QR ایجاد میکند که میتوانید با دکمه کد QR در این صفحه آن را بخوانید.</string>
|
||||
<string name="create">ساختن</string>
|
||||
<string name="d">روز</string>
|
||||
<string name="danger_zone">منطقه خطر</string>
|
||||
@@ -2689,10 +2670,7 @@
|
||||
<string name="privacy_policy">سیاست حریم خصوصی</string>
|
||||
<string name="private_conversation_notification"><پیام خصوصی رمزگشایی نشد>\\n\nدر یک پیام خصوصی/رمزنگاری شده بین %1$s و %2$s نام شما آمده بود.</string>
|
||||
<string name="private_inbox_section">رله های صندوق دریافت پیام خصوصی</string>
|
||||
<string name="private_inbox_section_explainer">بین ۱-۳ رله به عنوان رله صندوق ورودی خصوصی وارد کنید. دیگران از این رله ها برای ارسال پیام خصوصی به شما استفاده خواهند کرد. رله های صندوق دریافت پیام خصوصی می بایست هر پیامی از هر کسی را بپذیرند، اما فقط بگذارند شما آن ها را بارگیری کنید. انتخاب های خوب شامل:
|
||||
- inbox.nostr.wine (پولی)
|
||||
- auth.nostr1.com (رایگان)
|
||||
- you.nostr1.com (رله پولی یا شخصی)</string>
|
||||
<string name="private_inbox_section_explainer">بین ۱-۳ رله به عنوان رله صندوق ورودی خصوصی وارد کنید. دیگران از این رله ها برای ارسال پیام خصوصی به شما استفاده خواهند کرد. رله های صندوق دریافت پیام خصوصی می بایست هر پیامی از هر کسی را بپذیرند، اما فقط بگذارند شما آن ها را بارگیری کنید. انتخاب های خوب شامل: - inbox.nostr.wine (پولی) - auth.nostr1.com (رایگان) - you.nostr1.com (رله پولی یا شخصی)</string>
|
||||
<string name="private_inbox_section_explainer_profile">کاربر DM ها را روی این relay ها دریافت میکند</string>
|
||||
<string name="private_message">پیام خصوصی</string>
|
||||
<string name="private_note">خصوصی کردن: یادداشت را به صورت gift-wrap فقط برای کاربران مطلعشده ارسال کن</string>
|
||||
@@ -2713,11 +2691,8 @@
|
||||
<string name="proxy_section">relay های پراکسی</string>
|
||||
<string name="proxy_section_explainer">relay های تجمیعکننده که برنامه باید برای دانلود فیدهای شما از آنها استفاده کند، مانند filter.nostr.wine. این جایگزین مدل outbox میشود و باعث میشود برنامه فقط به relay های موجود در لیستهایتان متصل شود.</string>
|
||||
<string name="public_chat">گفتگوی عمومی</string>
|
||||
<string name="public_chat_explainer">گفتگوهای عمومی در ناستر برای همه نمایان هستند
|
||||
می توانند در آن شرکت کنند. آنها برای انجمن های باز درباره موضوعات بهخصوص عالی هستند.
|
||||
نظارت می تواند توسط حذف پست ها از رله ها انجام گیرد</string>
|
||||
<string name="public_chat_relays_explainer">برای میزبانی این گروه ۱تا ۳ رله وارد کنید.
|
||||
کلاینت های ناستر از این تنظیمات استفاده می کنند تا بدانند پیام ها را از کجا بارگیری کنند و به کجا بفرستند.</string>
|
||||
<string name="public_chat_explainer">گفتگوهای عمومی در ناستر برای همه نمایان هستند می توانند در آن شرکت کنند. آنها برای انجمن های باز درباره موضوعات بهخصوص عالی هستند. نظارت می تواند توسط حذف پست ها از رله ها انجام گیرد</string>
|
||||
<string name="public_chat_relays_explainer">برای میزبانی این گروه ۱تا ۳ رله وارد کنید. کلاینت های ناستر از این تنظیمات استفاده می کنند تا بدانند پیام ها را از کجا بارگیری کنند و به کجا بفرستند.</string>
|
||||
<string name="public_chat_relays_title">رله ها</string>
|
||||
<string name="public_chat_title">فراداده گفتگوی عمومی</string>
|
||||
<string name="public_chats">گفتگوهای عمومی</string>
|
||||
@@ -2742,10 +2717,7 @@
|
||||
<string name="read_only_user">کاربر با امکان خواندن فقط</string>
|
||||
<string name="record_a_message_description">برای ضبط پیام کلیک کنید و نگه دارید</string>
|
||||
<string name="relay_chat">گفتگوی relay</string>
|
||||
<string name="relay_chat_explainer">گفتگوهای relay گروههای چت هستند که توسط relay خانگی خود کنترل میشوند.
|
||||
آنها برای همه در Nostr قابل مشاهده هستند و هر کسی میتواند در آنها شرکت کند.
|
||||
آنها برای جوامع باز حول موضوعات خاص عالی هستند. برخی از این گروهها ناپایدار
|
||||
هستند و بنابراین پیامهای چت با گذشت زمان ناپدید میشوند</string>
|
||||
<string name="relay_chat_explainer">گفتگوهای relay گروههای چت هستند که توسط relay خانگی خود کنترل میشوند. آنها برای همه در Nostr قابل مشاهده هستند و هر کسی میتواند در آنها شرکت کند. آنها برای جوامع باز حول موضوعات خاص عالی هستند. برخی از این گروهها ناپایدار هستند و بنابراین پیامهای چت با گذشت زمان ناپدید میشوند</string>
|
||||
<string name="relay_chat_title">گفتگوهای relay</string>
|
||||
<string name="relay_management_tab_events">رویدادها</string>
|
||||
<string name="relay_management_tab_ips">آدرسهای IP</string>
|
||||
@@ -2903,7 +2875,7 @@
|
||||
<string name="tor_use_new_relays_explainer">تور را برای رله های ارسال/دریافت الزامی کن</string>
|
||||
<string name="tor_use_nip05_verification">تایید آدرس ناستر</string>
|
||||
<string name="tor_use_nip05_verification_explainer">تور را برای تایید آدرس های NIP-05 الزامی کن</string>
|
||||
<string name="tor_use_onion_address">رله ها / آدرس های Onion </string>
|
||||
<string name="tor_use_onion_address">رله ها / آدرس های Onion</string>
|
||||
<string name="tor_use_onion_address_explainer">از تور برای هر آدرس اونیون استفاده کن</string>
|
||||
<string name="tor_use_profile_pictures">تصاویر نمایه</string>
|
||||
<string name="tor_use_profile_pictures_explainer">تور را برای بارگیری تصاویر نمایه اجباری کن</string>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<string name="quote">نقل قول</string>
|
||||
<string name="fork">فورک</string>
|
||||
<string name="new_amount_in_sats">مبلغ جدید به ساتوشی</string>
|
||||
<string name="replying_to"> پاسخ به</string>
|
||||
<string name="replying_to">پاسخ به</string>
|
||||
<string name="and"> و </string>
|
||||
<string name="following">دنبال شونده</string>
|
||||
<string name="followers">دنبال کننده</string>
|
||||
@@ -211,7 +211,7 @@
|
||||
<string name="copy_user_id">کپی شناسه کاربر</string>
|
||||
<string name="unblock_user">از بلاک درآوردن کاربر</string>
|
||||
<string name="user_is_blocked_hidden">این کاربر مسدود/بیصدا شده است. پستهای آنها مخفی است.</string>
|
||||
<string name="npub_hex_username">npub, hex, نام کاربری </string>
|
||||
<string name="npub_hex_username">npub, hex, نام کاربری</string>
|
||||
<string name="clear">پاک کردن</string>
|
||||
<string name="app_logo">لوگوی اپ</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex کلید خصوصی</string>
|
||||
@@ -233,7 +233,7 @@
|
||||
<string name="chats_reply_searching_history">در حال جستجوی پیام اصلی…</string>
|
||||
<string name="chats_reply_not_found">این پیام پیدا نشد</string>
|
||||
<string name="chats_reply_searched">همه relay ها جستجو شد · برای مشاهده ضربه بزنید</string>
|
||||
<string name="error_loading_replies"> :خطا در بارگیری پاسخ ها</string>
|
||||
<string name="error_loading_replies">:خطا در بارگیری پاسخ ها</string>
|
||||
<string name="try_again">دوباره تلاش کنید</string>
|
||||
<string name="notification_feed_is_empty">هنوز هیچ اعلانی نیست.</string>
|
||||
<string name="open_poll">نظرسنجی باز</string>
|
||||
@@ -259,14 +259,8 @@
|
||||
<string name="mark_all_known_as_read">همه شناس ها خوانده شده کن</string>
|
||||
<string name="mark_all_new_as_read">همه جدیدها را خوانده شده کن</string>
|
||||
<string name="mark_all_as_read">همه را خوانده شده کن</string>
|
||||
<string name="account_backup_tips2_md">نکات ایمنی و ذخیره کلید
|
||||
|
||||
حساب کاربری شما با یک کلید خصوصی محافظت می شود. این کلید دنباله ای بلند از کاراکترها است که با **nsec1** آغاز می گردد. هر کس به این کلید خصوصی دسترسی داشته باشد می تواند بجای شما یادداشت پست کرده یا هویت شما را تغییر دهد.
|
||||
هرگز کلید خصوصی خود را در هیچ وبسایت با نرم افزاری که به آن اطمینان ندارید **وارد نکنید**.
|
||||
سازندگان امتیست **هرگز** کلیدتان را از شما نمی خواهند.
|
||||
یک پشتیبان یدکی مخفی از کلید خود به منظور بازیابی **نگه دارید**. ما استفاده از نرم افزار مدیریت پسورد را توصیه می کنیم.</string>
|
||||
<string name="account_backup_tips3_md">برای ایمنی بیشتر، می توانید کلید خود را با یک رمزعبور رمزنگاری کنید. این نوع کلید با **ncryptsec1** آغاز می شود و نمی تواند بدون رمز عبور شما استفاده شود.
|
||||
اگر پسوردتان را گم کنید، نخواهید توانست کلیدتان را بازیابی کنید.</string>
|
||||
<string name="account_backup_tips2_md">نکات ایمنی و ذخیره کلید حساب کاربری شما با یک کلید خصوصی محافظت می شود. این کلید دنباله ای بلند از کاراکترها است که با **nsec1** آغاز می گردد. هر کس به این کلید خصوصی دسترسی داشته باشد می تواند بجای شما یادداشت پست کرده یا هویت شما را تغییر دهد. هرگز کلید خصوصی خود را در هیچ وبسایت با نرم افزاری که به آن اطمینان ندارید **وارد نکنید**. سازندگان امتیست **هرگز** کلیدتان را از شما نمی خواهند. یک پشتیبان یدکی مخفی از کلید خود به منظور بازیابی **نگه دارید**. ما استفاده از نرم افزار مدیریت پسورد را توصیه می کنیم.</string>
|
||||
<string name="account_backup_tips3_md">برای ایمنی بیشتر، می توانید کلید خود را با یک رمزعبور رمزنگاری کنید. این نوع کلید با **ncryptsec1** آغاز می شود و نمی تواند بدون رمز عبور شما استفاده شود. اگر پسوردتان را گم کنید، نخواهید توانست کلیدتان را بازیابی کنید.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">رمزنگاری و کپی کلید من</string>
|
||||
<string name="badge_award_image_for">تصویر مدال پاداش برای %1$s</string>
|
||||
<string name="badge_award_image">تصویر جایزه نشان</string>
|
||||
@@ -286,7 +280,7 @@
|
||||
<string name="quick_action_request_deletion_gallery_title">حذف از گالری</string>
|
||||
<string name="quick_action_request_deletion_gallery_alert_body_v2">این رسانه را از گالری خود حذف کنید.</string>
|
||||
<string name="quick_action_request_deletion_alert_title">درخواست حذف</string>
|
||||
<string name="quick_action_request_deletion_alert_body">آماتیست درخواست می کند که یادداشت شما از رله هایی که درحال حاضر به آن متصل هستید حذف شود. هیچ تضمینی نیست که یادداشت شما برای همیشه از آن رله ها یا از رله های دیگری که ممکن است در آنها ذخیره شده باشد حذف خواهد شد.. </string>
|
||||
<string name="quick_action_request_deletion_alert_body">آماتیست درخواست می کند که یادداشت شما از رله هایی که درحال حاضر به آن متصل هستید حذف شود. هیچ تضمینی نیست که یادداشت شما برای همیشه از آن رله ها یا از رله های دیگری که ممکن است در آنها ذخیره شده باشد حذف خواهد شد..</string>
|
||||
<string name="quick_action_block_dialog_btn">بلاک</string>
|
||||
<string name="quick_action_delete_dialog_btn">حذف</string>
|
||||
<string name="quick_action_block">بلاک</string>
|
||||
@@ -959,9 +953,7 @@
|
||||
<string name="push_server_none_explainer">غیرفعال سازی اعلان ها</string>
|
||||
<string name="push_server_uses_app_explainer">از اپلیکیشن %1$s استفاده می کند</string>
|
||||
<string name="push_server_install_app">تنظیمات اعلان ها</string>
|
||||
<string name="push_server_install_app_description">برای دریافت اعلان ها، می توانید هر اپلیکیشنی که از [Unified Push](https://unifiedpush.org/) پشتیبانی می کند نصب کنید، مانند[Ntfy](https://ntfy.sh/).
|
||||
پس از نصب، اپلیکیشنی را که می خواهید استفاده کنید در تنظیمات انتخاب کنید.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">برای دریافت اعلان ها، می توانید هر اپلیکیشنی که از [Unified Push](https://unifiedpush.org/) پشتیبانی می کند نصب کنید، مانند[Ntfy](https://ntfy.sh/). پس از نصب، اپلیکیشنی را که می خواهید استفاده کنید در تنظیمات انتخاب کنید.</string>
|
||||
<string name="thread_title">رسته</string>
|
||||
<string name="send_the_seller_a_message">به فروشنده پیغام دهید</string>
|
||||
<string name="hi_there_is_this_still_available">سلام، هنوز موجوده؟</string>
|
||||
@@ -1313,10 +1305,7 @@
|
||||
<string name="show_nprofile_as_a_qr_code">نمایش nprofile به عنوان کد QR</string>
|
||||
<string name="dm_relays_not_found">تنظیم رله های صندوق دریافت خصوصی</string>
|
||||
<string name="dm_relays_not_found_description">با این تنظیمات همه می توانند بدانند که هنگام ارسال پیام به شما از کدام رله ها استفاده کنند. بدون این تنظیمات ممکن است برخی پیام ها را از دست بدهید.</string>
|
||||
<string name="dm_relays_not_found_examples2">گزینه های خوب:
|
||||
- inbox.nostr.wine (پولی)
|
||||
- auth.nostr1.com (رایگان)
|
||||
- you.nostr1.com (رله شخصی - پولی)</string>
|
||||
<string name="dm_relays_not_found_examples2">گزینه های خوب: - inbox.nostr.wine (پولی) - auth.nostr1.com (رایگان) - you.nostr1.com (رله شخصی - پولی)</string>
|
||||
<string name="dm_relays_not_found_editing">از ۱ تا ۳ رله به عنوان رله خصوصی وارد کنید. رله های صندوق دربافت پیام های خصوصی می بایست هر پیامی از هرکس را بپذیرند، ولی تنها به شما اجازه بارگیری پیام ها را می دهند.</string>
|
||||
<string name="dm_relays_not_found_create_now">هم اکنون تنظیم شود</string>
|
||||
<string name="recipient_missing_dm_relays">relay های صندوق ورودی DM یافت نشد. پیامها تحویل داده نمیشوند تا زمانی که لیست relay خود را پیکربندی کنند.</string>
|
||||
@@ -1343,7 +1332,7 @@
|
||||
<string name="zap_the_devs_title">به توسعه دهندگان رپ دهید!</string>
|
||||
<string name="zap_the_devs_description">هدیه شما به ما برای تاثیرگذاری کمک می کند. هر ساتوشی به حساب می آید!</string>
|
||||
<string name="donate_now">اکنون کمک کنید</string>
|
||||
<string name="brought_to_you_by">تقدیم از طرف: </string>
|
||||
<string name="brought_to_you_by">تقدیم از طرف:</string>
|
||||
<string name="this_version_brought_to_you_by">این نسخه نرمافزار پیشکش از:</string>
|
||||
<string name="version_name">نسخه %1$s</string>
|
||||
<string name="thank_you">متشکریم!</string>
|
||||
@@ -2048,7 +2037,7 @@
|
||||
<string name="copied_note_id_to_clipboard">(@note1)شناسه یادداشت در کلیپبورد کپی شد</string>
|
||||
<string name="copied_note_text_to_clipboard">یادداشت در کلیپبورد کپی شد</string>
|
||||
<string name="copied_to_clipboard">در کلیپبورد کپی شد</string>
|
||||
<string name="copied_user_id_to_clipboard">@npubنویسنده در کلیپبورد کپی شد </string>
|
||||
<string name="copied_user_id_to_clipboard">@npubنویسنده در کلیپبورد کپی شد</string>
|
||||
<string name="copy_my_secret_key">کلید خصوصیم را کپی کن</string>
|
||||
<string name="copy_to_clipboard">کپی به کلیپبورد</string>
|
||||
<string name="could_not_assemble_lnurl_from_lightning_address_check_the_user_s_setup">LNUrl از آدرس لایتنینگ "%1$s" بدست نیامد. تنظیمات کاربر را بررسی کنید.</string>
|
||||
@@ -2057,15 +2046,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">صورتحساب از %1$s گرفته نشد: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">فایل فشرده باز نشد</string>
|
||||
<string name="couldnt_find_nwc_wallets">کیف پول یافت نشد</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst هیچ برنامه کیف پولی که از Nostr Wallet Connect (NWC) پشتیبانی کند پیدا نکرد.
|
||||
\n\nکارهایی که میتوانید انجام دهید:
|
||||
\n\t1. بررسی پشتیبانی NWC: مطمئن شوید که برنامه کیف پول مورد نظر شما با Nostr Wallet Connect سازگار است.
|
||||
\n\t2. ایجاد اتصال: به برنامه کیف پول خود بروید و یک اتصال NWC جدید ایجاد کنید.
|
||||
\n\t3. اتصال به Amethyst: کیف پول شما معمولاً سه گزینه ارائه میدهد:
|
||||
\n\t\t3.1 اتصال خودکار: دکمهای برای باز کردن و اتصال خودکار به Amethyst. اگر این گزینه وجود دارد، آن دکمه را بزنید، Amethyst را باز کنید و روی صفحه جدید ذخیره کنید.
|
||||
\n\t\t3.2 اتصال دستی: یک URI اتصال که میتوانید کپی کنید و با کلیک روی آیکون paste در این صفحه مستقیماً وارد کنید.
|
||||
\n\t\t3.3 کد QR: کیف پول یک کد QR ایجاد میکند که میتوانید با دکمه کد QR در این صفحه آن را بخوانید.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst هیچ برنامه کیف پولی که از Nostr Wallet Connect (NWC) پشتیبانی کند پیدا نکرد. \n\nکارهایی که میتوانید انجام دهید: \n\t1. بررسی پشتیبانی NWC: مطمئن شوید که برنامه کیف پول مورد نظر شما با Nostr Wallet Connect سازگار است. \n\t2. ایجاد اتصال: به برنامه کیف پول خود بروید و یک اتصال NWC جدید ایجاد کنید. \n\t3. اتصال به Amethyst: کیف پول شما معمولاً سه گزینه ارائه میدهد: \n\t\t3.1 اتصال خودکار: دکمهای برای باز کردن و اتصال خودکار به Amethyst. اگر این گزینه وجود دارد، آن دکمه را بزنید، Amethyst را باز کنید و روی صفحه جدید ذخیره کنید. \n\t\t3.2 اتصال دستی: یک URI اتصال که میتوانید کپی کنید و با کلیک روی آیکون paste در این صفحه مستقیماً وارد کنید. \n\t\t3.3 کد QR: کیف پول یک کد QR ایجاد میکند که میتوانید با دکمه کد QR در این صفحه آن را بخوانید.</string>
|
||||
<string name="create">ساختن</string>
|
||||
<string name="d">روز</string>
|
||||
<string name="danger_zone">منطقه خطر</string>
|
||||
@@ -2732,10 +2713,7 @@
|
||||
<string name="privacy_policy">سیاست حریم خصوصی</string>
|
||||
<string name="private_conversation_notification"><پیام خصوصی رمزگشایی نشد>\\n\nدر یک پیام خصوصی/رمزنگاری شده بین %1$s و %2$s نام شما آمده بود.</string>
|
||||
<string name="private_inbox_section">رله های صندوق دریافت پیام خصوصی</string>
|
||||
<string name="private_inbox_section_explainer">بین ۱-۳ رله به عنوان رله صندوق ورودی خصوصی وارد کنید. دیگران از این رله ها برای ارسال پیام خصوصی به شما استفاده خواهند کرد. رله های صندوق دریافت پیام خصوصی می بایست هر پیامی از هر کسی را بپذیرند، اما فقط بگذارند شما آن ها را بارگیری کنید. انتخاب های خوب شامل:
|
||||
- inbox.nostr.wine (پولی)
|
||||
- auth.nostr1.com (رایگان)
|
||||
- you.nostr1.com (رله پولی یا شخصی)</string>
|
||||
<string name="private_inbox_section_explainer">بین ۱-۳ رله به عنوان رله صندوق ورودی خصوصی وارد کنید. دیگران از این رله ها برای ارسال پیام خصوصی به شما استفاده خواهند کرد. رله های صندوق دریافت پیام خصوصی می بایست هر پیامی از هر کسی را بپذیرند، اما فقط بگذارند شما آن ها را بارگیری کنید. انتخاب های خوب شامل: - inbox.nostr.wine (پولی) - auth.nostr1.com (رایگان) - you.nostr1.com (رله پولی یا شخصی)</string>
|
||||
<string name="private_inbox_section_explainer_profile">کاربر DM ها را روی این relay ها دریافت میکند</string>
|
||||
<string name="private_message">پیام خصوصی</string>
|
||||
<string name="private_note">خصوصی کردن: یادداشت را به صورت gift-wrap فقط برای کاربران مطلعشده ارسال کن</string>
|
||||
@@ -2782,10 +2760,7 @@
|
||||
<string name="read_only_user">کاربر با امکان خواندن فقط</string>
|
||||
<string name="record_a_message_description">برای ضبط پیام کلیک کنید و نگه دارید</string>
|
||||
<string name="relay_chat">گفتگوی relay</string>
|
||||
<string name="relay_chat_explainer">گفتگوهای relay گروههای چت هستند که توسط relay خانگی خود کنترل میشوند.
|
||||
آنها برای همه در Nostr قابل مشاهده هستند و هر کسی میتواند در آنها شرکت کند.
|
||||
آنها برای جوامع باز حول موضوعات خاص عالی هستند. برخی از این گروهها ناپایدار
|
||||
هستند و بنابراین پیامهای چت با گذشت زمان ناپدید میشوند</string>
|
||||
<string name="relay_chat_explainer">گفتگوهای relay گروههای چت هستند که توسط relay خانگی خود کنترل میشوند. آنها برای همه در Nostr قابل مشاهده هستند و هر کسی میتواند در آنها شرکت کند. آنها برای جوامع باز حول موضوعات خاص عالی هستند. برخی از این گروهها ناپایدار هستند و بنابراین پیامهای چت با گذشت زمان ناپدید میشوند</string>
|
||||
<string name="relay_chat_title">گفتگوهای relay</string>
|
||||
<string name="relay_management_tab_events">رویدادها</string>
|
||||
<string name="relay_management_tab_ips">آدرسهای IP</string>
|
||||
@@ -2943,7 +2918,7 @@
|
||||
<string name="tor_use_new_relays_explainer">تور را برای رله های ارسال/دریافت الزامی کن</string>
|
||||
<string name="tor_use_nip05_verification">تایید آدرس ناستر</string>
|
||||
<string name="tor_use_nip05_verification_explainer">تور را برای تایید آدرس های NIP-05 الزامی کن</string>
|
||||
<string name="tor_use_onion_address">رله ها / آدرس های Onion </string>
|
||||
<string name="tor_use_onion_address">رله ها / آدرس های Onion</string>
|
||||
<string name="tor_use_onion_address_explainer">از تور برای هر آدرس اونیون استفاده کن</string>
|
||||
<string name="tor_use_profile_pictures">تصاویر نمایه</string>
|
||||
<string name="tor_use_profile_pictures_explainer">تور را برای بارگیری تصاویر نمایه اجباری کن</string>
|
||||
|
||||
@@ -268,15 +268,8 @@
|
||||
<string name="mark_all_known_as_read">Merkitse kaikki Tunnetut luetuiksi</string>
|
||||
<string name="mark_all_new_as_read">Merkitse kaikki Uudet luetuiksi</string>
|
||||
<string name="mark_all_as_read">Merkitse kaikki luetuiksi</string>
|
||||
<string name="account_backup_tips2_md"> ## Avainten varmuuskopiointi ja turvallisuusvinkit
|
||||
\n\nTilisi on suojattu salaisella avaimella. Avain on pitkä merkkijono, joka alkaa **nsec1**:llä. Kuka tahansa, jolla on pääsy tähän salaiseen avaimeen, voi julkaista ja muuttaa henkilöllisyyttäsi.
|
||||
\n\n- **Älä** anna salaista avaintasi mihinkään verkkosivustoon tai ohjelmistoon, johon et luota.
|
||||
\n- Amethystin kehittäjät eivät **koskaan** pyydä salaista avaintasi.
|
||||
\n- **Tee** turvallinen varmuuskopio salaisesta avaimestasi tilin palauttamista varten. Suosittelemme salasananhallintaohjelman käyttöä.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Lisäturvallisuuden vuoksi voit salata avaimesi salasanalla. Tämä avain alkaa **ncryptsec1**:llä eikä sitä voi käyttää ilman salasanaasi.
|
||||
\n\nJos kadotat salasanasi, et pysty palauttamaan avaintasi.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Avainten varmuuskopiointi ja turvallisuusvinkit \n\nTilisi on suojattu salaisella avaimella. Avain on pitkä merkkijono, joka alkaa **nsec1**:llä. Kuka tahansa, jolla on pääsy tähän salaiseen avaimeen, voi julkaista ja muuttaa henkilöllisyyttäsi. \n\n- **Älä** anna salaista avaintasi mihinkään verkkosivustoon tai ohjelmistoon, johon et luota. \n- Amethystin kehittäjät eivät **koskaan** pyydä salaista avaintasi. \n- **Tee** turvallinen varmuuskopio salaisesta avaimestasi tilin palauttamista varten. Suosittelemme salasananhallintaohjelman käyttöä.</string>
|
||||
<string name="account_backup_tips3_md">Lisäturvallisuuden vuoksi voit salata avaimesi salasanalla. Tämä avain alkaa **ncryptsec1**:llä eikä sitä voi käyttää ilman salasanaasi. \n\nJos kadotat salasanasi, et pysty palauttamaan avaintasi.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Salaa ja kopioi salainen avaimeni</string>
|
||||
<string name="badge_award_image_for">Merkki kohteelle %1$s</string>
|
||||
<string name="badge_award_image">"Merkkipalkinnon kuva</string>
|
||||
@@ -959,8 +952,7 @@
|
||||
<string name="push_server_none_explainer">Poistaa Push-ilmoitukset käytöstä</string>
|
||||
<string name="push_server_uses_app_explainer">Käyttää sovellusta %1$s</string>
|
||||
<string name="push_server_install_app">Push-ilmoituksen asennus</string>
|
||||
<string name="push_server_install_app_description"> Saadaksesi push-ilmoituksia, asenna mikä tahansa sovellus, joka tukee Unified Push:ia, kuten Ntfy.
|
||||
Asennuksen jälkeen valitse Asetuksista sovellus, jota haluat käyttää.</string>
|
||||
<string name="push_server_install_app_description">Saadaksesi push-ilmoituksia, asenna mikä tahansa sovellus, joka tukee Unified Push:ia, kuten Ntfy. Asennuksen jälkeen valitse Asetuksista sovellus, jota haluat käyttää.</string>
|
||||
<string name="thread_title">Keskusteluketju</string>
|
||||
<string name="send_the_seller_a_message">Lähetä myyjälle viesti</string>
|
||||
<string name="hi_there_is_this_still_available">Hei, onko tämä vielä saatavilla?</string>
|
||||
@@ -2011,15 +2003,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Laskun hakeminen epäonnistui kohteesta %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Pakattua tiedostoa ei voitu avata</string>
|
||||
<string name="couldnt_find_nwc_wallets">Lompakkoa ei löydy</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ei löytänyt yhtään lompakkosovellusta, joka tukee Nostr Wallet Connect (NWC) -toimintoa.
|
||||
\n\nMitä voit tehdä:
|
||||
\n\t1. Tarkista NWC-tuki: Varmista, että haluamasi lompakkosovellus on yhteensopiva Nostr Wallet Connectin kanssa.
|
||||
\n\t2. Luo yhteys: Siirry lompakkosovellukseesi ja luo uusi NWC-yhteys.
|
||||
\n\t3. Linkitä Amethystiin: Lompakkosi tarjoaa yleensä kolme vaihtoehtoa:
|
||||
\n\t\t3.1 Automaattinen linkitys: Painike, joka avaa Amethystin ja yhdistää automaattisesti. Jos näet sen, paina painiketta, avaa Amethyst ja tallenna uudella näytöllä.
|
||||
\n\t\t3.2 Manuaalinen linkitys: YhteysURI, jonka voit kopioida ja liittää tämän näytön liitä-kuvakkeella.
|
||||
\n\t\t3.3 QR-koodi: Lompakko luo QR-koodin, jonka voit lukea tämän näytön QR-koodipainikkeella.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst ei löytänyt yhtään lompakkosovellusta, joka tukee Nostr Wallet Connect (NWC) -toimintoa. \n\nMitä voit tehdä: \n\t1. Tarkista NWC-tuki: Varmista, että haluamasi lompakkosovellus on yhteensopiva Nostr Wallet Connectin kanssa. \n\t2. Luo yhteys: Siirry lompakkosovellukseesi ja luo uusi NWC-yhteys. \n\t3. Linkitä Amethystiin: Lompakkosi tarjoaa yleensä kolme vaihtoehtoa: \n\t\t3.1 Automaattinen linkitys: Painike, joka avaa Amethystin ja yhdistää automaattisesti. Jos näet sen, paina painiketta, avaa Amethyst ja tallenna uudella näytöllä. \n\t\t3.2 Manuaalinen linkitys: YhteysURI, jonka voit kopioida ja liittää tämän näytön liitä-kuvakkeella. \n\t\t3.3 QR-koodi: Lompakko luo QR-koodin, jonka voit lukea tämän näytön QR-koodipainikkeella.</string>
|
||||
<string name="create">Luo</string>
|
||||
<string name="d">pv</string>
|
||||
<string name="danger_zone">Vaara-alue</string>
|
||||
@@ -2677,11 +2661,8 @@
|
||||
<string name="proxy_section">Proxy-relait</string>
|
||||
<string name="proxy_section_explainer">Aggregaattorirelait, joita sovelluksen täytyy käyttää feedien lataamiseen, kuten filter.nostr.wine. Tämä korvaa outbox-mallin ja saa sovelluksen yhdistämään vain listoissasi oleviin relaihin.</string>
|
||||
<string name="public_chat">Julkinen keskustelu</string>
|
||||
<string name="public_chat_explainer">Julkiset chatit ovat näkyvissä kaikille Nostrissa ja kuka tahansa
|
||||
voi osallistua niihin. Ne sopivat hyvin avoimiin yhteisöihin tiettyjen aiheiden ympärille.
|
||||
Moderointia voidaan hallita poistamalla julkaisuja sen relay-palvelimilta</string>
|
||||
<string name="public_chat_relays_explainer">Syötä 1–3 relay-palvelinta, jotka isännöivät tätä ryhmää.
|
||||
Nostr-asiakkaat käyttävät tätä asetusta tietääkseen, mistä ladata viestejä ja mihin lähettää viestisi.</string>
|
||||
<string name="public_chat_explainer">Julkiset chatit ovat näkyvissä kaikille Nostrissa ja kuka tahansa voi osallistua niihin. Ne sopivat hyvin avoimiin yhteisöihin tiettyjen aiheiden ympärille. Moderointia voidaan hallita poistamalla julkaisuja sen relay-palvelimilta</string>
|
||||
<string name="public_chat_relays_explainer">Syötä 1–3 relay-palvelinta, jotka isännöivät tätä ryhmää. Nostr-asiakkaat käyttävät tätä asetusta tietääkseen, mistä ladata viestejä ja mihin lähettää viestisi.</string>
|
||||
<string name="public_chat_relays_title">relay-palvelimet</string>
|
||||
<string name="public_chat_title">Julkisen chatin metatiedot</string>
|
||||
<string name="public_chats">Julkiset keskustelut</string>
|
||||
@@ -2706,10 +2687,7 @@
|
||||
<string name="read_only_user">Vain luku -käyttäjä</string>
|
||||
<string name="record_a_message_description">Paina ja pidä pohjassa tallentaaksesi ääniviesti</string>
|
||||
<string name="relay_chat">relay-chat</string>
|
||||
<string name="relay_chat_explainer">relay-chatit ovat chat-ryhmiä, joita hallinnoi niiden kotipalvelin.
|
||||
Ne ovat näkyvissä kaikille Nostrissa ja kuka tahansa voi osallistua niihin.
|
||||
Ne sopivat hyvin avoimiin yhteisöihin tiettyjen aiheiden ympärille. Osa näistä ryhmistä on katoavia,
|
||||
joten chat-viestit häviävät ajan myötä</string>
|
||||
<string name="relay_chat_explainer">relay-chatit ovat chat-ryhmiä, joita hallinnoi niiden kotipalvelin. Ne ovat näkyvissä kaikille Nostrissa ja kuka tahansa voi osallistua niihin. Ne sopivat hyvin avoimiin yhteisöihin tiettyjen aiheiden ympärille. Osa näistä ryhmistä on katoavia, joten chat-viestit häviävät ajan myötä</string>
|
||||
<string name="relay_chat_title">relay-chatit</string>
|
||||
<string name="relay_management_tab_events">Tapahtumat</string>
|
||||
<string name="relay_management_tab_ips">IP-osoitteet</string>
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
<string name="copy_user_id">Copier l'ID utilisateur</string>
|
||||
<string name="unblock_user">Débloquer l'utilisateur</string>
|
||||
<string name="user_is_blocked_hidden">Cet utilisateur est bloqué/muet. Ses publications sont masquées.</string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur </string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur</string>
|
||||
<string name="clear">Nettoyer</string>
|
||||
<string name="app_logo">Logo de l'App</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex private key</string>
|
||||
@@ -266,15 +266,8 @@
|
||||
<string name="mark_all_known_as_read">Marquer tous les Connus comme lu</string>
|
||||
<string name="mark_all_new_as_read">Marquer tous les Nouveaux comme lu</string>
|
||||
<string name="mark_all_as_read">Tout marquer comme lu</string>
|
||||
<string name="account_backup_tips2_md"> ## Sauvegarde des Clés et Conseils de Sécurité
|
||||
\n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité.
|
||||
\n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance.
|
||||
\n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète.
|
||||
\n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe.
|
||||
\n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Sauvegarde des Clés et Conseils de Sécurité \n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité. \n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance. \n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète. \n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.</string>
|
||||
<string name="account_backup_tips3_md">Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe. \n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Chiffrer et copier ma clé secrète</string>
|
||||
<string name="badge_award_image_for">Image de badge pour %1$s</string>
|
||||
<string name="badge_award_image">Image du badge de récompense</string>
|
||||
@@ -823,7 +816,7 @@
|
||||
<string name="max_subs">Souscription maximale</string>
|
||||
<string name="max_filters_per_sub">Nombre maximum de filtres par sub</string>
|
||||
<string name="max_limit_events_returning">Limite Max (Renvoi des Évènements)</string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID </string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID</string>
|
||||
<string name="cashu_mint_label">Mint : %1$s</string>
|
||||
<string name="cashu_redeem">Échanger</string>
|
||||
<string name="cashu_copy_token">Copier le Jeton</string>
|
||||
@@ -938,9 +931,7 @@
|
||||
<string name="push_server_none_explainer">Désactive les Notifications Push</string>
|
||||
<string name="push_server_uses_app_explainer">Utilise l'application %1$s</string>
|
||||
<string name="push_server_install_app">Configuration des Notifications Push</string>
|
||||
<string name="push_server_install_app_description"> Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/).
|
||||
Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/). Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.</string>
|
||||
<string name="thread_title">Fil de discussion</string>
|
||||
<string name="send_the_seller_a_message">Envoyer un message au vendeur</string>
|
||||
<string name="hi_there_is_this_still_available">Bonjour, est-ce toujours disponible ?</string>
|
||||
@@ -2603,11 +2594,8 @@
|
||||
<string name="proxy_section">Relais Proxy</string>
|
||||
<string name="proxy_section_explainer">Relais agrégateurs que l'application doit utiliser pour télécharger vos flux, tels que filter.nostr.wine. Cela remplace le modèle de boîte d'envoi et permettra à l'application de se connecter uniquement aux relais de vos listes.</string>
|
||||
<string name="public_chat">Chat public</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui
|
||||
peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques.
|
||||
La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe.
|
||||
Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques. La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe. Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_relays_title">Relais</string>
|
||||
<string name="public_chat_title">Métadonnées de tchat public</string>
|
||||
<string name="public_chats">Chats publics</string>
|
||||
@@ -2632,10 +2620,7 @@
|
||||
<string name="read_only_user">Utilisateur en lecture seule</string>
|
||||
<string name="record_a_message_description">Cliquez et maintenez pour enregistrer un message</string>
|
||||
<string name="relay_chat">Relais de discussion</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine.
|
||||
Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer.
|
||||
Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères
|
||||
et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine. Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer. Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_title">Relais de discussions</string>
|
||||
<string name="relay_management_tab_events">Événements</string>
|
||||
<string name="relay_management_tab_pubkeys">Utilisateurs</string>
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
<string name="copy_user_id">Copier l'ID utilisateur</string>
|
||||
<string name="unblock_user">Débloquer l'utilisateur</string>
|
||||
<string name="user_is_blocked_hidden">Cet utilisateur est bloqué/muet. Ses publications sont masquées.</string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur </string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur</string>
|
||||
<string name="clear">Nettoyer</string>
|
||||
<string name="app_logo">Logo de l'App</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex private key</string>
|
||||
@@ -268,15 +268,8 @@
|
||||
<string name="mark_all_known_as_read">Marquer tous les Connus comme lu</string>
|
||||
<string name="mark_all_new_as_read">Marquer tous les Nouveaux comme lu</string>
|
||||
<string name="mark_all_as_read">Tout marquer comme lu</string>
|
||||
<string name="account_backup_tips2_md"> ## Sauvegarde des Clés et Conseils de Sécurité
|
||||
\n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité.
|
||||
\n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance.
|
||||
\n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète.
|
||||
\n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe.
|
||||
\n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Sauvegarde des Clés et Conseils de Sécurité \n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité. \n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance. \n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète. \n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.</string>
|
||||
<string name="account_backup_tips3_md">Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe. \n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Chiffrer et copier ma clé secrète</string>
|
||||
<string name="badge_award_image_for">Image de badge pour %1$s</string>
|
||||
<string name="badge_award_image">Image du badge de récompense</string>
|
||||
@@ -905,7 +898,7 @@
|
||||
<string name="max_subs">Souscription maximale</string>
|
||||
<string name="max_filters_per_sub">Nombre maximum de filtres par sub</string>
|
||||
<string name="max_limit_events_returning">Limite Max (Renvoi des Évènements)</string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID </string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID</string>
|
||||
<string name="cashu_mint_label">Mint : %1$s</string>
|
||||
<string name="cashu_redeem">Échanger</string>
|
||||
<string name="cashu_copy_token">Copier le Jeton</string>
|
||||
@@ -1039,9 +1032,7 @@
|
||||
<string name="push_server_none_explainer">Désactive les Notifications Push</string>
|
||||
<string name="push_server_uses_app_explainer">Utilise l'application %1$s</string>
|
||||
<string name="push_server_install_app">Configuration des Notifications Push</string>
|
||||
<string name="push_server_install_app_description"> Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/).
|
||||
Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/). Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.</string>
|
||||
<string name="thread_title">Fil de discussion</string>
|
||||
<string name="send_the_seller_a_message">Envoyer un message au vendeur</string>
|
||||
<string name="hi_there_is_this_still_available">Bonjour, est-ce toujours disponible ?</string>
|
||||
@@ -2883,11 +2874,8 @@
|
||||
<string name="proxy_section">Relais Proxy</string>
|
||||
<string name="proxy_section_explainer">Relais agrégateurs que l'application doit utiliser pour télécharger vos flux, tels que filter.nostr.wine. Cela remplace le modèle de boîte d'envoi et permettra à l'application de se connecter uniquement aux relais de vos listes.</string>
|
||||
<string name="public_chat">Chat public</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui
|
||||
peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques.
|
||||
La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe.
|
||||
Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques. La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe. Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_relays_title">Relais</string>
|
||||
<string name="public_chat_title">Métadonnées de tchat public</string>
|
||||
<string name="public_chats">Chats publics</string>
|
||||
@@ -2912,10 +2900,7 @@
|
||||
<string name="read_only_user">Utilisateur en lecture seule</string>
|
||||
<string name="record_a_message_description">Cliquez et maintenez pour enregistrer un message</string>
|
||||
<string name="relay_chat">Relais de discussion</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine.
|
||||
Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer.
|
||||
Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères
|
||||
et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine. Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer. Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_title">Relais de discussions</string>
|
||||
<string name="relay_group_flag_private">Privé</string>
|
||||
<string name="relay_management_tab_events">Événements</string>
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
<string name="copy_user_id">Copier l'ID utilisateur</string>
|
||||
<string name="unblock_user">Débloquer l'utilisateur</string>
|
||||
<string name="user_is_blocked_hidden">Cet utilisateur est bloqué/muet. Ses publications sont masquées.</string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur </string>
|
||||
<string name="npub_hex_username">npub, hex, nom d'utilisateur</string>
|
||||
<string name="clear">Nettoyer</string>
|
||||
<string name="app_logo">Logo de l'App</string>
|
||||
<string name="nsec_npub_hex_private_key">nsec / npub / hex private key</string>
|
||||
@@ -259,15 +259,8 @@
|
||||
<string name="mark_all_known_as_read">Marquer tous les Connus comme lu</string>
|
||||
<string name="mark_all_new_as_read">Marquer tous les Nouveaux comme lu</string>
|
||||
<string name="mark_all_as_read">Tout marquer comme lu</string>
|
||||
<string name="account_backup_tips2_md"> ## Sauvegarde des Clés et Conseils de Sécurité
|
||||
\n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité.
|
||||
\n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance.
|
||||
\n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète.
|
||||
\n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe.
|
||||
\n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Sauvegarde des Clés et Conseils de Sécurité \n\nVotre compte est sécurisé par une clé secrète. La clé est une longue séquence de caractères commençant par **nsec1**. Toute personne ayant accès à cette clé secrète peut publier et modifier votre identité. \n\n- Ne mettez **pas** votre clé secrète sur un site web ou un logiciel auquel vous ne faites pas confiance. \n- Les développeurs d'Amethyst ne vous demanderont **jamais** votre clé secrète. \n- **Faites** une sauvegarde sécurisée de votre clé secrète pour la récupération de votre compte. Nous vous recommandons d'utiliser un gestionnaire de mots de passe.</string>
|
||||
<string name="account_backup_tips3_md">Pour plus de sécurité, vous pouvez chiffrer votre clé avec un mot de passe. Cette clé commence par **ncryptsec1** et ne peut être utilisée sans votre mot de passe. \n\nSi vous perdez votre mot de passe, vous ne pourrez pas récupérer votre clé.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Chiffrer et copier ma clé secrète</string>
|
||||
<string name="badge_award_image_for">Image de badge pour %1$s</string>
|
||||
<string name="badge_award_image">Image du badge de récompense</string>
|
||||
@@ -844,7 +837,7 @@
|
||||
<string name="max_subs">Souscription maximale</string>
|
||||
<string name="max_filters_per_sub">Nombre maximum de filtres par sub</string>
|
||||
<string name="max_limit_events_returning">Limite Max (Renvoi des Évènements)</string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID </string>
|
||||
<string name="max_subid_length">Longueur maximale du SubID</string>
|
||||
<string name="cashu_mint_label">Mint : %1$s</string>
|
||||
<string name="cashu_redeem">Échanger</string>
|
||||
<string name="cashu_copy_token">Copier le Jeton</string>
|
||||
@@ -960,9 +953,7 @@
|
||||
<string name="push_server_none_explainer">Désactive les Notifications Push</string>
|
||||
<string name="push_server_uses_app_explainer">Utilise l'application %1$s</string>
|
||||
<string name="push_server_install_app">Configuration des Notifications Push</string>
|
||||
<string name="push_server_install_app_description"> Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/).
|
||||
Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Pour recevoir des notifications push, installez n'importe quelle application qui supporte les [Unified Push](https://unifiedpush.org/), tel que [Ntfy](https://ntfy.sh/). Après installation, sélectionnez l'application que vous voulez utiliser dans les Paramètres.</string>
|
||||
<string name="thread_title">Fil de discussion</string>
|
||||
<string name="send_the_seller_a_message">Envoyer un message au vendeur</string>
|
||||
<string name="hi_there_is_this_still_available">Bonjour, est-ce toujours disponible ?</string>
|
||||
@@ -2743,11 +2734,8 @@
|
||||
<string name="proxy_section">Relais Proxy</string>
|
||||
<string name="proxy_section_explainer">Relais agrégateurs que l'application doit utiliser pour télécharger vos flux, tels que filter.nostr.wine. Cela remplace le modèle de boîte d'envoi et permettra à l'application de se connecter uniquement aux relais de vos listes.</string>
|
||||
<string name="public_chat">Chat public</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui
|
||||
peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques.
|
||||
La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe.
|
||||
Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_explainer">Les conversations publiques sont visibles pour tout le monde sur Nostr et n'importe qui peut y participer. Elles sont idéales pour les communautés ouvertes autour de sujets spécifiques. La modération peut être contrôlée en supprimant les messages sur ses relais</string>
|
||||
<string name="public_chat_relays_explainer">Insérez entre 1 et 3 relais qui hébergent ce groupe. Les clients Nostr utilisent ce paramètre pour savoir où télécharger les messages et où les envoyer.</string>
|
||||
<string name="public_chat_relays_title">Relais</string>
|
||||
<string name="public_chat_title">Métadonnées de tchat public</string>
|
||||
<string name="public_chats">Chats publics</string>
|
||||
@@ -2772,10 +2760,7 @@
|
||||
<string name="read_only_user">Utilisateur en lecture seule</string>
|
||||
<string name="record_a_message_description">Cliquez et maintenez pour enregistrer un message</string>
|
||||
<string name="relay_chat">Relais de discussion</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine.
|
||||
Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer.
|
||||
Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères
|
||||
et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_explainer">Les relais de discussions sont des groupes de discussion contrôlés par leur relais d'origine. Ils sont visibles par tous les utilisateurs de Nostr et tout le monde peut y participer. Ils sont idéaux pour les communautés ouvertes autour de sujets spécifiques. Certains de ces groupes sont éphémères et, par conséquent, les messages de discussion disparaissent avec le temps</string>
|
||||
<string name="relay_chat_title">Relais de discussions</string>
|
||||
<string name="relay_management_tab_events">Événements</string>
|
||||
<string name="relay_management_tab_ips">IPs</string>
|
||||
|
||||
@@ -646,15 +646,8 @@
|
||||
<string name="mark_all_known_as_read">सब ज्ञात को पढ लिया चिह्नित करें</string>
|
||||
<string name="mark_all_new_as_read">सब नये को पढ लिया चिह्नित करें</string>
|
||||
<string name="mark_all_as_read">सब को पढ लिया चिह्नित करें</string>
|
||||
<string name="account_backup_tips2_md">## कुंचिका सुरक्षार्थ अनुकृति तथा सुरक्षा सुझाव
|
||||
\n\nआपकी लेखा एक गुप्त कुंचिका से सुरक्षित किया गया है। कुंचिका अक्षरों की एक लम्बी श्रृंखला है जो **nsec1** से आरम्भ होता है। जिस किसी के पास यह कुंचिका है वह पत्र प्रकाशित कर सकेगा तथा आपका परिचय परिवर्तित कर सकेगा।
|
||||
\n\n- आपकी गुप्त कुंचिका किसी भी जालस्थान अथवा क्रमक में **ना** डालें जिसपर आपका विश्वास ना हो।
|
||||
\n- अमेथिस्ट क्रमलेख विकासकर्ता आपकी गुप्त कुंचिका **कभी नहीं** पूछेंगे।
|
||||
\n- आपकी गुप्त कुंचिका की एक सुरक्षित अनुकृति **अवश्य** रखें अपनी लेखा पुनः प्राप्त करने के लिए। पारणशब्ध प्रबंधन क्रमक की पुनः प्रशंसा करते हैं।
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> अधिक सुरक्षा के लिए आप अपनी कुंचिका का रहस्यीकरण कर सकते हैं एक पारणशब्द के साथ। यह कुंचिका आरम्भ होगी **ncryptsec1** से तथा पारणशब्द के बिना प्रयोग साध्य नहीं।
|
||||
\n\n यदि आप अपना पारणशब्द खो देते हैं, तो आप अपनी कुंचिका को पुनः प्राप्त नहीं कर सकते।
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## कुंचिका सुरक्षार्थ अनुकृति तथा सुरक्षा सुझाव \n\nआपकी लेखा एक गुप्त कुंचिका से सुरक्षित किया गया है। कुंचिका अक्षरों की एक लम्बी श्रृंखला है जो **nsec1** से आरम्भ होता है। जिस किसी के पास यह कुंचिका है वह पत्र प्रकाशित कर सकेगा तथा आपका परिचय परिवर्तित कर सकेगा। \n\n- आपकी गुप्त कुंचिका किसी भी जालस्थान अथवा क्रमक में **ना** डालें जिसपर आपका विश्वास ना हो। \n- अमेथिस्ट क्रमलेख विकासकर्ता आपकी गुप्त कुंचिका **कभी नहीं** पूछेंगे। \n- आपकी गुप्त कुंचिका की एक सुरक्षित अनुकृति **अवश्य** रखें अपनी लेखा पुनः प्राप्त करने के लिए। पारणशब्ध प्रबंधन क्रमक की पुनः प्रशंसा करते हैं।</string>
|
||||
<string name="account_backup_tips3_md">अधिक सुरक्षा के लिए आप अपनी कुंचिका का रहस्यीकरण कर सकते हैं एक पारणशब्द के साथ। यह कुंचिका आरम्भ होगी **ncryptsec1** से तथा पारणशब्द के बिना प्रयोग साध्य नहीं। \n\n यदि आप अपना पारणशब्द खो देते हैं, तो आप अपनी कुंचिका को पुनः प्राप्त नहीं कर सकते।</string>
|
||||
<string name="backup_keys_nudge_title">अपने कुंचिकाओं को सुरक्षित रखें</string>
|
||||
<string name="backup_keys_nudge_body">आपकी गुप्त कुंचिका एकमात्र विधि है इस लेखा का अभिगमन करने के लिए। यदि आप इसे खो देते हैं तो इसे कभी भी पुनःप्राप्त नहीं कर सकते। इसे कहीं सुरक्षित रखें अभी इस समय।</string>
|
||||
<string name="backup_keys_nudge_backup_now">अभी इसी समय सुरक्षित अनुकृति बनाएँ</string>
|
||||
@@ -1834,9 +1827,7 @@
|
||||
<string name="push_server_none_explainer">प्रेषित सूचनाएँ अक्षम करता है</string>
|
||||
<string name="push_server_uses_app_explainer">%1$s क्रमक का प्रयोग करता है</string>
|
||||
<string name="push_server_install_app">प्रेषित सूचना स्थापन</string>
|
||||
<string name="push_server_install_app_description"> प्रेषित सूचनाएँ प्राप्त करने के लिए, किसी भी क्रमक की स्थापना करें जो [संयुक्त प्रेषण](https://unifiedpush.org/) का अवलम्बन करता है, जैसे [एनटीफै](https://ntfy.sh/)।
|
||||
स्थापना पश्चात, जिस क्रमक का उपयोग करना चाहते हैं उसका चयन करें स्थापना विकल्पों में।
|
||||
</string>
|
||||
<string name="push_server_install_app_description">प्रेषित सूचनाएँ प्राप्त करने के लिए, किसी भी क्रमक की स्थापना करें जो [संयुक्त प्रेषण](https://unifiedpush.org/) का अवलम्बन करता है, जैसे [एनटीफै](https://ntfy.sh/)। स्थापना पश्चात, जिस क्रमक का उपयोग करना चाहते हैं उसका चयन करें स्थापना विकल्पों में।</string>
|
||||
<string name="thread_title">सूत्र</string>
|
||||
<string name="send_the_seller_a_message">विक्रेता को संदेश भेजें</string>
|
||||
<string name="hi_there_is_this_still_available">नमस्ते, क्या यह अब भी उपलब्ध है?</string>
|
||||
@@ -3585,17 +3576,9 @@
|
||||
<string name="could_not_fetch_invoice_from_details">चालान नहीं लाया जा सका %1$s से : %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">संकुचित अभिलेख को खोल नहीं पाए</string>
|
||||
<string name="couldnt_find_nwc_wallets">धनकोष अप्राप्त</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">अमेथिस्ट को कोई धनकोष क्रमक प्राप्य नहीं जो नोस्टर धनकोष संयोजन का अवलम्बन करता हो।
|
||||
\n\nआप यह कर सकते हैं :
|
||||
\n\t१॰ नोस्टर धनकोष संयोजन अवलम्बन का सत्यापन करें। दुबारा जाँचें की आपका मनचाहा धनकोष क्रमक नोस्टर धनकोष संयोजन के साथ संगत है।
|
||||
\n\t२॰ संयोजन बनाएँ। आपके धनकोष क्रमक में जाकर एक नया नोस्टर धनकोष संयोजन बनाएँ।
|
||||
\n\t३॰ अमेथिस्ट के साथ जोडें। आपका धनकोष क्रमक सामान्यतः तीन विकल्प देगा।
|
||||
\n\t\t३॰१ स्वचालित जोड। एक घुण्डी जिससे स्वचालित रूप से खोलें तथा अमेथिस्ट से जोडें। यदि हो तो उस घुण्डी को टाँकें तथा अमेथिस्ट खोलें तथा नव्य पटल पर अभिलेखन करें।
|
||||
\n\t\t३॰२ मनुष्यकृत जोड। एक संयोजन वैश्विकसंसाधनपरिचायक जिसकी अनुकृति करके सीधे इस पटल पर प्रविष्ट कर सकते हैं।
|
||||
\n\t\t३॰३ क्यूआर॰ चित्र अक्षरराशि। धनकोष क्रमक एक क्यूआर॰ चित्र अक्षरराशि बनएगा जिसे आप परख सकते हैं इस पटल पर क्यूआर॰ क्रमचित्र घुण्डी द्वारा।
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">अमेथिस्ट को कोई धनकोष क्रमक प्राप्य नहीं जो नोस्टर धनकोष संयोजन का अवलम्बन करता हो। \n\nआप यह कर सकते हैं : \n\t१॰ नोस्टर धनकोष संयोजन अवलम्बन का सत्यापन करें। दुबारा जाँचें की आपका मनचाहा धनकोष क्रमक नोस्टर धनकोष संयोजन के साथ संगत है। \n\t२॰ संयोजन बनाएँ। आपके धनकोष क्रमक में जाकर एक नया नोस्टर धनकोष संयोजन बनाएँ। \n\t३॰ अमेथिस्ट के साथ जोडें। आपका धनकोष क्रमक सामान्यतः तीन विकल्प देगा। \n\t\t३॰१ स्वचालित जोड। एक घुण्डी जिससे स्वचालित रूप से खोलें तथा अमेथिस्ट से जोडें। यदि हो तो उस घुण्डी को टाँकें तथा अमेथिस्ट खोलें तथा नव्य पटल पर अभिलेखन करें। \n\t\t३॰२ मनुष्यकृत जोड। एक संयोजन वैश्विकसंसाधनपरिचायक जिसकी अनुकृति करके सीधे इस पटल पर प्रविष्ट कर सकते हैं। \n\t\t३॰३ क्यूआर॰ चित्र अक्षरराशि। धनकोष क्रमक एक क्यूआर॰ चित्र अक्षरराशि बनएगा जिसे आप परख सकते हैं इस पटल पर क्यूआर॰ क्रमचित्र घुण्डी द्वारा।</string>
|
||||
<string name="create">बनाएँ</string>
|
||||
<string name="d"> दि॰</string>
|
||||
<string name="d">दि॰</string>
|
||||
<string name="danger_zone">संकट क्षेत्र</string>
|
||||
<string name="dark">अन्धकारमय</string>
|
||||
<string name="description">विवरण</string>
|
||||
@@ -3791,7 +3774,7 @@
|
||||
<string name="git_repositories_search_close">छलनी आवृत</string>
|
||||
<string name="git_repositories_search_open">क्रमलेखकोश छलनी</string>
|
||||
<string name="goal_progress">%1$s वित्तपोषित %2$s साट्स उद्देश्य में से</string>
|
||||
<string name="h"> घं॰</string>
|
||||
<string name="h">घं॰</string>
|
||||
<string name="hash_verification_failed">यह विषयवस्तु परिवर्तित हुआ है। हो सकता है लेखक ने परिवर्तन देखा नहीं अथवा अनुमति दिया नहीं।</string>
|
||||
<string name="hash_verification_info_title">इसका अर्थ क्या है?</string>
|
||||
<string name="hash_verification_passed">यह विषयवस्तु वैसे ही है जैसे पत्र प्रकाशन पर</string>
|
||||
@@ -4080,7 +4063,7 @@
|
||||
<string name="login_with_a_private_key_to_be_able_to_upload">आप ख्याप्य कुंचिका का प्रयोग कर रहे हैं जिससे केवल पढ सकते हैं। आरोहण करने के लिए गुप्त कुंचिका के साथ प्रवेशांकन करें</string>
|
||||
<string name="login_with_a_private_key_to_like_posts">आप ख्याप्य कुंचिका का प्रयोग कर रहे हैं जिससे केवल पढ सकते हैं। प्रकाशित पत्रों को चाहने के लिए गुप्त कुंचिका के साथ प्रवेशांकन करें</string>
|
||||
<string name="longs">चलचित्र</string>
|
||||
<string name="m"> मि॰</string>
|
||||
<string name="m">मि॰</string>
|
||||
<string name="manage_emoji_packs">मेरे भावचिह्न पोटलियाँ</string>
|
||||
<string name="marmot_add_photo">चित्र जोडें</string>
|
||||
<string name="marmot_adding_user">जोडा जा रहा है %1$s…</string>
|
||||
@@ -4711,11 +4694,8 @@
|
||||
<string name="proxy_section">प्रतिनिधि पुनःप्रसारक</string>
|
||||
<string name="proxy_section_explainer">संग्रहकर्ता पुनःप्रसारक जो क्रमक द्वारा उपयुक्त होना चाहिए आपके सूचनावलियों का अवरोहण करने के लिए। जैसे कि filter.nostr.wine । यह निर्गतपेटिका प्रतिरूप को प्रतिस्थापित करेगा तथा क्रमक आपके सूचियों में पुनःप्रसारकों के साथ ही जुडेगा।</string>
|
||||
<string name="public_chat">सार्वजनिक चर्चा</string>
|
||||
<string name="public_chat_explainer">सार्वजनिक चर्चाएँ सबके लिए दृश्यमान हैं नोस्टर पर तथा सभी
|
||||
इनमें भाग ले सकते हैं। ये उत्कृष्ट हैं खुले समुदायों के लिए विशिष्ट विषयों के प्रसंग में।
|
||||
नियमन का नियन्त्रण किया जा सकता है पत्रों को मिटाने से पुनःप्रसारकों में</string>
|
||||
<string name="public_chat_relays_explainer">इस समुदाय के निवास के लिए १ - ३ पुनःप्रसारकों को जोडें।
|
||||
नोस्टर ग्राहक इस स्थापना विकल्प का प्रयोग करेंगे यह जानने के लिए कि कहाँ से सन्देशों का अवरोहण करना है तथा कहाँ आपके सन्देश भेजने हैं।</string>
|
||||
<string name="public_chat_explainer">सार्वजनिक चर्चाएँ सबके लिए दृश्यमान हैं नोस्टर पर तथा सभी इनमें भाग ले सकते हैं। ये उत्कृष्ट हैं खुले समुदायों के लिए विशिष्ट विषयों के प्रसंग में। नियमन का नियन्त्रण किया जा सकता है पत्रों को मिटाने से पुनःप्रसारकों में</string>
|
||||
<string name="public_chat_relays_explainer">इस समुदाय के निवास के लिए १ - ३ पुनःप्रसारकों को जोडें। नोस्टर ग्राहक इस स्थापना विकल्प का प्रयोग करेंगे यह जानने के लिए कि कहाँ से सन्देशों का अवरोहण करना है तथा कहाँ आपके सन्देश भेजने हैं।</string>
|
||||
<string name="public_chat_relays_title">पुनःप्रसारक</string>
|
||||
<string name="public_chat_title">सार्वजनिक चर्चा उपतथ्य</string>
|
||||
<string name="public_chats">सार्वजनिक चर्चा</string>
|
||||
@@ -4780,10 +4760,7 @@
|
||||
<string name="relay_auth_search_keywords">प्रमाण प्रमाणीकरण प्रवेशांकन पुनःप्रसारक हस्ताक्षरण सत्यापन निप॰४२ परिचय</string>
|
||||
<string name="relay_auth_settings_title">पुनःप्रसारक प्रमाणीकरण</string>
|
||||
<string name="relay_chat">पुनःप्रसारक चर्चा</string>
|
||||
<string name="relay_chat_explainer">पुनःप्रसारक चर्चाएँ आवासी पुनःप्रसारक द्वारा नियन्त्रित चर्चा समुदाएँ हैं।
|
||||
वे नोस्टर पर सभी के लिए दृश्य हैं तथा उनमें सभी भाग ले सकते हैं।
|
||||
वे उत्कृष्ट हैं खुले समुदायों के लिए विशिष्ट विषयों पर। इनमें से कुछ समुदाएँ अस्थायी हैं।
|
||||
तथा इसीलिए समय के साथ चर्चा सन्देश अदृश्य हो जाते हैं</string>
|
||||
<string name="relay_chat_explainer">पुनःप्रसारक चर्चाएँ आवासी पुनःप्रसारक द्वारा नियन्त्रित चर्चा समुदाएँ हैं। वे नोस्टर पर सभी के लिए दृश्य हैं तथा उनमें सभी भाग ले सकते हैं। वे उत्कृष्ट हैं खुले समुदायों के लिए विशिष्ट विषयों पर। इनमें से कुछ समुदाएँ अस्थायी हैं। तथा इसीलिए समय के साथ चर्चा सन्देश अदृश्य हो जाते हैं</string>
|
||||
<string name="relay_chat_title">पुनःप्रसारक चर्चाएँ</string>
|
||||
<string name="relay_explain_account_data">आपके अपने परिचय तथा स्थापना विकल्प तथा पाण्डुलिपियाँ। आपके मुख्य पुनःप्रसारकों पर।</string>
|
||||
<string name="relay_explain_community_chats">पुनःप्रसारक जिनपर प्रत्येक समुदाय अपने समतलों को प्रकाशित करते हैं।</string>
|
||||
@@ -5286,4 +5263,322 @@
|
||||
<string name="cyberspace_bag_unsigned">हस्ताक्षररहित। इसलिए यह कर्ता केवल एक कथन है</string>
|
||||
<string name="cyberspace_bag_unknown_kind">प्रकार %1$d का वस्तु। जिसे यह ग्राहक चित्रित नहीं करता</string>
|
||||
<string name="cyberspace_bag_opaque">%1$d अष्टकों का अमुक जिसे यह ग्राहक पढता नहीं</string>
|
||||
<string name="backup_action_block_again">पुनःबाधित करें %1$s को</string>
|
||||
<string name="backup_action_keep_count">रखें %1$s</string>
|
||||
<string name="backup_action_rejoin">पुनःजुडें %1$s</string>
|
||||
<string name="backup_action_remute">पुनःमौन %1$s</string>
|
||||
<string name="backup_action_restore_count">पुनःस्थापन %1$s</string>
|
||||
<string name="backup_action_restore_feeds">सूचनावलियाँ पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_places">स्थल पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_profile">परिचय पुनःस्थापध</string>
|
||||
<string name="backup_action_restore_providers">प्रदाता पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_relays">पुनःप्रसारक पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_topics">विषय पुनःस्थापन</string>
|
||||
<string name="backup_action_restore_wallet">धनकोष पुनःस्थापन</string>
|
||||
<string name="backup_card_accept">स्वीकार</string>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s तथा %2$d जोडा</item>
|
||||
<item quantity="other">%1$s तथा %2$d जोडे</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s तथा %2$d बाधित किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d को बाधित किए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s तथा %2$d का अनुगमन किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d का अनुगमन किए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s तथा %2$d से जुडे</item>
|
||||
<item quantity="other">%1$s तथा %2$d से जुडे</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s तथा %2$d को मौनकृत किया</item>
|
||||
<item quantity="other">%1$s तथा %2$d को मौनकृत किए</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">आपके अमेथिस्ट समचरणीकृत क्रमक स्थापना विकल्पों को परिवर्तित किया गया एक अन्य क्रमक में और वह अमेथिस्ट नहीं था। इससे समस्याएँ उत्पन्न हो सकते हैं।</string>
|
||||
<string name="backup_card_concord_emptied">आपने अपनी कोंकोर्ड सूची रिक्त की</string>
|
||||
<string name="backup_card_concord_rewritten">आपने अपनी कोंकोर्ड सूची का परिवर्तन किया</string>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">आपने %1$d सीधासन्देश पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d सीधासन्देश पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">आपने %1$d इष्ट सूचनावली हटाया</item>
|
||||
<item quantity="other">आपने %1$d इष्ट सूचनावलियों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">आपने %1$d व्यक्ति का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d व्यक्तियों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">आपने %1$d विषयसूचक का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d विषयसूचकों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">आपने %1$d अनुक्रमणीकार पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d अनुक्रमणीकार पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">आपने %1$d समूहचर्चा कुंचिका पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d समूहचर्चा कुंचिका पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">आपने %1$d सार्वजनिक चर्चा छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d सार्वजनिक चर्चाओं को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">आपने %1$d समुदाय छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d समुदायों को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">आपने %1$d समूह छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d समूहों को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">आपने %1$d चर्चाशाला छोड दिया</item>
|
||||
<item quantity="other">आपने %1$d चर्चाशालाओं को छोड दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">आपने %1$d की मौनावस्था हटाया</item>
|
||||
<item quantity="other">आपने %1$d की मौनावस्था हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">आपने %1$d सार्वजनिक पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d सार्वजनिक पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<string name="backup_card_nutzap_key_removed">आपने अपनी नटज्साप कुंचिका को हटाया</string>
|
||||
<string name="backup_card_nutzap_key_replaced">आपने अपनी नटज्साप कुंचिका का प्रतिस्थापन किया</string>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">आपने %1$d नटज्साप टकसाल हटाया</item>
|
||||
<item quantity="other">आपने %1$d नटज्साप टकसालों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">आपने %1$d बोल्ट॰बारह प्रस्ताव हटाया</item>
|
||||
<item quantity="other">आपने %1$d बोल्ट॰बारह प्रस्तावों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">आपने %1$d भुगतान प्राप्त करने की विधि हटाया</item>
|
||||
<item quantity="other">आपने %1$d भुगतान प्राप्त करने के विधियों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">आपने %1$d स्थल का अनुगमन हटाया</item>
|
||||
<item quantity="other">आपने %1$d स्थलों का अनुगमन हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">आपने %1$d निजी पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d निजी पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">आपने %1$d परिचय प्रपत्रस्थान हटाया</item>
|
||||
<item quantity="other">आपने %1$d परिचय प्रपत्रस्थान हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक सूचनावली हटाया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारक सूचनावलियाँ हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">आपने %1$d खोज पुनःप्रसारक हटाया</item>
|
||||
<item quantity="other">आपने %1$d खोज पुनःप्रसारकों को हटाए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">आपने %1$d विश्वाससेवा प्रदाता परिवर्तित किया</item>
|
||||
<item quantity="other">आपने %1$d विश्वाससेवाओं के प्रदाता को परिवर्तित किया</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक पर विश्वास करना रोक दिया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारकों पर विश्वास करना रोक दिए</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">आपने %1$d पुनःप्रसारक अबाधित किया</item>
|
||||
<item quantity="other">आपने %1$d पुनःप्रसारकों को अबाधित किए</item>
|
||||
</plurals>
|
||||
<string name="backup_card_wallet_emptied">आपने अपना काशयू धनकोष रिक्त किया</string>
|
||||
<string name="backup_card_wallet_rewritten">आपने अपने काशयू धनकोष को परिवर्तित किया</string>
|
||||
<string name="backup_conflict_added">जोडे गए (%1$s)</string>
|
||||
<string name="backup_conflict_changed">परिवर्तित (%1$s)</string>
|
||||
<string name="backup_conflict_count_added">%1$s जोडे गए</string>
|
||||
<string name="backup_conflict_count_changed">%1$s परिवर्तित</string>
|
||||
<string name="backup_conflict_count_removed">%1$s हटाए गए</string>
|
||||
<string name="backup_conflict_keep_new">नया संस्करण का उपयोग करें</string>
|
||||
<string name="backup_conflict_private_added">आपने निजी (रहस्यीकृत) वस्तुओं को जोडा।</string>
|
||||
<string name="backup_conflict_private_changed">आपने निजी (रहस्यीकृत) वस्तुओं का परिवर्तन भी किया। उनकी तुलना यहाँ नहीं की जा सकती।</string>
|
||||
<string name="backup_conflict_private_cleared">आपने सभी निजी (रहस्यीकृत) वस्तुओं को हटा दिया।</string>
|
||||
<string name="backup_conflict_relay_read_only">पठनेवशक्य</string>
|
||||
<string name="backup_conflict_relay_read_write">पठन तथा लेखन</string>
|
||||
<string name="backup_conflict_relay_write_only">लेखनेवशक्य</string>
|
||||
<string name="backup_conflict_removed">हटाए गए (%1$s)</string>
|
||||
<string name="backup_conflict_restore_mine">सुरक्षित संस्करण पुनःस्थापन</string>
|
||||
<string name="backup_conflict_title">आपने अपना %1$s अन्य क्रमक में परिवर्तित किया</string>
|
||||
<string name="backup_entry_algo_feed">सूचनावलियाँ</string>
|
||||
<string name="backup_entry_chat_room">चर्चा शालाएँ</string>
|
||||
<string name="backup_entry_community">समुदाय</string>
|
||||
<string name="backup_entry_hashtag">विषयसूचक</string>
|
||||
<string name="backup_entry_identity_claim">सम्बन्धित व्यक्तिगण</string>
|
||||
<string name="backup_entry_location">स्थान</string>
|
||||
<string name="backup_entry_mint">टकसाल</string>
|
||||
<string name="backup_entry_nutzap_key">नटज्साप कुंचिकाएँ</string>
|
||||
<string name="backup_entry_offer">प्रस्ताव</string>
|
||||
<string name="backup_entry_other">अन्य प्रविष्टियाँ</string>
|
||||
<string name="backup_entry_payment_target">भुगतान पते</string>
|
||||
<string name="backup_entry_person">लोग</string>
|
||||
<string name="backup_entry_profile_field">परिचय प्रपत्रस्थान</string>
|
||||
<string name="backup_entry_public_chat">सार्वजनिक चर्चाएँ</string>
|
||||
<string name="backup_entry_relay">पुनःप्रसारक</string>
|
||||
<string name="backup_entry_relay_group">समूह</string>
|
||||
<string name="backup_entry_thread">सूत्र</string>
|
||||
<string name="backup_entry_trust_provider">विश्वाससेवा प्रदाता</string>
|
||||
<string name="backup_entry_word">शब्द</string>
|
||||
<string name="backup_profile_field_about">जानकारी</string>
|
||||
<string name="backup_profile_field_banner">ध्वज</string>
|
||||
<string name="backup_profile_field_birthday">जन्मदिन</string>
|
||||
<string name="backup_profile_field_bot">क्रमचर चिह्न</string>
|
||||
<string name="backup_profile_field_clink_offer">क्लिंक॰ प्रस्ताव</string>
|
||||
<string name="backup_profile_field_display_name">प्रदर्शन नाम</string>
|
||||
<string name="backup_profile_field_lud06">लैटनिंग जालपता</string>
|
||||
<string name="backup_profile_field_lud16">लैटनिंग पता</string>
|
||||
<string name="backup_profile_field_name">प्रयोक्तानाम</string>
|
||||
<string name="backup_profile_field_nip05">नोस्टर पता</string>
|
||||
<string name="backup_profile_field_picture">चित्र</string>
|
||||
<string name="backup_profile_field_pronouns">सर्वनाम</string>
|
||||
<string name="backup_profile_field_website">जालस्थान</string>
|
||||
<string name="backup_review_allowed_tag">अनुमत</string>
|
||||
<string name="backup_review_changed_by_other_app">अन्य क्रमक में परिवर्तित। %1$s</string>
|
||||
<string name="backup_review_concord_body">आपके कोंकोर्ड समुदाय आपके लिए रहस्यीकृत हैं। इसलिए उनकी तुलना यहाँ नहीं की जा सकती। पुनःस्थापन उन्हीं को लौट डालेगा जिनका अभिलेखन इस यन्त्र ने किया।</string>
|
||||
<string name="backup_review_demoted_tag">स्थानान्तरित</string>
|
||||
<string name="backup_review_dropped_count">%1$s परित्यक्त</string>
|
||||
<string name="backup_review_dropped_tag">परित्यक्त</string>
|
||||
<string name="backup_review_encrypted_added">आपने उसे बनाया</string>
|
||||
<string name="backup_review_encrypted_changed">आपने उसे परिवर्तित किया</string>
|
||||
<string name="backup_review_encrypted_cleared">आपने उसे रिक्त किया</string>
|
||||
<string name="backup_review_feed">सूचनावली</string>
|
||||
<string name="backup_review_gone">चला गया</string>
|
||||
<string name="backup_review_hashtags_you_follow">विषयसूचक जिनका आप अनुगमन करते हैं</string>
|
||||
<string name="backup_review_inbox">आगतपेटिका</string>
|
||||
<string name="backup_review_inbox_explainer">जहाँ अन्य आप तक अभिगमन करते हैं</string>
|
||||
<string name="backup_review_joined">जुड गए</string>
|
||||
<string name="backup_review_kept">रखे गए</string>
|
||||
<string name="backup_review_kept_count">%1$s रखे गए</string>
|
||||
<string name="backup_review_key_removed">ग्राहक कुंचिका हटाया गया</string>
|
||||
<string name="backup_review_key_replaced">ग्राहक कुंचिका प्रतिस्थापित</string>
|
||||
<string name="backup_review_key_warning">नटज्साप आगे से इस कुंचिका से बद्ध होंगे। यदि इस यन्त्र में वह नहीं है तो आप सम्भाव्यतः उनको यहाँ नहीं चुका सकते।</string>
|
||||
<string name="backup_review_left">शेष</string>
|
||||
<string name="backup_review_left_tag">शेष</string>
|
||||
<string name="backup_review_listed_tag">सूचीबद्ध</string>
|
||||
<string name="backup_review_moved_tag">स्थानान्तरित</string>
|
||||
<string name="backup_review_names_and_more">%1$s तथा %2$s अधिक</string>
|
||||
<string name="backup_review_new">नया संस्करण</string>
|
||||
<string name="backup_review_new_count">%1$s नए</string>
|
||||
<string name="backup_review_new_count_caption">नव्य</string>
|
||||
<string name="backup_review_new_tag">नव्य</string>
|
||||
<string name="backup_review_newly_blocked">नव्यतः बाधित</string>
|
||||
<string name="backup_review_newly_muted">%1$s नए मौनकृत</string>
|
||||
<string name="backup_review_no_longer_blocked">अब से बाधित नहीं</string>
|
||||
<string name="backup_review_not_set">स्थापित नहीं</string>
|
||||
<string name="backup_review_nothing_here">यहाँ कुछ नहीं</string>
|
||||
<string name="backup_review_offer">बोल्ट॰बारह प्रस्ताव</string>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d प्रस्ताव हटाया गया</item>
|
||||
<item quantity="other">%1$d प्रस्ताव हटाए गए</item>
|
||||
</plurals>
|
||||
<string name="backup_review_outbox">निर्गतपेटिका</string>
|
||||
<string name="backup_review_outbox_explainer">आप जहाँ प्रकाशित करते हैं</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">आपको भुगतान करने की %1$d विधि हटाया गया</item>
|
||||
<item quantity="other">आपको भुगतान करने की %1$d विधियाँ हटाए गए</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">लोग जो आपको भुगतान करते हैं उसी को देखते हैं जो इस सूची में है।</string>
|
||||
<string name="backup_review_places_gone">स्थल हटाए गए</string>
|
||||
<string name="backup_review_places_you_follow">स्थल जिनका आप अनुगमन करते हैं</string>
|
||||
<string name="backup_review_private_added_body">वे अब रहस्यीकृत हैं। जो कि सम्भाव्यतः ऊपर के सार्वजनिक वस्तुओं का गन्तव्य था।</string>
|
||||
<string name="backup_review_private_added_title">आपने वस्तुओं को निजी किया</string>
|
||||
<string name="backup_review_private_changed_body">वे रहस्यीकृत हैं। इसलिए उनकी तुलना यहाँ नहीं की जा सकती।</string>
|
||||
<string name="backup_review_private_changed_title">आपने निजी वस्तुओं का परिवर्तन किया</string>
|
||||
<string name="backup_review_private_wiped_body">वे रहस्यीकृत हैं। इसलिए केवल आप देख सकते हैं कि वे क्या थे। पुनःस्थापन से सब लौटके आ जाएँगे।</string>
|
||||
<string name="backup_review_private_wiped_title">आपने सभी निजी वस्तुओं को हटा दिया</string>
|
||||
<string name="backup_review_receiving_tag">ग्रहण मध्य</string>
|
||||
<string name="backup_review_renamed">पुनःनामकृत</string>
|
||||
<string name="backup_review_renamed_tag">पुनःनामकृत</string>
|
||||
<string name="backup_review_saved">इस यन्त्र पर</string>
|
||||
<string name="backup_review_search_people">%1$s लोग खोजें</string>
|
||||
<string name="backup_review_searching_tag">खोज मध्य</string>
|
||||
<string name="backup_review_service">सेवा</string>
|
||||
<string name="backup_review_service_followers">अनुचर</string>
|
||||
<string name="backup_review_service_rank">श्रेणी</string>
|
||||
<string name="backup_review_service_topics">विषयसूची</string>
|
||||
<string name="backup_review_services_changed">%2$s में से %1$s सेवाएँ परिवर्तित</string>
|
||||
<string name="backup_review_services_changed_explainer">वे अब अन्य व्यक्ति से आते है। अथवा किसी से नहीं</string>
|
||||
<string name="backup_review_still_blocked">अभी भी बाधित</string>
|
||||
<string name="backup_review_storing_tag">अभिलेखन मध्य</string>
|
||||
<string name="backup_review_tab_dropped">परित्यक्त। %1$s</string>
|
||||
<string name="backup_review_tab_edited">सम्पादित। %1$s</string>
|
||||
<string name="backup_review_tab_new">नए। %1$s</string>
|
||||
<string name="backup_review_title_cleared">%1$s पारित</string>
|
||||
<string name="backup_review_title_updated">%1$s अद्यतनकृत</string>
|
||||
<string name="backup_review_topics_gone">विषय हटाए गए</string>
|
||||
<string name="backup_review_trust_warning">श्रेणीयाँ तथा अनुचर गिनती तथा कचरालेख छालन जो आप देखते हैं इन प्रदाताओं से आते हैं।</string>
|
||||
<string name="backup_review_trusted_tag">विश्वसनीय</string>
|
||||
<string name="backup_review_unblocked">%1$s अबाधित</string>
|
||||
<string name="backup_review_unblocked_explainer">अमेथिस्ट पुनः उनसे जुडेगा</string>
|
||||
<string name="backup_review_units_tag">इकाई</string>
|
||||
<string name="backup_review_unmuted">%1$s मौनावस्था हटाए गए</string>
|
||||
<string name="backup_review_unmuted_explainer">ये पुनः आपके सूचनावलियों तक अभिगम्य</string>
|
||||
<string name="backup_review_untrusted_tag">अविश्वसनीय</string>
|
||||
<string name="backup_review_wallet_body">आपके धनकोष के टकसाल तथा कुंचिकाएँ आपके लिए रहस्यीकृत हैं। इसलिए उनकी तुलना वस्तु प्रति वस्तु यहाँ नहीं की जा सकती। पुनःस्थापन उन्हीं को लौट डालेगा जिनका अभिलेखन इस यन्त्र ने किया।</string>
|
||||
<string name="backup_review_was_named">पूर्वतः %1$s था</string>
|
||||
<string name="backup_review_words_and_hashtags">शब्द तथा विषयसूचक</string>
|
||||
<string name="backup_type_app_settings">समचरणीकृत क्रमक स्थापना विकल्प</string>
|
||||
<string name="backup_type_app_settings_explainer">अमेथिस्ट स्थापना विकल्प समचरणीकृत आपके यन्त्रों में। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_blocked_relays">बाधित पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_blocked_relays_explainer">पुनःप्रसारक जिनसे यह क्रमक कभी भी संयोजन नहीं करता।</string>
|
||||
<string name="backup_type_bolt12_offers">बोल्ट॰बारह प्रस्ताव</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">लैटनिंग प्रस्ताव जिनका उपयोग करके अन्य लोग आपको भुगतान करते हैं।</string>
|
||||
<string name="backup_type_cashu_wallet">काशयू धनकोष</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">आपके ईकाश धनकोष स्थापना विकल्प तथा टकसाल। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_communities">समुदाय सूची</string>
|
||||
<string name="backup_type_communities_explainer">समुदाय जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_concord_communities">कोंकोर्ड समुदाय सूची</string>
|
||||
<string name="backup_type_concord_communities_explainer">कोंकोर्ड समुदाय जिनसे आप जुडे। वे रहस्यीकृत हैं। इसलिए केवल उनकी उपस्थिति की तुलना की जा सकती है।</string>
|
||||
<string name="backup_type_dm_relays">सीधासन्देश पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_dm_relays_explainer">जहाँ अन्य आपके निजी सन्देश भेजते हैं।</string>
|
||||
<string name="backup_type_ephemeral_chats">अस्थायी चर्चा सूची</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">अस्थायी चर्चा शालाएँ जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_favorite_algo_feeds">इष्ट सूचनावली सूची</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">कलनविध्यात्मक सूचनावलियाँ जिनको आपने अभिलेखित किया।</string>
|
||||
<string name="backup_type_follow_list">अनुचरण सूची</string>
|
||||
<string name="backup_type_follow_list_explainer">निर्णय करता है किसके पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_geohashes">अनुचरित स्थान</string>
|
||||
<string name="backup_type_geohashes_explainer">स्थान जहाँ से पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_hashtags">अनुचरित विषयसूचक</string>
|
||||
<string name="backup_type_hashtags_explainer">विषयसूचक जिससे युक्त पत्र आपकी मुख्य सूचनावली में प्रकट होंगे।</string>
|
||||
<string name="backup_type_indexer_relays">अनुक्रमणीकार पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_indexer_relays_explainer">पुनःप्रसारक उपयुक्त अन्य लोगों के परिचय तथा पुनःप्रसारक सूचियों को प्राप्त करने के लिए।</string>
|
||||
<string name="backup_type_key_package_relays">समूहचर्चा कुंचिका पुनःप्रसारक</string>
|
||||
<string name="backup_type_key_package_relays_explainer">जहाँ अन्य उन कुंचिकाओं को प्राप्त करते हैं आपको रहस्यीकृत समूहचर्चाओं में जोडने के लिए।</string>
|
||||
<string name="backup_type_mute_list">मौन सूची</string>
|
||||
<string name="backup_type_mute_list_explainer">छिपाता है लोग शब्द विषयसूचक तथा सूत्र उन सब में से जो आप देखते हैं।</string>
|
||||
<string name="backup_type_nutzap_info">नटज्साप प्राप्ती स्थापना विकल्प</string>
|
||||
<string name="backup_type_nutzap_info_explainer">टकसाल तथा कुंचिका जिनका उपयोग अन्य करते हैं आपको नटज्साप भेजने के लिए।</string>
|
||||
<string name="backup_type_other">सूची</string>
|
||||
<string name="backup_type_other_explainer">इस यन्त्र पर अभिलेखित सूची।</string>
|
||||
<string name="backup_type_outbox_inbox_relays">सार्वजनिक पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">सबको बताता है आपके पत्र कहाँ प्राप्त करें तथा आपको उत्तर तथा उल्लेखों को कहाँ भेजें।</string>
|
||||
<string name="backup_type_payment_targets">भुगतान पते</string>
|
||||
<string name="backup_type_payment_targets_explainer">विधियाँ जिनसे अन्य लोग आपको भुगतान कर सके।</string>
|
||||
<string name="backup_type_private_outbox_relays">निजी पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">जहाँ आपके पाण्डुलिपियाँ तथा निजी जानकारी रखे जाते हैं।</string>
|
||||
<string name="backup_type_profile">परिचय</string>
|
||||
<string name="backup_type_profile_explainer">आपका नाम चित्र चरित तथा भुगतान पते। जैसे सब को दिखते हैं वैसे।</string>
|
||||
<string name="backup_type_public_chats">सार्वजनिक चर्चा सूची</string>
|
||||
<string name="backup_type_public_chats_explainer">सार्वजनिक चर्चाएँ जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_relay_feeds">इष्ट पुनःप्रसारक सूचनावलियाँ</string>
|
||||
<string name="backup_type_relay_feeds_explainer">पुनःप्रसारक जिनका आप वीक्षण करते हैं सूचनावलियों के रूप में।</string>
|
||||
<string name="backup_type_relay_groups">समूह सूची</string>
|
||||
<string name="backup_type_relay_groups_explainer">पुनःप्रसारक आधारित समूह जिनसे आप जुडे।</string>
|
||||
<string name="backup_type_search_relays">खोज पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_search_relays_explainer">उपयुक्त पुनःप्रसारक जब आप खोजते हैं।</string>
|
||||
<string name="backup_type_trust_providers">विश्वाससेवा प्रदाता सूची</string>
|
||||
<string name="backup_type_trust_providers_explainer">सेवाएँ जिनपर आप विश्वास करते है आपके लिए लोगों का सत्यापन तथा श्रेणीकरण करने के लिए।</string>
|
||||
<string name="backup_type_trusted_relays">विश्वसनीय पुनःप्रसारक सूची</string>
|
||||
<string name="backup_type_trusted_relays_explainer">पुनःप्रसारक जिनपर आप पर्याप्त विश्वास करते हैं बिना पूछे उनसे संयोजन करने के लिए।</string>
|
||||
</resources>
|
||||
|
||||
@@ -311,7 +311,7 @@
|
||||
<string name="podcast_value_split_percent">%1$d%%</string>
|
||||
<string name="podcast_value_for_value">Értéket az értékért</string>
|
||||
<string name="relay_monitor_rtt_open">Megnyitás</string>
|
||||
<string name="relay_monitor_rtt_read">Olvasás </string>
|
||||
<string name="relay_monitor_rtt_read">Olvasás</string>
|
||||
<string name="relay_monitor_rtt_write">Írás</string>
|
||||
<string name="relay_monitor_network">Hálózat</string>
|
||||
<string name="relay_monitor_relay_type">Típus</string>
|
||||
@@ -461,8 +461,7 @@
|
||||
<string name="send_payment_receipt_section">Zap-igazolás</string>
|
||||
<string name="send_payment_receipt_clink">Közvetlen lightning-fizetés - nem lesz zapigazolás közzétéve a Nostr-on.</string>
|
||||
<string name="send_payment_receipt_onchain">Egy láncon belüli zapigazolás közzé lesz téve a Nostr-on, így a címzett megtalálhatja a kifizetést.</string>
|
||||
<string name="send_payment_receipt_onchain_address">Fizetés közvetlenül a láncon belüli pénztárcából a profil megadott bitcoin-címére (%1$s) - nem lesz zapigazolás közzétéve.
|
||||
</string>
|
||||
<string name="send_payment_receipt_onchain_address">Fizetés közvetlenül a láncon belüli pénztárcából a profil megadott bitcoin-címére (%1$s) - nem lesz zapigazolás közzétéve.</string>
|
||||
<string name="send_payment_receipt_cashu">A nutzap-esemény magát az ecasht kézbesíti, így az mindig közzé lesz téve.</string>
|
||||
<string name="send_payment_requesting_invoice">Számla kérése…</string>
|
||||
<string name="send_payment_requesting_invoice_nostr">Számla kérése a Nostr hálózaton keresztül…</string>
|
||||
@@ -647,15 +646,8 @@
|
||||
<string name="mark_all_known_as_read">Az összes ismert megjelölése olvasottként</string>
|
||||
<string name="mark_all_new_as_read">Az összes új üzenet megjelölése olvasottként</string>
|
||||
<string name="mark_all_as_read">Összes megjelölése olvasottként</string>
|
||||
<string name="account_backup_tips2_md"> ## Kulcs- és biztonsági mentési tippek
|
||||
\n\nFiókját egy titkos kulcs védi. A kulcs egy hosszú véletlenszerű karakterlánc, amely **nsec1**-vel kezdődik. Bárki, aki az Ön titkos kulcsához hozzáfér, az Ön személyazonosságának használatával bármilyen tartalmat közzétehet.
|
||||
\n\n- **Ne** helyezze el a titkos kulcsát olyan webhelyen vagy szoftverben, amelyben nem bízik.
|
||||
\n- Az Amethyst fejlesztői az Ön titkos kulcsát **soha** nem fogják Öntől elkérni.
|
||||
\n- A fiók-helyreállításának érdekében, a titkos kulcsáról **mindig** készítsen biztonsági másolatot. Javasoljuk egy jelszókezelő használatát.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> A nagyobb biztonság érdekében titkosítsa egy jelszóval. A jelszóval védett kulcs **ncryptsec1**-vel kezdődik, és a jelszava nélkül nem használható.
|
||||
\n\nHa elveszíti a jelszavát, nem tudja visszaállítani a kulcsát.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Kulcs- és biztonsági mentési tippek \n\nFiókját egy titkos kulcs védi. A kulcs egy hosszú véletlenszerű karakterlánc, amely **nsec1**-vel kezdődik. Bárki, aki az Ön titkos kulcsához hozzáfér, az Ön személyazonosságának használatával bármilyen tartalmat közzétehet. \n\n- **Ne** helyezze el a titkos kulcsát olyan webhelyen vagy szoftverben, amelyben nem bízik. \n- Az Amethyst fejlesztői az Ön titkos kulcsát **soha** nem fogják Öntől elkérni. \n- A fiók-helyreállításának érdekében, a titkos kulcsáról **mindig** készítsen biztonsági másolatot. Javasoljuk egy jelszókezelő használatát.</string>
|
||||
<string name="account_backup_tips3_md">A nagyobb biztonság érdekében titkosítsa egy jelszóval. A jelszóval védett kulcs **ncryptsec1**-vel kezdődik, és a jelszava nélkül nem használható. \n\nHa elveszíti a jelszavát, nem tudja visszaállítani a kulcsát.</string>
|
||||
<string name="backup_keys_nudge_title">Biztonsági mentés készítése a kulcsokról</string>
|
||||
<string name="backup_keys_nudge_body">A titkos kulcs megadása az egyetlen módja a fiók elérésének. Ha elveszíti, akkor soha nem tudja visszaszerezni. Mentse el biztonságos helyre most.</string>
|
||||
<string name="backup_keys_nudge_backup_now">Biztonsági mentés most</string>
|
||||
@@ -779,7 +771,7 @@
|
||||
<string name="award_badge_remove_recipient">Eltávolítás</string>
|
||||
<string name="badge_untitled">Cím nélküli kitűző</string>
|
||||
<string name="badge_awardees_label">A kitűzőt %1$d érdemelte ki</string>
|
||||
<string name="profile_badges_header">Kitűzők · %1$d </string>
|
||||
<string name="profile_badges_header">Kitűzők · %1$d</string>
|
||||
<string name="profile_badges_description">Válassza ki, hogy a megszerzett kitűzők közül melyek jelenjenek meg a profilban.</string>
|
||||
<string name="profile_badges_empty">Ön még nem kapott kitűzőt.</string>
|
||||
<string name="profile_apps_header">Alkalmazások · %1$d</string>
|
||||
@@ -1835,9 +1827,7 @@
|
||||
<string name="push_server_none_explainer">Push-értesítések letiltása</string>
|
||||
<string name="push_server_uses_app_explainer">%1$s alkalmazást használ</string>
|
||||
<string name="push_server_install_app">Push-értesítések beállítása</string>
|
||||
<string name="push_server_install_app_description"> A push-értesítések fogadásához olyan alkalmazást telepítsen, amely támogatja a [Unified Push](https://unifiedpush.org/), például az [Ntfy](https://ntfy.sh/) alkalmazást.
|
||||
A telepítés után a beállításokban válassza ki a használni kívánt alkalmazást.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">A push-értesítések fogadásához olyan alkalmazást telepítsen, amely támogatja a [Unified Push](https://unifiedpush.org/), például az [Ntfy](https://ntfy.sh/) alkalmazást. A telepítés után a beállításokban válassza ki a használni kívánt alkalmazást.</string>
|
||||
<string name="thread_title">Bejegyzés</string>
|
||||
<string name="send_the_seller_a_message">Üzenet küldése az eladónak</string>
|
||||
<string name="hi_there_is_this_still_available">Tisztelt hölgyem / uram! Ez még aktuális?</string>
|
||||
@@ -3124,7 +3114,7 @@
|
||||
<string name="app_notification_calls_channel_description">Értesítések a bejövő hang- és videóhívásokhoz</string>
|
||||
<string name="app_notification_calls_channel_name">Bejövő hívások</string>
|
||||
<string name="app_notification_chess_challenge_accepted">%1$s elfogadta az Ön sakk-kihívását</string>
|
||||
<string name="app_notification_chess_channel_description">Értesítés a sakkjátékkal kapcsolatos eseményekre </string>
|
||||
<string name="app_notification_chess_channel_description">Értesítés a sakkjátékkal kapcsolatos eseményekre</string>
|
||||
<string name="app_notification_chess_channel_name">Sakk</string>
|
||||
<string name="app_notification_chess_summary">Sakkfrissítések</string>
|
||||
<string name="app_notification_chess_your_turn">%1$s lépett - Ön következik</string>
|
||||
@@ -3586,15 +3576,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Nem sikerült lekérni a számlát a következőtől: %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Nem sikerült megnyitni a tömörített fájlt</string>
|
||||
<string name="couldnt_find_nwc_wallets">Nem található pénztárca</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Az Amethyst nem talált olyan pénztárca-alkalmazást, amely támogatja a Nostr Wallet Connect (NWC) szolgáltatást.
|
||||
\n\nAmit tehet:
|
||||
\n\t1. NWC-támogatás ellenőrzése: Ellenőrizze, hogy a kívánt pénztárca-alkalmazás kompatibilis-e a Nostr Wallet Connect szolgáltatással.
|
||||
\n\t2. Kapcsolat létrehozása: Nyissa meg a pénztárcaalkalmazást, és hozzon létre egy új NWC-kapcsolatot.
|
||||
\n\t3. Kapcsolódás az Amethysthez: A pénztárcája általában három lehetőséget kínál:
|
||||
\n\t\t3.1 Automatikus kapcsolódás: Egy gomb az Amethyst automatikus megnyitásához és kapcsolódáshoz. Koppintson erre a gombra, nyissa meg az Amethyst alkalmazást, és mentse el az új képernyőn.
|
||||
\n\t\t3.2 Kézi kapcsolódás: Egy kapcsolódási cím, amelyet kimásolhat, és a képernyőn található beillesztés gombra koppintva közvetlenül beírhatja.
|
||||
\n\t\t3.3 QR-kód: A pénztárca létrehoz egy QR-kódot, amelyet a képernyőn található QR-kód gombról olvashat be.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Az Amethyst nem talált olyan pénztárca-alkalmazást, amely támogatja a Nostr Wallet Connect (NWC) szolgáltatást. \n\nAmit tehet: \n\t1. NWC-támogatás ellenőrzése: Ellenőrizze, hogy a kívánt pénztárca-alkalmazás kompatibilis-e a Nostr Wallet Connect szolgáltatással. \n\t2. Kapcsolat létrehozása: Nyissa meg a pénztárcaalkalmazást, és hozzon létre egy új NWC-kapcsolatot. \n\t3. Kapcsolódás az Amethysthez: A pénztárcája általában három lehetőséget kínál: \n\t\t3.1 Automatikus kapcsolódás: Egy gomb az Amethyst automatikus megnyitásához és kapcsolódáshoz. Koppintson erre a gombra, nyissa meg az Amethyst alkalmazást, és mentse el az új képernyőn. \n\t\t3.2 Kézi kapcsolódás: Egy kapcsolódási cím, amelyet kimásolhat, és a képernyőn található beillesztés gombra koppintva közvetlenül beírhatja. \n\t\t3.3 QR-kód: A pénztárca létrehoz egy QR-kódot, amelyet a képernyőn található QR-kód gombról olvashat be.</string>
|
||||
<string name="create">Létrehozás</string>
|
||||
<string name="d">n</string>
|
||||
<string name="danger_zone">Kritikus beállítások</string>
|
||||
@@ -3884,7 +3866,7 @@
|
||||
<string name="kind_adventure_reading">Kalandos olvasmány</string>
|
||||
<string name="kind_adventure_scene">Kalandjelenet</string>
|
||||
<string name="kind_app_curation_set">Alkalmazáslista</string>
|
||||
<string name="kind_app_recommendations">Ajánlott alkalmazások </string>
|
||||
<string name="kind_app_recommendations">Ajánlott alkalmazások</string>
|
||||
<string name="kind_appointment">Találkozó</string>
|
||||
<string name="kind_apps">Alkalmazások</string>
|
||||
<string name="kind_appt_rsvp">Időpont-visszaigazolás</string>
|
||||
@@ -4712,11 +4694,8 @@
|
||||
<string name="proxy_section">Proxyzott átjátszók</string>
|
||||
<string name="proxy_section_explainer">Összesítő átjátszók, amelyeket az alkalmazásnak használnia kell a hírfolyamok letöltéséhez, például filter.nostr.wine. Ez helyettesíti a kimeneti modellt, és az alkalmazás csak a listákban szereplő átjátszókhoz fog csatlakozni.</string>
|
||||
<string name="public_chat">Nyilvános csevegés</string>
|
||||
<string name="public_chat_explainer">A nyilvános csevegések mindenki számára láthatóak a Nostr-on, és bárki
|
||||
részt vehet bennük. Ezek kiválóan alkalmasak bizonyos témák köré szerveződő nyílt közösségek számára.
|
||||
A moderálás az átjátszókon lévő hozzászólások törlésével szabályozható</string>
|
||||
<string name="public_chat_relays_explainer">Adjon hozzá 1–3 olyan átjátszót, amelyek kiszolgálják ezt a csoportot.
|
||||
A Nostr-kliensek ezt a beállítást használják arra, hogy tudják, honnan töltsék le az üzeneteket, és hová küldjék az üzeneteket.</string>
|
||||
<string name="public_chat_explainer">A nyilvános csevegések mindenki számára láthatóak a Nostr-on, és bárki részt vehet bennük. Ezek kiválóan alkalmasak bizonyos témák köré szerveződő nyílt közösségek számára. A moderálás az átjátszókon lévő hozzászólások törlésével szabályozható</string>
|
||||
<string name="public_chat_relays_explainer">Adjon hozzá 1–3 olyan átjátszót, amelyek kiszolgálják ezt a csoportot. A Nostr-kliensek ezt a beállítást használják arra, hogy tudják, honnan töltsék le az üzeneteket, és hová küldjék az üzeneteket.</string>
|
||||
<string name="public_chat_relays_title">Átjátszók</string>
|
||||
<string name="public_chat_title">Nyilvános csevegés metaadatai</string>
|
||||
<string name="public_chats">Nyilvános csevegések</string>
|
||||
@@ -4781,10 +4760,7 @@
|
||||
<string name="relay_auth_search_keywords">hitelesítés, átjátszó, aláírás, ellenőrzés, nip-42, azonosság</string>
|
||||
<string name="relay_auth_settings_title">Átjátszó-hitelesítés</string>
|
||||
<string name="relay_chat">Átjátszócsevegés</string>
|
||||
<string name="relay_chat_explainer">Az átjátszócsevegések olyan csevegőcsoportok, amelyeket az otthoni átjátszó irányít.
|
||||
Ezek mindenki számára láthatóak a Nostr-on, és bárki részt vehet rajtuk.
|
||||
Remekül alkalmasak nyitott közösségek kialakítására bizonyos témák körül. Néhány ilyen csoport
|
||||
rövid élettartamú, ezért a csevegési üzenetek idővel eltűnnek</string>
|
||||
<string name="relay_chat_explainer">Az átjátszócsevegések olyan csevegőcsoportok, amelyeket az otthoni átjátszó irányít. Ezek mindenki számára láthatóak a Nostr-on, és bárki részt vehet rajtuk. Remekül alkalmasak nyitott közösségek kialakítására bizonyos témák körül. Néhány ilyen csoport rövid élettartamú, ezért a csevegési üzenetek idővel eltűnnek</string>
|
||||
<string name="relay_chat_title">Átjátszócsevegések</string>
|
||||
<string name="relay_explain_account_data">Saját profil, -beállítások és -piszkozatok a gazda-átjátszókon.</string>
|
||||
<string name="relay_explain_community_chats">Azok az átjátszók, amelyekre az egyes közösségek közzéteszik a terveiket.</string>
|
||||
@@ -5287,4 +5263,322 @@
|
||||
<string name="cyberspace_bag_unsigned">Aláírás nélküli, így ez a szerző csak állítás</string>
|
||||
<string name="cyberspace_bag_unknown_kind">Egy %1$d típusú elem, amelyet ez a kliens nem jelenít meg</string>
|
||||
<string name="cyberspace_bag_opaque">%1$d bájt valamiből, amit ez a kliens nem olvas</string>
|
||||
<string name="backup_action_block_again">%1$s újbóli letiltása</string>
|
||||
<string name="backup_action_keep_count">%1$s megtartása</string>
|
||||
<string name="backup_action_rejoin">Újbóli csatlakozás ehhez: %1$s</string>
|
||||
<string name="backup_action_remute">%1$s újbóli némítása</string>
|
||||
<string name="backup_action_restore_count">%1$s visszaállítása</string>
|
||||
<string name="backup_action_restore_feeds">Hírfolyamok visszaállítása</string>
|
||||
<string name="backup_action_restore_places">Helyek visszaállítása</string>
|
||||
<string name="backup_action_restore_profile">Profil visszaállítása</string>
|
||||
<string name="backup_action_restore_providers">Szolgáltatók visszaállítása</string>
|
||||
<string name="backup_action_restore_relays">Átjátszók visszaállítása</string>
|
||||
<string name="backup_action_restore_topics">Témák visszaállítása</string>
|
||||
<string name="backup_action_restore_wallet">Pénztárca visszaállítása</string>
|
||||
<string name="backup_card_accept">Elfogadás</string>
|
||||
<plurals name="backup_card_and_added">
|
||||
<item quantity="one">%1$s és %2$d hozzáadva</item>
|
||||
<item quantity="other">%1$s és %2$d hozzáadva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_blocked">
|
||||
<item quantity="one">%1$s és %2$d letiltva</item>
|
||||
<item quantity="other">%1$s és %2$d letiltva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_followed">
|
||||
<item quantity="one">%1$s és %2$d követve</item>
|
||||
<item quantity="other">%1$s és %2$d követve</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_joined">
|
||||
<item quantity="one">%1$s és %2$d csatlakozva</item>
|
||||
<item quantity="other">%1$s és %2$d csatlakozva</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_and_muted">
|
||||
<item quantity="one">%1$s és %2$d némítva</item>
|
||||
<item quantity="other">%1$s és %2$d némítva</item>
|
||||
</plurals>
|
||||
<string name="backup_card_app_settings">A szinkronizált Amethyst alkalmazásbeállításai egy másik, nem Amethyst alkalmazásban módosultak. Ez problémákat okozhat.</string>
|
||||
<string name="backup_card_concord_emptied">Ön kiürítette a Concord listáját</string>
|
||||
<string name="backup_card_concord_rewritten">Ön módosította a Concord listáját</string>
|
||||
<plurals name="backup_card_dm_relays_lost">
|
||||
<item quantity="one">Ön %1$d privát üzenetátjátszót távolított el</item>
|
||||
<item quantity="other">%1$d privát üzenet átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_feeds_removed">
|
||||
<item quantity="one">Ön %1$d kedvenc hírfolyamot távolított el</item>
|
||||
<item quantity="other">%1$d kedvenc hírfolyamot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_follows_dropped">
|
||||
<item quantity="one">%1$d személyt nem követ többé</item>
|
||||
<item quantity="other">%1$d személyt nem követ többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_hashtags_unfollowed">
|
||||
<item quantity="one">Ön %1$d kulcsszót nem követ többé</item>
|
||||
<item quantity="other">%1$d hashtaget nem követ többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_indexer_relays_lost">
|
||||
<item quantity="one">Ön %1$d indexelő átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d indexelő átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_key_package_relays_lost">
|
||||
<item quantity="one">Ön %1$d csoportos csevegési kulcsátjátszót távolított el</item>
|
||||
<item quantity="other">%1$d csoportcsevegés kulcs átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_chats">
|
||||
<item quantity="one">Ön %1$d nyilvános csevegést hagyott el</item>
|
||||
<item quantity="other">%1$d nyilvános csevegést hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_communities">
|
||||
<item quantity="one">Ön %1$d közösséget hagyott el</item>
|
||||
<item quantity="other">%1$d közösséget hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_groups">
|
||||
<item quantity="one">Ön %1$d csoportot hagyott el</item>
|
||||
<item quantity="other">%1$d csoportot hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_leave_rooms">
|
||||
<item quantity="one">Ön %1$d csevegőszobát hagyott el</item>
|
||||
<item quantity="other">%1$d csevegőszobát hagyott el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_mutes_visible">
|
||||
<item quantity="one">Ön %1$d dolog némítását oldotta fel</item>
|
||||
<item quantity="other">%1$d dolog némítását oldotta fel</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_nip65_lost">
|
||||
<item quantity="one">Ön %1$d nyilvános átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d nyilvános átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<string name="backup_card_nutzap_key_removed">Ön eltávolította a nutzap kulcsát</string>
|
||||
<string name="backup_card_nutzap_key_replaced">Ön lecserélte a nutzap kulcsát</string>
|
||||
<plurals name="backup_card_nutzap_mints_removed">
|
||||
<item quantity="one">Ön %1$d nutzap pénzverdét távolított el</item>
|
||||
<item quantity="other">%1$d nutzap pénzverdét távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_offers_removed">
|
||||
<item quantity="one">Ön %1$d BOLT12 ajánlatot távolított el</item>
|
||||
<item quantity="other">%1$d BOLT12 ajánlatot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_payment_targets_removed">
|
||||
<item quantity="one">Ön %1$d fizetési módot távolított el</item>
|
||||
<item quantity="other">%1$d fizetési módot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_places_unfollowed">
|
||||
<item quantity="one">Ön %1$d helyet nem követ többé</item>
|
||||
<item quantity="other">%1$d helyet nem követ többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_private_outbox_lost">
|
||||
<item quantity="one">Ön %1$d privát átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d privát átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_profile_lost_fields">
|
||||
<item quantity="one">Ön %1$d profilmezőt távolított el</item>
|
||||
<item quantity="other">%1$d profilmezőt távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_relay_feeds_lost">
|
||||
<item quantity="one">Ön %1$d átjátszó-hírfolyamot távolított el</item>
|
||||
<item quantity="other">%1$d átjátszó hírfolyamot távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_search_relays_lost">
|
||||
<item quantity="one">Ön %1$d kereső átjátszót távolított el</item>
|
||||
<item quantity="other">%1$d kereső átjátszót távolított el</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trust_services_changed">
|
||||
<item quantity="one">Ön %1$d bizalmi szolgáltatás szolgáltatóját módosította</item>
|
||||
<item quantity="other">%1$d bizalmi szolgáltatás szolgáltatóját változtatta meg</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_trusted_lost">
|
||||
<item quantity="one">Ön %1$d átjátszóban nem bízik többé</item>
|
||||
<item quantity="other">%1$d átjátszóban nem bízik többé</item>
|
||||
</plurals>
|
||||
<plurals name="backup_card_unblocked">
|
||||
<item quantity="one">Ön %1$d átjátszó letiltását oldotta fel</item>
|
||||
<item quantity="other">%1$d átjátszó blokkolását oldotta fel</item>
|
||||
</plurals>
|
||||
<string name="backup_card_wallet_emptied">Ön kiürítette a Cashu pénztárcáját</string>
|
||||
<string name="backup_card_wallet_rewritten">Ön módosította a Cashu pénztárcáját</string>
|
||||
<string name="backup_conflict_added">Hozzáadva (%1$s)</string>
|
||||
<string name="backup_conflict_changed">Módosítva (%1$s)</string>
|
||||
<string name="backup_conflict_count_added">%1$s hozzáadva</string>
|
||||
<string name="backup_conflict_count_changed">%1$s módosítva</string>
|
||||
<string name="backup_conflict_count_removed">%1$s eltávolítva</string>
|
||||
<string name="backup_conflict_keep_new">Új verzió használata</string>
|
||||
<string name="backup_conflict_private_added">Ön privát (titkosított) elemeket adott hozzá.</string>
|
||||
<string name="backup_conflict_private_changed">Ön privát (titkosított) elemeket is módosított. Ezek itt nem hasonlíthatók össze.</string>
|
||||
<string name="backup_conflict_private_cleared">Ön eltávolította az összes privát (titkosított) elemet.</string>
|
||||
<string name="backup_conflict_relay_read_only">csak olvasható</string>
|
||||
<string name="backup_conflict_relay_read_write">olvasás és írás</string>
|
||||
<string name="backup_conflict_relay_write_only">csak írható</string>
|
||||
<string name="backup_conflict_removed">Eltávolítva (%1$s)</string>
|
||||
<string name="backup_conflict_restore_mine">Mentett verzió visszaállítása</string>
|
||||
<string name="backup_conflict_title">Ön módosította a következőt: %1$s, egy másik alkalmazásban</string>
|
||||
<string name="backup_entry_algo_feed">Hírfolyamok</string>
|
||||
<string name="backup_entry_chat_room">Csevegőszobák</string>
|
||||
<string name="backup_entry_community">Közösségek</string>
|
||||
<string name="backup_entry_hashtag">Kulcsszavak</string>
|
||||
<string name="backup_entry_identity_claim">Kapcsolt identitások</string>
|
||||
<string name="backup_entry_location">Helyek</string>
|
||||
<string name="backup_entry_mint">Pénzverdék</string>
|
||||
<string name="backup_entry_nutzap_key">Nutzap kulcsok</string>
|
||||
<string name="backup_entry_offer">Ajánlatok</string>
|
||||
<string name="backup_entry_other">Egyéb bejegyzések</string>
|
||||
<string name="backup_entry_payment_target">Fizetési címek</string>
|
||||
<string name="backup_entry_person">Személyek</string>
|
||||
<string name="backup_entry_profile_field">Profilmezők</string>
|
||||
<string name="backup_entry_public_chat">Nyilvános csevegések</string>
|
||||
<string name="backup_entry_relay">Átjátszók</string>
|
||||
<string name="backup_entry_relay_group">Csoportok</string>
|
||||
<string name="backup_entry_thread">Beszélgetések</string>
|
||||
<string name="backup_entry_trust_provider">Bizalmi szolgáltatók</string>
|
||||
<string name="backup_entry_word">Szavak</string>
|
||||
<string name="backup_profile_field_about">Névjegy</string>
|
||||
<string name="backup_profile_field_banner">Borító</string>
|
||||
<string name="backup_profile_field_birthday">Születésnap</string>
|
||||
<string name="backup_profile_field_bot">Bot jelölő</string>
|
||||
<string name="backup_profile_field_clink_offer">CLINK-ajánlat</string>
|
||||
<string name="backup_profile_field_display_name">Megjelenített név</string>
|
||||
<string name="backup_profile_field_lud06">LNURL</string>
|
||||
<string name="backup_profile_field_lud16">Lightning-cím</string>
|
||||
<string name="backup_profile_field_name">Felhasználónév</string>
|
||||
<string name="backup_profile_field_nip05">Nostr-cím</string>
|
||||
<string name="backup_profile_field_picture">Kép</string>
|
||||
<string name="backup_profile_field_pronouns">Névmások</string>
|
||||
<string name="backup_profile_field_website">Weboldal</string>
|
||||
<string name="backup_review_allowed_tag">Engedélyezve</string>
|
||||
<string name="backup_review_changed_by_other_app">Módosítva egy másik alkalmazásban · %1$s</string>
|
||||
<string name="backup_review_concord_body">A Concord közösségei Önhöz vannak titkosítva, így itt nem hasonlíthatók össze. A visszaállítás pontosan azt hozza vissza, amit ez az eszköz mentett.</string>
|
||||
<string name="backup_review_demoted_tag">Áthelyezve</string>
|
||||
<string name="backup_review_dropped_count">%1$s elvetve</string>
|
||||
<string name="backup_review_dropped_tag">Elvetve</string>
|
||||
<string name="backup_review_encrypted_added">Ön hozta létre</string>
|
||||
<string name="backup_review_encrypted_changed">Ön módosította</string>
|
||||
<string name="backup_review_encrypted_cleared">Ön kiürítette</string>
|
||||
<string name="backup_review_feed">Hírfolyam</string>
|
||||
<string name="backup_review_gone">Eltűnt</string>
|
||||
<string name="backup_review_hashtags_you_follow">Ön által követett kulcsszavak</string>
|
||||
<string name="backup_review_inbox">Bejövő</string>
|
||||
<string name="backup_review_inbox_explainer">ahol mások elérik Önt</string>
|
||||
<string name="backup_review_joined">csatlakozott</string>
|
||||
<string name="backup_review_kept">megtartva</string>
|
||||
<string name="backup_review_kept_count">%1$s megtartva</string>
|
||||
<string name="backup_review_key_removed">Fogadási kulcs eltávolítva</string>
|
||||
<string name="backup_review_key_replaced">Fogadási kulcs lecserélve</string>
|
||||
<string name="backup_review_key_warning">A nutzapok ehhez az új kulcshoz lesznek kötve. Ha ez az eszköz nem rendelkezik vele, lehet, hogy itt nem tudja beváltani őket.</string>
|
||||
<string name="backup_review_left">elhagyta a csoportot</string>
|
||||
<string name="backup_review_left_tag">Elhagyva</string>
|
||||
<string name="backup_review_listed_tag">Listázva</string>
|
||||
<string name="backup_review_moved_tag">Áthelyezve</string>
|
||||
<string name="backup_review_names_and_more">%1$s és %2$s további</string>
|
||||
<string name="backup_review_new">Új verzió</string>
|
||||
<string name="backup_review_new_count">%1$s új</string>
|
||||
<string name="backup_review_new_count_caption">új</string>
|
||||
<string name="backup_review_new_tag">Új</string>
|
||||
<string name="backup_review_newly_blocked">Újonnan letiltva</string>
|
||||
<string name="backup_review_newly_muted">%1$s újonnan némítva</string>
|
||||
<string name="backup_review_no_longer_blocked">Már nincs letiltva</string>
|
||||
<string name="backup_review_not_set">Nincs beállítva</string>
|
||||
<string name="backup_review_nothing_here">Itt nincs semmi</string>
|
||||
<string name="backup_review_offer">BOLT12 ajánlat</string>
|
||||
<plurals name="backup_review_offers_gone">
|
||||
<item quantity="one">%1$d ajánlat eltávolítva</item>
|
||||
<item quantity="other">%1$d ajánlat eltávolítva</item>
|
||||
</plurals>
|
||||
<string name="backup_review_outbox">Kimenő</string>
|
||||
<string name="backup_review_outbox_explainer">ahol közzétesz</string>
|
||||
<plurals name="backup_review_payment_targets_gone">
|
||||
<item quantity="one">%1$d fizetési mód eltávolítva</item>
|
||||
<item quantity="other">%1$d fizetési mód eltávolítva</item>
|
||||
</plurals>
|
||||
<string name="backup_review_payments_explainer">A fizető emberek csak azt látják, ami ebben a listában van.</string>
|
||||
<string name="backup_review_places_gone">eltűnt helyek</string>
|
||||
<string name="backup_review_places_you_follow">Ön által követett helyek</string>
|
||||
<string name="backup_review_private_added_body">Most már titkosítva vannak, valószínűleg ide kerültek a fenti nyilvános elemek.</string>
|
||||
<string name="backup_review_private_added_title">Ön priváttá tette az elemeket</string>
|
||||
<string name="backup_review_private_changed_body">Titkosítva vannak, így itt nem hasonlíthatók össze.</string>
|
||||
<string name="backup_review_private_changed_title">Ön módosította a privát elemeket</string>
|
||||
<string name="backup_review_private_wiped_body">Titkosítva vannak, így csak Ön láthatja, mik voltak. A visszaállítás mindet visszahozza.</string>
|
||||
<string name="backup_review_private_wiped_title">Ön eltávolította az összes privát elemet</string>
|
||||
<string name="backup_review_receiving_tag">Fogadás</string>
|
||||
<string name="backup_review_renamed">átnevezte</string>
|
||||
<string name="backup_review_renamed_tag">Átnevezve</string>
|
||||
<string name="backup_review_saved">Ezen az eszközön</string>
|
||||
<string name="backup_review_search_people">%1$s személy keresése</string>
|
||||
<string name="backup_review_searching_tag">Keresés</string>
|
||||
<string name="backup_review_service">Szolgáltatás</string>
|
||||
<string name="backup_review_service_followers">Követők</string>
|
||||
<string name="backup_review_service_rank">Rang</string>
|
||||
<string name="backup_review_service_topics">Témák</string>
|
||||
<string name="backup_review_services_changed">%2$s szolgáltatásból %1$s módosult</string>
|
||||
<string name="backup_review_services_changed_explainer">Most már valaki mástól vagy senkitől sem származnak</string>
|
||||
<string name="backup_review_still_blocked">Továbbra is le van tiltva</string>
|
||||
<string name="backup_review_storing_tag">Tárolás</string>
|
||||
<string name="backup_review_tab_dropped">Elvetve · %1$s</string>
|
||||
<string name="backup_review_tab_edited">Szerkesztve · %1$s</string>
|
||||
<string name="backup_review_tab_new">Új · %1$s</string>
|
||||
<string name="backup_review_title_cleared">%1$s törölve</string>
|
||||
<string name="backup_review_title_updated">%1$s frissítve</string>
|
||||
<string name="backup_review_topics_gone">eltűnt témák</string>
|
||||
<string name="backup_review_trust_warning">A látott rangok, követőszámok és a kéretlen tartalomszűrés ezektől a szolgáltatóktól származnak.</string>
|
||||
<string name="backup_review_trusted_tag">Megbízható</string>
|
||||
<string name="backup_review_unblocked">%1$s letiltása feloldva</string>
|
||||
<string name="backup_review_unblocked_explainer">Az Amethyst újra kapcsolódni fog hozzájuk</string>
|
||||
<string name="backup_review_units_tag">Egységek</string>
|
||||
<string name="backup_review_unmuted">%1$s némítása feloldva</string>
|
||||
<string name="backup_review_unmuted_explainer">Ezek újra megjelenhetnek a hírfolyamaiban</string>
|
||||
<string name="backup_review_untrusted_tag">Nem megbízható</string>
|
||||
<string name="backup_review_wallet_body">A saját pénztárca pénzverdéi és kulcsai Önhöz vannak titkosítva, így itt nem hasonlíthatók össze tételesen. A visszaállítás pontosan azt hozza vissza, amit ez az eszköz mentett.</string>
|
||||
<string name="backup_review_was_named">„%1$s” volt</string>
|
||||
<string name="backup_review_words_and_hashtags">Szavak és kulcsszavak</string>
|
||||
<string name="backup_type_app_settings">szinkronizált alkalmazásbeállítások</string>
|
||||
<string name="backup_type_app_settings_explainer">Az eszközök között szinkronizált Amethyst-beállítások. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_blocked_relays">letiltott átjátszólista</string>
|
||||
<string name="backup_type_blocked_relays_explainer">Átjátszók, amelyekhez ez az alkalmazás soha nem kapcsolódik.</string>
|
||||
<string name="backup_type_bolt12_offers">BOLT12 ajánlatok</string>
|
||||
<string name="backup_type_bolt12_offers_explainer">A lightning ajánlatok, amelyeket mások a fizetéshez használnak az Ön számára.</string>
|
||||
<string name="backup_type_cashu_wallet">Cashu pénztárca</string>
|
||||
<string name="backup_type_cashu_wallet_explainer">Az ecash pénztárca beállításai és pénzverdéi. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_communities">közösséglista</string>
|
||||
<string name="backup_type_communities_explainer">Közösségek, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_concord_communities">Concord közösséglista</string>
|
||||
<string name="backup_type_concord_communities_explainer">A Concord közösségek, amelyekhez csatlakozott. Titkosítva vannak, így csak a jelenlétük hasonlítható össze.</string>
|
||||
<string name="backup_type_dm_relays">privát üzenet átjátszólista</string>
|
||||
<string name="backup_type_dm_relays_explainer">Ahová mások kézbesítik a privát üzeneteit.</string>
|
||||
<string name="backup_type_ephemeral_chats">rövid életű csevegési lista</string>
|
||||
<string name="backup_type_ephemeral_chats_explainer">Rövid életű csevegőszobák, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_favorite_algo_feeds">kedvenc hírfolyamlista</string>
|
||||
<string name="backup_type_favorite_algo_feeds_explainer">Mentett algoritmus-hírfolyamok.</string>
|
||||
<string name="backup_type_follow_list">követési lista</string>
|
||||
<string name="backup_type_follow_list_explainer">Meghatározza, kinek a bejegyzései jelenjenek meg a kezdőlapon.</string>
|
||||
<string name="backup_type_geohashes">követett helyek</string>
|
||||
<string name="backup_type_geohashes_explainer">Helyek, amelyek bejegyzései megjelennek a hírfolyamaiban.</string>
|
||||
<string name="backup_type_hashtags">követett kulcsszavak</string>
|
||||
<string name="backup_type_hashtags_explainer">Kulcsszavak, amelyek bejegyzései megjelennek a hírfolyamban.</string>
|
||||
<string name="backup_type_indexer_relays">indexelő átjátszólista</string>
|
||||
<string name="backup_type_indexer_relays_explainer">Azok az átjátszók, amelyeket mások profiljainak és átjátszólistáinak megtalálásához használnak.</string>
|
||||
<string name="backup_type_key_package_relays">csoportos csevegési kulcsátjátszók</string>
|
||||
<string name="backup_type_key_package_relays_explainer">Ahol mások megtalálják a kulcsokat, hogy titkosított csoportos csevegésekhez adhassák Önt.</string>
|
||||
<string name="backup_type_mute_list">némítási lista</string>
|
||||
<string name="backup_type_mute_list_explainer">Elrejti a személyeket, szavakat, kulcsszavakat és beszélgetéseket mindenből, amit lát.</string>
|
||||
<string name="backup_type_nutzap_info">nutzap fogadási beállítások</string>
|
||||
<string name="backup_type_nutzap_info_explainer">A pénzverdék és a kulcs, amelyeket mások a nutzapok küldéséhez használnak az Ön számára.</string>
|
||||
<string name="backup_type_other">lista</string>
|
||||
<string name="backup_type_other_explainer">Egy listaelem ezen az eszközön mentve.</string>
|
||||
<string name="backup_type_outbox_inbox_relays">nyilvános átjátszólista</string>
|
||||
<string name="backup_type_outbox_inbox_relays_explainer">Megmondja mindenkinek, hol találhatók a bejegyzései, és hová küldjék a válaszokat és említéseket.</string>
|
||||
<string name="backup_type_payment_targets">fizetési címek</string>
|
||||
<string name="backup_type_payment_targets_explainer">A módok, ahogy mások fizethetnek Önnek.</string>
|
||||
<string name="backup_type_private_outbox_relays">privát átjátszólista</string>
|
||||
<string name="backup_type_private_outbox_relays_explainer">Ahol a piszkozatai és privát adatai tárolódnak.</string>
|
||||
<string name="backup_type_profile">profil</string>
|
||||
<string name="backup_type_profile_explainer">Az Ön neve, képe, bemutatkozása és fizetési címei, ahogy mindenki látja őket.</string>
|
||||
<string name="backup_type_public_chats">nyilvános csevegési lista</string>
|
||||
<string name="backup_type_public_chats_explainer">Nyilvános csevegések, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_relay_feeds">kedvenc átjátszóhírfolyamok</string>
|
||||
<string name="backup_type_relay_feeds_explainer">Olyan átjátszók, amelyeket hírfolyamként böngész.</string>
|
||||
<string name="backup_type_relay_groups">csoportlista</string>
|
||||
<string name="backup_type_relay_groups_explainer">Átjátszó-alapú csoportok, amelyekhez csatlakozott.</string>
|
||||
<string name="backup_type_search_relays">kereső átjátszólista</string>
|
||||
<string name="backup_type_search_relays_explainer">Kereséskor használt átjátszók.</string>
|
||||
<string name="backup_type_trust_providers">bizalmi szolgáltatólista</string>
|
||||
<string name="backup_type_trust_providers_explainer">A szolgáltatások, amelyekben megbízik, hogy rangsorolják és ellenőrizzék Önnek az embereket.</string>
|
||||
<string name="backup_type_trusted_relays">megbízható átjátszólista</string>
|
||||
<string name="backup_type_trusted_relays_explainer">Átjátszók, amelyekhez kérdezés nélkül kapcsolódhat.</string>
|
||||
</resources>
|
||||
|
||||
@@ -266,15 +266,8 @@
|
||||
<string name="mark_all_known_as_read">Tandai semua yang dikenal sebagai telah dibaca</string>
|
||||
<string name="mark_all_new_as_read">Tandai semua yang baru sebagai telah dibaca</string>
|
||||
<string name="mark_all_as_read">Tandai semua sebagai telah dibaca</string>
|
||||
<string name="account_backup_tips2_md"> ## Tips Cadangan Kunci dan Keamanan
|
||||
\n\nAkun Anda diamankan dengan kunci rahasia. Kunci ini adalah rangkaian karakter panjang yang diawali dengan **nsec1**. Siapa pun yang memiliki akses ke kunci rahasia ini dapat memposting dan mengubah identitas Anda.
|
||||
\n\n- **Jangan** memasukkan kunci rahasia Anda ke situs web atau perangkat lunak yang tidak Anda percaya.
|
||||
\n- Pengembang Amethyst **tidak akan pernah** meminta kunci rahasia Anda.
|
||||
\n- **Lakukan** pencadangan kunci rahasia Anda secara aman untuk pemulihan akun. Kami merekomendasikan penggunaan pengelola kata sandi.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Untuk keamanan tambahan, Anda dapat mengenkripsi kunci dengan kata sandi. Kunci ini diawali dengan **ncryptsec1** dan tidak dapat digunakan tanpa kata sandi Anda.
|
||||
\n\nJika Anda kehilangan kata sandi, Anda tidak akan dapat memulihkan kunci Anda.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Tips Cadangan Kunci dan Keamanan \n\nAkun Anda diamankan dengan kunci rahasia. Kunci ini adalah rangkaian karakter panjang yang diawali dengan **nsec1**. Siapa pun yang memiliki akses ke kunci rahasia ini dapat memposting dan mengubah identitas Anda. \n\n- **Jangan** memasukkan kunci rahasia Anda ke situs web atau perangkat lunak yang tidak Anda percaya. \n- Pengembang Amethyst **tidak akan pernah** meminta kunci rahasia Anda. \n- **Lakukan** pencadangan kunci rahasia Anda secara aman untuk pemulihan akun. Kami merekomendasikan penggunaan pengelola kata sandi.</string>
|
||||
<string name="account_backup_tips3_md">Untuk keamanan tambahan, Anda dapat mengenkripsi kunci dengan kata sandi. Kunci ini diawali dengan **ncryptsec1** dan tidak dapat digunakan tanpa kata sandi Anda. \n\nJika Anda kehilangan kata sandi, Anda tidak akan dapat memulihkan kunci Anda.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Enkripsi dan salin kunci rahasia saya</string>
|
||||
<string name="badge_award_image_for">Gambar penghargaan lencana untuk %1$s</string>
|
||||
<string name="badge_award_image">"Gambar penghargaan lencana</string>
|
||||
@@ -853,13 +846,11 @@
|
||||
<string name="meeting_space_closed_tag">DITUTUP</string>
|
||||
<string name="meeting_space_planned_tag">TERJADWAL</string>
|
||||
<string name="meeting_space_planned_starts_at">Mulai %1$s</string>
|
||||
<string name="are_you_sure_you_want_to_log_out">Keluar akan menghapus semua informasi yang disimpan secara lokal.
|
||||
Pastikan kunci pribadi Anda telah simpan untuk menghindari kehilangan akun Anda. Apakah Anda ingin melanjutkan?</string>
|
||||
<string name="are_you_sure_you_want_to_log_out">Keluar akan menghapus semua informasi yang disimpan secara lokal. Pastikan kunci pribadi Anda telah simpan untuk menghindari kehilangan akun Anda. Apakah Anda ingin melanjutkan?</string>
|
||||
<string name="followed_tags">Tags yang Diikuti</string>
|
||||
<string name="discover_follows_explainer">Ini adalah daftar pengguna yang Anda rekomendasikan kepada orang lain. Hanya pengguna publik yang diizinkan.</string>
|
||||
<string name="community_approved_posts">Post yang disetujui</string>
|
||||
<string name="groups_no_descriptor">Grup ini tidak memiliki deskripsi atau peraturan.
|
||||
Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="groups_no_descriptor">Grup ini tidak memiliki deskripsi atau peraturan. Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="community_no_descriptor">Komunitas ini tidak memiliki deskripsi. Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="user_preferences">Preferensi Pengguna</string>
|
||||
<string name="settings_search_placeholder">Cari pengaturan</string>
|
||||
@@ -951,9 +942,7 @@ Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="push_server_none_explainer">Matikan Pemberitahuan Push</string>
|
||||
<string name="push_server_uses_app_explainer">Memakai aplikasi %1$s</string>
|
||||
<string name="push_server_install_app">Pengaturan Pemberitahuan Push</string>
|
||||
<string name="push_server_install_app_description"> Untuk menerima Pemberitahuan Push, Install aplikasi yang mendukung [Unified Push](https://unifiedpush.org/), seperti [Ntfy](https://ntfy.sh/).
|
||||
Setelah diinstall, Pilih aplikasi yang ingin digunakan di pengaturan.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Untuk menerima Pemberitahuan Push, Install aplikasi yang mendukung [Unified Push](https://unifiedpush.org/), seperti [Ntfy](https://ntfy.sh/). Setelah diinstall, Pilih aplikasi yang ingin digunakan di pengaturan.</string>
|
||||
<string name="thread_title">Utas</string>
|
||||
<string name="send_the_seller_a_message">Kirim pesan ke penjual</string>
|
||||
<string name="hi_there_is_this_still_available">Halo, apakah ini masih tersedia?</string>
|
||||
@@ -1991,15 +1980,7 @@ Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="could_not_fetch_invoice_from_details">Tidak dapat mengambil invoice dari %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Tidak dapat membuka file terkompresi</string>
|
||||
<string name="couldnt_find_nwc_wallets">Dompet tidak ditemukan</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst tidak dapat menemukan aplikasi dompet apa pun yang mendukung Nostr Wallet Connect (NWC).
|
||||
\n\nYang dapat Anda lakukan:
|
||||
\n\t1. Verifikasi Dukungan NWC: Pastikan aplikasi dompet pilihan Anda kompatibel dengan Nostr Wallet Connect.
|
||||
\n\t2. Buat Koneksi: Buka aplikasi dompet Anda dan buat koneksi NWC baru.
|
||||
\n\t3. Hubungkan ke Amethyst: Dompet Anda biasanya akan memberikan tiga pilihan:
|
||||
\n\t\t3.1 Tautan Otomatis: Tombol untuk secara otomatis membuka dan terhubung ke Amethyst. Jika ada, klik tombol tersebut, buka Amethyst dan tekan simpan di layar baru.
|
||||
\n\t\t3.2 Tautan Manual: URI Koneksi yang dapat Anda salin dan klik ikon tempel di layar ini untuk memasukkannya secara langsung.
|
||||
\n\t\t3.3 Kode QR: Dompet membuat kode QR yang dapat Anda baca dari tombol kode QR di layar ini.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst tidak dapat menemukan aplikasi dompet apa pun yang mendukung Nostr Wallet Connect (NWC). \n\nYang dapat Anda lakukan: \n\t1. Verifikasi Dukungan NWC: Pastikan aplikasi dompet pilihan Anda kompatibel dengan Nostr Wallet Connect. \n\t2. Buat Koneksi: Buka aplikasi dompet Anda dan buat koneksi NWC baru. \n\t3. Hubungkan ke Amethyst: Dompet Anda biasanya akan memberikan tiga pilihan: \n\t\t3.1 Tautan Otomatis: Tombol untuk secara otomatis membuka dan terhubung ke Amethyst. Jika ada, klik tombol tersebut, buka Amethyst dan tekan simpan di layar baru. \n\t\t3.2 Tautan Manual: URI Koneksi yang dapat Anda salin dan klik ikon tempel di layar ini untuk memasukkannya secara langsung. \n\t\t3.3 Kode QR: Dompet membuat kode QR yang dapat Anda baca dari tombol kode QR di layar ini.</string>
|
||||
<string name="create">Buat</string>
|
||||
<string name="d">h</string>
|
||||
<string name="danger_zone">Zona Berbahaya</string>
|
||||
@@ -2183,8 +2164,7 @@ Beri tahu kepada pemilik untuk menambahnya</string>
|
||||
<string name="image_saved_to_the_gallery">Gambar disimpan ke galeri</string>
|
||||
<string name="impersonation">Identitas palsu</string>
|
||||
<string name="inbox_relays_title">Relay Kotak Masuk</string>
|
||||
<string name="incorrect_invoice_amount_sats_from_it_should_have_been">Jumlah faktur salah (%1$s sat) dari %2$s.
|
||||
Seharusnya %3$s</string>
|
||||
<string name="incorrect_invoice_amount_sats_from_it_should_have_been">Jumlah faktur salah (%1$s sat) dari %2$s. Seharusnya %3$s</string>
|
||||
<string name="indexer_section">Relay Indeks</string>
|
||||
<string name="indexer_section_explainer">Relay yang berspesialisasi dalam menyimpan metadata dan daftar relay semua orang, seperti purplepag.es. Amethyst akan menggunakan relay ini untuk menemukan pengguna yang tidak ada dalam daftar Anda.</string>
|
||||
<string name="interest_set_creation_screen_title">Kumpulan Minat Baru</string>
|
||||
@@ -2618,11 +2598,8 @@ Seharusnya %3$s</string>
|
||||
<string name="proxy_section">Relay Proxy</string>
|
||||
<string name="proxy_section_explainer">Relay agregator yang harus digunakan aplikasi untuk mengunduh feed Anda, seperti filter.nostr.wine. Ini menggantikan model outbox dan akan membuat aplikasi hanya terhubung ke relay dalam daftar Anda.</string>
|
||||
<string name="public_chat">Obrolan Publik</string>
|
||||
<string name="public_chat_explainer">Obrolan publik terlihat oleh semua orang di Nostr dan siapa pun
|
||||
dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu.
|
||||
Moderasi dapat dilakukan dengan menghapus postingan di relay-nya</string>
|
||||
<string name="public_chat_relays_explainer">Masukkan antara 1–3 relay yang menjadi host grup ini.
|
||||
Klien Nostr menggunakan pengaturan ini untuk mengetahui tempat mengunduh dan mengirim pesan Anda.</string>
|
||||
<string name="public_chat_explainer">Obrolan publik terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu. Moderasi dapat dilakukan dengan menghapus postingan di relay-nya</string>
|
||||
<string name="public_chat_relays_explainer">Masukkan antara 1–3 relay yang menjadi host grup ini. Klien Nostr menggunakan pengaturan ini untuk mengetahui tempat mengunduh dan mengirim pesan Anda.</string>
|
||||
<string name="public_chat_relays_title">relay</string>
|
||||
<string name="public_chat_title">Metadata Obrolan Publik</string>
|
||||
<string name="public_chats">Obrolan Publik</string>
|
||||
@@ -2647,10 +2624,7 @@ Seharusnya %3$s</string>
|
||||
<string name="read_only_user">Pengguna hanya-baca</string>
|
||||
<string name="record_a_message_description">Tekan dan tahan untuk merekam pesan</string>
|
||||
<string name="relay_chat">Obrolan relay</string>
|
||||
<string name="relay_chat_explainer">Obrolan relay adalah grup obrolan yang dikendalikan oleh relay induknya.
|
||||
Obrolan ini terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi.
|
||||
Sangat cocok untuk komunitas terbuka seputar topik tertentu. Beberapa grup ini bersifat sementara
|
||||
sehingga pesan obrolan akan menghilang seiring waktu</string>
|
||||
<string name="relay_chat_explainer">Obrolan relay adalah grup obrolan yang dikendalikan oleh relay induknya. Obrolan ini terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu. Beberapa grup ini bersifat sementara sehingga pesan obrolan akan menghilang seiring waktu</string>
|
||||
<string name="relay_chat_title">Obrolan relay</string>
|
||||
<string name="relay_management_tab_events">Acara</string>
|
||||
<string name="relay_management_tab_ips">IP</string>
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
<string name="username">Nama pengguna</string>
|
||||
<string name="about_me">Tentang saya</string>
|
||||
<string name="avatar_url">URL Avatar</string>
|
||||
<string name="banner_url">URL Spanduk/Banner </string>
|
||||
<string name="banner_url">URL Spanduk/Banner</string>
|
||||
<string name="website_url">URL Situs Web</string>
|
||||
<string name="pronouns">Kata ganti</string>
|
||||
<string name="stale_relay_hint_label">relay sumber mungkin sudah usang</string>
|
||||
@@ -257,17 +257,8 @@
|
||||
<string name="mark_all_known_as_read">Tandai semua yg dikenal telah dibaca</string>
|
||||
<string name="mark_all_new_as_read">Tandai pesan baru telah dibaca</string>
|
||||
<string name="mark_all_as_read">Tandai semua telah dibaca</string>
|
||||
<string name="account_backup_tips2_md">
|
||||
## Tips Cadangan Kunci dan Keamanan
|
||||
\n\nAkun Anda diamankan dengan kunci rahasia. Kunci ini adalah rangkaian karakter panjang yang diawali dengan **nsec1**. Siapa pun yang memiliki akses ke kunci rahasia ini dapat memposting dan mengubah identitas Anda.
|
||||
\n\n- **Jangan** memasukkan kunci rahasia Anda ke situs web atau perangkat lunak yang tidak Anda percaya.
|
||||
\n- Pengembang Amethyst **tidak akan pernah** meminta kunci rahasia Anda.
|
||||
\n- **Lakukan** pencadangan kunci rahasia Anda secara aman untuk pemulihan akun. Kami merekomendasikan penggunaan pengelola kata sandi.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md">
|
||||
Untuk keamanan tambahan, Anda dapat mengenkripsi kunci dengan kata sandi. Kunci ini diawali dengan **ncryptsec1** dan tidak dapat digunakan tanpa kata sandi Anda.
|
||||
\n\nJika Anda kehilangan kata sandi, Anda tidak akan dapat memulihkan kunci Anda.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Tips Cadangan Kunci dan Keamanan \n\nAkun Anda diamankan dengan kunci rahasia. Kunci ini adalah rangkaian karakter panjang yang diawali dengan **nsec1**. Siapa pun yang memiliki akses ke kunci rahasia ini dapat memposting dan mengubah identitas Anda. \n\n- **Jangan** memasukkan kunci rahasia Anda ke situs web atau perangkat lunak yang tidak Anda percaya. \n- Pengembang Amethyst **tidak akan pernah** meminta kunci rahasia Anda. \n- **Lakukan** pencadangan kunci rahasia Anda secara aman untuk pemulihan akun. Kami merekomendasikan penggunaan pengelola kata sandi.</string>
|
||||
<string name="account_backup_tips3_md">Untuk keamanan tambahan, Anda dapat mengenkripsi kunci dengan kata sandi. Kunci ini diawali dengan **ncryptsec1** dan tidak dapat digunakan tanpa kata sandi Anda. \n\nJika Anda kehilangan kata sandi, Anda tidak akan dapat memulihkan kunci Anda.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Enkripsi dan salin kunci rahasia saya</string>
|
||||
<string name="badge_award_image_for">Gambar penghargaan lencana untuk %1$s</string>
|
||||
<string name="badge_award_image">"Gambar penghargaan lencana</string>
|
||||
@@ -960,10 +951,7 @@
|
||||
<string name="push_server_none_explainer">Menonaktifkan Notifikasi Push</string>
|
||||
<string name="push_server_uses_app_explainer">Menggunakan aplikasi %1$s</string>
|
||||
<string name="push_server_install_app">Pengaturan Notifikasi Push</string>
|
||||
<string name="push_server_install_app_description">
|
||||
Untuk menerima notifikasi push, instal aplikasi yang mendukung [Unified Push](https://unifiedpush.org/), seperti [Ntfy](https://ntfy.sh/).
|
||||
Setelah menginstal, pilih aplikasi yang ingin Anda gunakan di Pengaturan.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Untuk menerima notifikasi push, instal aplikasi yang mendukung [Unified Push](https://unifiedpush.org/), seperti [Ntfy](https://ntfy.sh/). Setelah menginstal, pilih aplikasi yang ingin Anda gunakan di Pengaturan.</string>
|
||||
<string name="thread_title">Utas</string>
|
||||
<string name="send_the_seller_a_message">Kirim pesan ke penjual</string>
|
||||
<string name="hi_there_is_this_still_available">Halo, apakah ini masih tersedia?</string>
|
||||
@@ -2048,15 +2036,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Tidak dapat mengambil invoice dari %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Tidak dapat membuka file terkompresi</string>
|
||||
<string name="couldnt_find_nwc_wallets">Dompet tidak ditemukan</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst tidak dapat menemukan aplikasi dompet apa pun yang mendukung Nostr Wallet Connect (NWC).
|
||||
\n\nYang dapat Anda lakukan:
|
||||
\n\t1. Verifikasi Dukungan NWC: Pastikan aplikasi dompet pilihan Anda kompatibel dengan Nostr Wallet Connect.
|
||||
\n\t2. Buat Koneksi: Buka aplikasi dompet Anda dan buat koneksi NWC baru.
|
||||
\n\t3. Hubungkan ke Amethyst: Dompet Anda biasanya akan memberikan tiga pilihan:
|
||||
\n\t\t3.1 Tautan Otomatis: Tombol untuk secara otomatis membuka dan terhubung ke Amethyst. Jika ada, klik tombol tersebut, buka Amethyst dan tekan simpan di layar baru.
|
||||
\n\t\t3.2 Tautan Manual: URI Koneksi yang dapat Anda salin dan klik ikon tempel di layar ini untuk memasukkannya secara langsung.
|
||||
\n\t\t3.3 Kode QR: Dompet membuat kode QR yang dapat Anda baca dari tombol kode QR di layar ini.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst tidak dapat menemukan aplikasi dompet apa pun yang mendukung Nostr Wallet Connect (NWC). \n\nYang dapat Anda lakukan: \n\t1. Verifikasi Dukungan NWC: Pastikan aplikasi dompet pilihan Anda kompatibel dengan Nostr Wallet Connect. \n\t2. Buat Koneksi: Buka aplikasi dompet Anda dan buat koneksi NWC baru. \n\t3. Hubungkan ke Amethyst: Dompet Anda biasanya akan memberikan tiga pilihan: \n\t\t3.1 Tautan Otomatis: Tombol untuk secara otomatis membuka dan terhubung ke Amethyst. Jika ada, klik tombol tersebut, buka Amethyst dan tekan simpan di layar baru. \n\t\t3.2 Tautan Manual: URI Koneksi yang dapat Anda salin dan klik ikon tempel di layar ini untuk memasukkannya secara langsung. \n\t\t3.3 Kode QR: Dompet membuat kode QR yang dapat Anda baca dari tombol kode QR di layar ini.</string>
|
||||
<string name="create">Buat</string>
|
||||
<string name="d">hari</string>
|
||||
<string name="danger_zone">Zona Berbahaya</string>
|
||||
@@ -2723,11 +2703,8 @@
|
||||
<string name="proxy_section">Relay Proxy</string>
|
||||
<string name="proxy_section_explainer">Relay agregator yang harus digunakan aplikasi untuk mengunduh feed Anda, seperti filter.nostr.wine. Ini menggantikan model outbox dan akan membuat aplikasi hanya terhubung ke relay dalam daftar Anda.</string>
|
||||
<string name="public_chat">Percakapan Publik</string>
|
||||
<string name="public_chat_explainer">Obrolan publik terlihat oleh semua orang di Nostr dan siapa pun
|
||||
dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu.
|
||||
Moderasi dapat dilakukan dengan menghapus postingan di relay-nya</string>
|
||||
<string name="public_chat_relays_explainer">Masukkan antara 1–3 relay yang menjadi host grup ini.
|
||||
Klien Nostr menggunakan pengaturan ini untuk mengetahui tempat mengunduh dan mengirim pesan Anda.</string>
|
||||
<string name="public_chat_explainer">Obrolan publik terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu. Moderasi dapat dilakukan dengan menghapus postingan di relay-nya</string>
|
||||
<string name="public_chat_relays_explainer">Masukkan antara 1–3 relay yang menjadi host grup ini. Klien Nostr menggunakan pengaturan ini untuk mengetahui tempat mengunduh dan mengirim pesan Anda.</string>
|
||||
<string name="public_chat_relays_title">relay</string>
|
||||
<string name="public_chat_title">Metadata Obrolan Publik</string>
|
||||
<string name="public_chats">Obrolan Publik</string>
|
||||
@@ -2752,10 +2729,7 @@
|
||||
<string name="read_only_user">Pengguna hanya-baca</string>
|
||||
<string name="record_a_message_description">Tekan dan tahan untuk merekam pesan</string>
|
||||
<string name="relay_chat">Obrolan relay</string>
|
||||
<string name="relay_chat_explainer">Obrolan relay adalah grup obrolan yang dikendalikan oleh relay induknya.
|
||||
Obrolan ini terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi.
|
||||
Sangat cocok untuk komunitas terbuka seputar topik tertentu. Beberapa grup ini bersifat sementara
|
||||
sehingga pesan obrolan akan menghilang seiring waktu</string>
|
||||
<string name="relay_chat_explainer">Obrolan relay adalah grup obrolan yang dikendalikan oleh relay induknya. Obrolan ini terlihat oleh semua orang di Nostr dan siapa pun dapat berpartisipasi. Sangat cocok untuk komunitas terbuka seputar topik tertentu. Beberapa grup ini bersifat sementara sehingga pesan obrolan akan menghilang seiring waktu</string>
|
||||
<string name="relay_chat_title">Obrolan relay</string>
|
||||
<string name="relay_management_tab_events">Acara</string>
|
||||
<string name="relay_management_tab_ips">IP</string>
|
||||
|
||||
@@ -266,15 +266,8 @@
|
||||
<string name="mark_all_known_as_read">Segna tutti i conosciuti come letti</string>
|
||||
<string name="mark_all_new_as_read">Segna tutti i nuovi come letti</string>
|
||||
<string name="mark_all_as_read">Segna tutti come letti</string>
|
||||
<string name="account_backup_tips2_md"> ## Suggerimenti per il backup e la sicurezza della chiave
|
||||
\n\nIl tuo account è protetto da una chiave segreta. La chiave è una lunga sequenza di caratteri che inizia con **nsec1**. Chiunque abbia accesso a questa chiave segreta può pubblicare e modificare la tua identità.
|
||||
\n\n- **Non** inserire la tua chiave segreta in nessun sito web o software di cui non ti fidi.
|
||||
\n- Gli sviluppatori di Amethyst non chiederanno **mai** la tua chiave segreta.
|
||||
\n- **Conserva** un backup sicuro della tua chiave segreta per il recupero dell'account. Si consiglia l'uso di un gestore di password.
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> Per maggiore sicurezza, puoi cifrare la tua chiave con una password. Questa chiave inizia con **ncryptsec1** e non può essere utilizzata senza la tua password.
|
||||
\n\nSe perdi la password, non potrai recuperare la tua chiave.
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## Suggerimenti per il backup e la sicurezza della chiave \n\nIl tuo account è protetto da una chiave segreta. La chiave è una lunga sequenza di caratteri che inizia con **nsec1**. Chiunque abbia accesso a questa chiave segreta può pubblicare e modificare la tua identità. \n\n- **Non** inserire la tua chiave segreta in nessun sito web o software di cui non ti fidi. \n- Gli sviluppatori di Amethyst non chiederanno **mai** la tua chiave segreta. \n- **Conserva** un backup sicuro della tua chiave segreta per il recupero dell'account. Si consiglia l'uso di un gestore di password.</string>
|
||||
<string name="account_backup_tips3_md">Per maggiore sicurezza, puoi cifrare la tua chiave con una password. Questa chiave inizia con **ncryptsec1** e non può essere utilizzata senza la tua password. \n\nSe perdi la password, non potrai recuperare la tua chiave.</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">Cifra e copia la mia chiave segreta</string>
|
||||
<string name="badge_award_image_for">Immagine premio badge per %1$s</string>
|
||||
<string name="badge_award_image">"Immagine del premio badge</string>
|
||||
@@ -947,9 +940,7 @@
|
||||
<string name="push_server_none_explainer">Disabilita le notifiche push</string>
|
||||
<string name="push_server_uses_app_explainer">Usa l'app %1$s</string>
|
||||
<string name="push_server_install_app">Configurazione notifiche push</string>
|
||||
<string name="push_server_install_app_description"> Per ricevere notifiche push, installa qualsiasi app che supporta [Unified Push](https://unifiedpush.org/), come [Ntfy](https://ntfy.sh/).
|
||||
Dopo l'installazione, seleziona l'app che desideri usare nelle Impostazioni.
|
||||
</string>
|
||||
<string name="push_server_install_app_description">Per ricevere notifiche push, installa qualsiasi app che supporta [Unified Push](https://unifiedpush.org/), come [Ntfy](https://ntfy.sh/). Dopo l'installazione, seleziona l'app che desideri usare nelle Impostazioni.</string>
|
||||
<string name="send_the_seller_a_message">Invia un messaggio al venditore</string>
|
||||
<string name="hi_there_is_this_still_available">Ciao, è ancora disponibile?</string>
|
||||
<string name="classifieds_title">Titolo</string>
|
||||
@@ -1986,15 +1977,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">Impossibile recuperare la fattura da %1$s: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">Impossibile aprire il file compresso</string>
|
||||
<string name="couldnt_find_nwc_wallets">Wallet non trovato</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst non ha trovato app wallet compatibili con Nostr Wallet Connect (NWC).
|
||||
\n\nCosa puoi fare:
|
||||
\n\t1. Verifica il supporto NWC: controlla che la tua app wallet preferita sia compatibile con Nostr Wallet Connect.
|
||||
\n\t2. Crea connessione: vai nella tua app wallet e crea una nuova connessione NWC.
|
||||
\n\t3. Collega ad Amethyst: la tua app wallet ti offrirà solitamente tre opzioni:
|
||||
\n\t\t3.1 Collegamento automatico: un pulsante per aprire e connettersi automaticamente ad Amethyst. In tal caso, clicca quel pulsante, apri Amethyst e premi salva nella nuova schermata.
|
||||
\n\t\t3.2 Collegamento manuale: un URI di connessione che puoi copiare e incollare tramite l'icona di incolla in questa schermata.
|
||||
\n\t\t3.3 Codice QR: il wallet crea un codice QR che puoi leggere tramite il pulsante QR in questa schermata.
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst non ha trovato app wallet compatibili con Nostr Wallet Connect (NWC). \n\nCosa puoi fare: \n\t1. Verifica il supporto NWC: controlla che la tua app wallet preferita sia compatibile con Nostr Wallet Connect. \n\t2. Crea connessione: vai nella tua app wallet e crea una nuova connessione NWC. \n\t3. Collega ad Amethyst: la tua app wallet ti offrirà solitamente tre opzioni: \n\t\t3.1 Collegamento automatico: un pulsante per aprire e connettersi automaticamente ad Amethyst. In tal caso, clicca quel pulsante, apri Amethyst e premi salva nella nuova schermata. \n\t\t3.2 Collegamento manuale: un URI di connessione che puoi copiare e incollare tramite l'icona di incolla in questa schermata. \n\t\t3.3 Codice QR: il wallet crea un codice QR che puoi leggere tramite il pulsante QR in questa schermata.</string>
|
||||
<string name="create">Crea</string>
|
||||
<string name="d">g</string>
|
||||
<string name="danger_zone">Zona pericolosa</string>
|
||||
@@ -2645,11 +2628,8 @@
|
||||
<string name="proxy_section">Relay proxy</string>
|
||||
<string name="proxy_section_explainer">Relay aggregatori che l'app deve usare per scaricare i tuoi feed, come filter.nostr.wine. Questo sostituisce il modello outbox e farà connettere l'app solo ai relay nelle tue liste.</string>
|
||||
<string name="public_chat">Chat Pubblica</string>
|
||||
<string name="public_chat_explainer">Le chat pubbliche sono visibili a tutti su Nostr e chiunque
|
||||
può parteciparvi. Sono ideali per comunità aperte su argomenti specifici.
|
||||
La moderazione può essere controllata eliminando i post sui relay associati</string>
|
||||
<string name="public_chat_relays_explainer">Inserisci tra 1 e 3 relay che ospitano questo gruppo.
|
||||
I client Nostr usano questa impostazione per sapere da dove scaricare i messaggi e dove inviare i tuoi messaggi.</string>
|
||||
<string name="public_chat_explainer">Le chat pubbliche sono visibili a tutti su Nostr e chiunque può parteciparvi. Sono ideali per comunità aperte su argomenti specifici. La moderazione può essere controllata eliminando i post sui relay associati</string>
|
||||
<string name="public_chat_relays_explainer">Inserisci tra 1 e 3 relay che ospitano questo gruppo. I client Nostr usano questa impostazione per sapere da dove scaricare i messaggi e dove inviare i tuoi messaggi.</string>
|
||||
<string name="public_chat_relays_title">Relay</string>
|
||||
<string name="public_chat_title">Metadati chat pubblica</string>
|
||||
<string name="public_chats">Chat pubbliche</string>
|
||||
@@ -2674,10 +2654,7 @@
|
||||
<string name="read_only_user">Utente in sola lettura</string>
|
||||
<string name="record_a_message_description">Tieni premuto per registrare un messaggio</string>
|
||||
<string name="relay_chat">Chat relay</string>
|
||||
<string name="relay_chat_explainer">Le chat relay sono gruppi di chat controllati dal loro relay di riferimento.
|
||||
Sono visibili a tutti su Nostr e chiunque può parteciparvi.
|
||||
Sono ideali per comunità aperte su argomenti specifici. Alcuni di questi gruppi sono effimeri
|
||||
e quindi i messaggi della chat scompaiono nel tempo</string>
|
||||
<string name="relay_chat_explainer">Le chat relay sono gruppi di chat controllati dal loro relay di riferimento. Sono visibili a tutti su Nostr e chiunque può parteciparvi. Sono ideali per comunità aperte su argomenti specifici. Alcuni di questi gruppi sono effimeri e quindi i messaggi della chat scompaiono nel tempo</string>
|
||||
<string name="relay_chat_title">Chat relay</string>
|
||||
<string name="relay_management_tab_events">Eventi</string>
|
||||
<string name="relay_management_tab_ips">IP</string>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<string name="scan_qr">QRコードをスキャン</string>
|
||||
<string name="show_anyway">それでも表示する</string>
|
||||
<string name="post_was_hidden">このポストは、非表示にしているユーザーまたはワードが含まれているため隠されています</string>
|
||||
<string name="post_was_flagged_as_inappropriate_by">このユーザによって投稿が不適切なものとしてマークされています: </string>
|
||||
<string name="post_was_flagged_as_inappropriate_by">このユーザによって投稿が不適切なものとしてマークされています:</string>
|
||||
<string name="post_not_found">投稿が見つかりません</string>
|
||||
<string name="channel_image">チャンネル画像</string>
|
||||
<string name="referenced_event_not_found">参照先のイベントが見つかりません</string>
|
||||
@@ -271,15 +271,8 @@
|
||||
<string name="mark_all_known_as_read">すべての「知り合い」を既読にする</string>
|
||||
<string name="mark_all_new_as_read">すべての「新規リクエスト」を既読にする</string>
|
||||
<string name="mark_all_as_read">すべて既読にする</string>
|
||||
<string name="account_backup_tips2_md"> ## 鍵のバックアップとセキュリティのヒント
|
||||
\n\nアカウントは秘密鍵によって保護されています。この鍵は **nsec1** で始まる長い文字列です。この秘密鍵にアクセスできる人は誰でも、あなたの名前でポストしたり、プロフィールを変更したりできます。
|
||||
\n\n- 信頼していないウェブサイトやアプリに秘密鍵を **入力しないでください**。
|
||||
\n- Amethyst の開発者が秘密鍵を **求めることは絶対にありません**。
|
||||
\n- アカウントの復元のために、秘密鍵の安全なバックアップを **必ず** 保管してください。パスワードマネージャーの使用をお勧めします。
|
||||
</string>
|
||||
<string name="account_backup_tips3_md"> さらにセキュリティを高めるために、鍵をパスワードで暗号化することができます。この鍵は **ncryptsec1** で始まり、パスワードなしでは使用できません。
|
||||
\n\nパスワードを忘れると、鍵を復元できなくなります。
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## 鍵のバックアップとセキュリティのヒント \n\nアカウントは秘密鍵によって保護されています。この鍵は **nsec1** で始まる長い文字列です。この秘密鍵にアクセスできる人は誰でも、あなたの名前でポストしたり、プロフィールを変更したりできます。 \n\n- 信頼していないウェブサイトやアプリに秘密鍵を **入力しないでください**。 \n- Amethyst の開発者が秘密鍵を **求めることは絶対にありません**。 \n- アカウントの復元のために、秘密鍵の安全なバックアップを **必ず** 保管してください。パスワードマネージャーの使用をお勧めします。</string>
|
||||
<string name="account_backup_tips3_md">さらにセキュリティを高めるために、鍵をパスワードで暗号化することができます。この鍵は **ncryptsec1** で始まり、パスワードなしでは使用できません。 \n\nパスワードを忘れると、鍵を復元できなくなります。</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">秘密鍵を暗号化してコピー</string>
|
||||
<string name="badge_award_image_for">%1$sのバッジ授与画像</string>
|
||||
<string name="badge_award_image">バッジ授与の画像</string>
|
||||
@@ -965,9 +958,7 @@
|
||||
<string name="push_server_none_explainer">プッシュ通知を無効にします</string>
|
||||
<string name="push_server_uses_app_explainer">アプリ%1$sを使用</string>
|
||||
<string name="push_server_install_app">プッシュ通知の設定</string>
|
||||
<string name="push_server_install_app_description"> プッシュ通知を受け取るには、[Ntfy](https://ntfy.sh/)など[Unified Push](https://unifiedpush.org/)に対応したアプリをインストールしてください。
|
||||
インストール後、設定で使用するアプリを選択してください。
|
||||
</string>
|
||||
<string name="push_server_install_app_description">プッシュ通知を受け取るには、[Ntfy](https://ntfy.sh/)など[Unified Push](https://unifiedpush.org/)に対応したアプリをインストールしてください。 インストール後、設定で使用するアプリを選択してください。</string>
|
||||
<string name="thread_title">スレッド</string>
|
||||
<string name="send_the_seller_a_message">出品者にメッセージを送る</string>
|
||||
<string name="hi_there_is_this_still_available">こんにちは、こちらはまだ入手可能ですか?</string>
|
||||
@@ -2016,15 +2007,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">%1$s から請求書を取得できませんでした: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">圧縮ファイルを開けませんでした</string>
|
||||
<string name="couldnt_find_nwc_wallets">ウォレットが見つかりません</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst は Nostr Wallet Connect(NWC)に対応したウォレットアプリを見つけられませんでした。
|
||||
\n\n対処方法:
|
||||
\n\t1. NWC サポートを確認: お使いのウォレットアプリが Nostr Wallet Connect に対応しているか再確認してください。
|
||||
\n\t2. 接続を作成: ウォレットアプリで新しい NWC 接続を作成してください。
|
||||
\n\t3. Amethyst にリンク: ウォレットは通常、以下の3つの方法を提供します:
|
||||
\n\t\t3.1 自動リンク: 自動的に Amethyst を開いて接続するボタン。その場合、ボタンをクリックして Amethyst を開き、新しい画面で保存を押してください。
|
||||
\n\t\t3.2 手動リンク: この画面の貼り付けアイコンをクリックして直接入力できる接続 URI。
|
||||
\n\t\t3.3 QR コード: ウォレットが作成する QR コード。この画面の QR コードボタンから読み取れます。
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst は Nostr Wallet Connect(NWC)に対応したウォレットアプリを見つけられませんでした。 \n\n対処方法: \n\t1. NWC サポートを確認: お使いのウォレットアプリが Nostr Wallet Connect に対応しているか再確認してください。 \n\t2. 接続を作成: ウォレットアプリで新しい NWC 接続を作成してください。 \n\t3. Amethyst にリンク: ウォレットは通常、以下の3つの方法を提供します: \n\t\t3.1 自動リンク: 自動的に Amethyst を開いて接続するボタン。その場合、ボタンをクリックして Amethyst を開き、新しい画面で保存を押してください。 \n\t\t3.2 手動リンク: この画面の貼り付けアイコンをクリックして直接入力できる接続 URI。 \n\t\t3.3 QR コード: ウォレットが作成する QR コード。この画面の QR コードボタンから読み取れます。</string>
|
||||
<string name="create">作成</string>
|
||||
<string name="d">日</string>
|
||||
<string name="danger_zone">危険ゾーン</string>
|
||||
@@ -2667,11 +2650,8 @@
|
||||
<string name="proxy_section">Proxy Relay</string>
|
||||
<string name="proxy_section_explainer">filter.nostr.wine のように、アプリがフィードをダウンロードするために使用するアグリゲーター relay です。これにより outbox モデルが置き換えられ、アプリはリスト内の relay のみに接続するようになります。</string>
|
||||
<string name="public_chat">公開チャット</string>
|
||||
<string name="public_chat_explainer">パブリックチャットは Nostr 上の全員に公開されており、誰でも
|
||||
参加できます。特定のトピックを中心としたオープンなコミュニティに最適です。
|
||||
モデレーションは、その relay 上のポストを削除することで管理できます</string>
|
||||
<string name="public_chat_relays_explainer">このグループをホストする relay を 1〜3 件入力してください。
|
||||
Nostr クライアントはこの設定を使用して、メッセージのダウンロード先と送信先を決定します。</string>
|
||||
<string name="public_chat_explainer">パブリックチャットは Nostr 上の全員に公開されており、誰でも 参加できます。特定のトピックを中心としたオープンなコミュニティに最適です。 モデレーションは、その relay 上のポストを削除することで管理できます</string>
|
||||
<string name="public_chat_relays_explainer">このグループをホストする relay を 1〜3 件入力してください。 Nostr クライアントはこの設定を使用して、メッセージのダウンロード先と送信先を決定します。</string>
|
||||
<string name="public_chat_relays_title">Relay</string>
|
||||
<string name="public_chat_title">パブリックチャットのメタデータ</string>
|
||||
<string name="public_chats">パブリックチャット</string>
|
||||
@@ -2696,10 +2676,7 @@
|
||||
<string name="read_only_user">読み取り専用ユーザー</string>
|
||||
<string name="record_a_message_description">長押ししてメッセージを録音</string>
|
||||
<string name="relay_chat">relay チャット</string>
|
||||
<string name="relay_chat_explainer">relay チャットは、ホスト relay によって管理されるチャットグループです。
|
||||
Nostr 上の全員に公開されており、誰でも参加できます。
|
||||
特定のトピックを中心としたオープンなコミュニティに最適です。一部のグループは一時的なもので、
|
||||
チャットメッセージは時間とともに消えます</string>
|
||||
<string name="relay_chat_explainer">relay チャットは、ホスト relay によって管理されるチャットグループです。 Nostr 上の全員に公開されており、誰でも参加できます。 特定のトピックを中心としたオープンなコミュニティに最適です。一部のグループは一時的なもので、 チャットメッセージは時間とともに消えます</string>
|
||||
<string name="relay_chat_title">relay チャット</string>
|
||||
<string name="relay_management_tab_events">イベント</string>
|
||||
<string name="relay_management_tab_ips">IP</string>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<string name="scan_qr">QRコードをスキャン</string>
|
||||
<string name="show_anyway">それでも表示する</string>
|
||||
<string name="post_was_hidden">このポストは、非表示にしているユーザーまたはワードが含まれているため隠されています</string>
|
||||
<string name="post_was_flagged_as_inappropriate_by">このユーザによって投稿が不適切なものとしてマークされています: </string>
|
||||
<string name="post_was_flagged_as_inappropriate_by">このユーザによって投稿が不適切なものとしてマークされています:</string>
|
||||
<string name="post_not_found">投稿が見つかりません</string>
|
||||
<string name="post_not_found_short">👀</string>
|
||||
<string name="channel_image">チャンネル画像</string>
|
||||
@@ -257,17 +257,8 @@
|
||||
<string name="mark_all_known_as_read">すべての「知り合い」を既読にする</string>
|
||||
<string name="mark_all_new_as_read">すべての「新規リクエスト」を既読にする</string>
|
||||
<string name="mark_all_as_read">すべて既読にする</string>
|
||||
<string name="account_backup_tips2_md">
|
||||
## 鍵のバックアップとセキュリティのヒント
|
||||
\n\nアカウントは秘密鍵によって保護されています。この鍵は **nsec1** で始まる長い文字列です。この秘密鍵にアクセスできる人は誰でも、あなたの名前でポストしたり、プロフィールを変更したりできます。
|
||||
\n\n- 信頼していないウェブサイトやアプリに秘密鍵を **入力しないでください**。
|
||||
\n- Amethyst の開発者が秘密鍵を **求めることは絶対にありません**。
|
||||
\n- アカウントの復元のために、秘密鍵の安全なバックアップを **必ず** 保管してください。パスワードマネージャーの使用をお勧めします。
|
||||
</string>
|
||||
<string name="account_backup_tips3_md">
|
||||
さらにセキュリティを高めるために、鍵をパスワードで暗号化することができます。この鍵は **ncryptsec1** で始まり、パスワードなしでは使用できません。
|
||||
\n\nパスワードを忘れると、鍵を復元できなくなります。
|
||||
</string>
|
||||
<string name="account_backup_tips2_md">## 鍵のバックアップとセキュリティのヒント \n\nアカウントは秘密鍵によって保護されています。この鍵は **nsec1** で始まる長い文字列です。この秘密鍵にアクセスできる人は誰でも、あなたの名前でポストしたり、プロフィールを変更したりできます。 \n\n- 信頼していないウェブサイトやアプリに秘密鍵を **入力しないでください**。 \n- Amethyst の開発者が秘密鍵を **求めることは絶対にありません**。 \n- アカウントの復元のために、秘密鍵の安全なバックアップを **必ず** 保管してください。パスワードマネージャーの使用をお勧めします。</string>
|
||||
<string name="account_backup_tips3_md">さらにセキュリティを高めるために、鍵をパスワードで暗号化することができます。この鍵は **ncryptsec1** で始まり、パスワードなしでは使用できません。 \n\nパスワードを忘れると、鍵を復元できなくなります。</string>
|
||||
<string name="encrypt_and_copy_my_secret_key">秘密鍵を暗号化してコピー</string>
|
||||
<string name="badge_award_image_for">%1$sのバッジ授与画像</string>
|
||||
<string name="badge_award_image">バッジ授与の画像</string>
|
||||
@@ -960,10 +951,7 @@
|
||||
<string name="push_server_none_explainer">プッシュ通知を無効にします</string>
|
||||
<string name="push_server_uses_app_explainer">アプリ%1$sを使用</string>
|
||||
<string name="push_server_install_app">プッシュ通知の設定</string>
|
||||
<string name="push_server_install_app_description">
|
||||
プッシュ通知を受け取るには、[Ntfy](https://ntfy.sh/)など[Unified Push](https://unifiedpush.org/)に対応したアプリをインストールしてください。
|
||||
インストール後、設定で使用するアプリを選択してください。
|
||||
</string>
|
||||
<string name="push_server_install_app_description">プッシュ通知を受け取るには、[Ntfy](https://ntfy.sh/)など[Unified Push](https://unifiedpush.org/)に対応したアプリをインストールしてください。 インストール後、設定で使用するアプリを選択してください。</string>
|
||||
<string name="thread_title">スレッド</string>
|
||||
<string name="send_the_seller_a_message">出品者にメッセージを送る</string>
|
||||
<string name="hi_there_is_this_still_available">こんにちは、こちらはまだ入手可能ですか?</string>
|
||||
@@ -2048,15 +2036,7 @@
|
||||
<string name="could_not_fetch_invoice_from_details">%1$s から請求書を取得できませんでした: %2$s</string>
|
||||
<string name="could_not_open_the_compressed_file">圧縮ファイルを開けませんでした</string>
|
||||
<string name="couldnt_find_nwc_wallets">ウォレットが見つかりません</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst は Nostr Wallet Connect(NWC)に対応したウォレットアプリを見つけられませんでした。
|
||||
\n\n対処方法:
|
||||
\n\t1. NWC サポートを確認: お使いのウォレットアプリが Nostr Wallet Connect に対応しているか再確認してください。
|
||||
\n\t2. 接続を作成: ウォレットアプリで新しい NWC 接続を作成してください。
|
||||
\n\t3. Amethyst にリンク: ウォレットは通常、以下の3つの方法を提供します:
|
||||
\n\t\t3.1 自動リンク: 自動的に Amethyst を開いて接続するボタン。その場合、ボタンをクリックして Amethyst を開き、新しい画面で保存を押してください。
|
||||
\n\t\t3.2 手動リンク: この画面の貼り付けアイコンをクリックして直接入力できる接続 URI。
|
||||
\n\t\t3.3 QR コード: ウォレットが作成する QR コード。この画面の QR コードボタンから読み取れます。
|
||||
</string>
|
||||
<string name="couldnt_find_nwc_wallets_description">Amethyst は Nostr Wallet Connect(NWC)に対応したウォレットアプリを見つけられませんでした。 \n\n対処方法: \n\t1. NWC サポートを確認: お使いのウォレットアプリが Nostr Wallet Connect に対応しているか再確認してください。 \n\t2. 接続を作成: ウォレットアプリで新しい NWC 接続を作成してください。 \n\t3. Amethyst にリンク: ウォレットは通常、以下の3つの方法を提供します: \n\t\t3.1 自動リンク: 自動的に Amethyst を開いて接続するボタン。その場合、ボタンをクリックして Amethyst を開き、新しい画面で保存を押してください。 \n\t\t3.2 手動リンク: この画面の貼り付けアイコンをクリックして直接入力できる接続 URI。 \n\t\t3.3 QR コード: ウォレットが作成する QR コード。この画面の QR コードボタンから読み取れます。</string>
|
||||
<string name="create">作成</string>
|
||||
<string name="d">日</string>
|
||||
<string name="danger_zone">危険ゾーン</string>
|
||||
@@ -2723,11 +2703,8 @@
|
||||
<string name="proxy_section">Proxy Relay</string>
|
||||
<string name="proxy_section_explainer">filter.nostr.wine のように、アプリがフィードをダウンロードするために使用するアグリゲーター relay です。これにより outbox モデルが置き換えられ、アプリはリスト内の relay のみに接続するようになります。</string>
|
||||
<string name="public_chat">公開チャット</string>
|
||||
<string name="public_chat_explainer">パブリックチャットは Nostr 上の全員に公開されており、誰でも
|
||||
参加できます。特定のトピックを中心としたオープンなコミュニティに最適です。
|
||||
モデレーションは、その relay 上のポストを削除することで管理できます</string>
|
||||
<string name="public_chat_relays_explainer">このグループをホストする relay を 1〜3 件入力してください。
|
||||
Nostr クライアントはこの設定を使用して、メッセージのダウンロード先と送信先を決定します。</string>
|
||||
<string name="public_chat_explainer">パブリックチャットは Nostr 上の全員に公開されており、誰でも 参加できます。特定のトピックを中心としたオープンなコミュニティに最適です。 モデレーションは、その relay 上のポストを削除することで管理できます</string>
|
||||
<string name="public_chat_relays_explainer">このグループをホストする relay を 1〜3 件入力してください。 Nostr クライアントはこの設定を使用して、メッセージのダウンロード先と送信先を決定します。</string>
|
||||
<string name="public_chat_relays_title">Relay</string>
|
||||
<string name="public_chat_title">パブリックチャットのメタデータ</string>
|
||||
<string name="public_chats">パブリックチャット</string>
|
||||
@@ -2752,10 +2729,7 @@
|
||||
<string name="read_only_user">読み取り専用ユーザー</string>
|
||||
<string name="record_a_message_description">長押ししてメッセージを録音</string>
|
||||
<string name="relay_chat">relay チャット</string>
|
||||
<string name="relay_chat_explainer">relay チャットは、ホスト relay によって管理されるチャットグループです。
|
||||
Nostr 上の全員に公開されており、誰でも参加できます。
|
||||
特定のトピックを中心としたオープンなコミュニティに最適です。一部のグループは一時的なもので、
|
||||
チャットメッセージは時間とともに消えます</string>
|
||||
<string name="relay_chat_explainer">relay チャットは、ホスト relay によって管理されるチャットグループです。 Nostr 上の全員に公開されており、誰でも参加できます。 特定のトピックを中心としたオープンなコミュニティに最適です。一部のグループは一時的なもので、 チャットメッセージは時間とともに消えます</string>
|
||||
<string name="relay_chat_title">relay チャット</string>
|
||||
<string name="relay_management_tab_events">イベント</string>
|
||||
<string name="relay_management_tab_ips">IP</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user