From e89e8e5d010d4d4a9aaea5312aec82e5f0ee6380 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 14:19:27 -0400 Subject: [PATCH 01/11] moves mark as read to the AccountViewModel scope. --- .../amethyst/ui/note/NoteCompose.kt | 41 ++++++++----------- .../ui/screen/loggedIn/AccountViewModel.kt | 13 ++++++ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 4ba139024..af6635131 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -831,34 +831,17 @@ private fun CheckNewAndRenderNote( val backgroundColor = remember { mutableStateOf(defaultBackgroundColor) } LaunchedEffect(key1 = routeForLastRead, key2 = parentBackgroundColor?.value) { - launch(Dispatchers.IO) { - routeForLastRead?.let { - val lastTime = accountViewModel.account.loadLastRead(it) - - val createdAt = baseNote.createdAt() - if (createdAt != null) { - accountViewModel.account.markAsRead(it, createdAt) - - val isNew = createdAt > lastTime - - val newBackgroundColor = if (isNew) { - if (parentBackgroundColor != null) { - newItemColor.compositeOver(parentBackgroundColor.value) - } else { - newItemColor.compositeOver(defaultBackgroundColor) - } + routeForLastRead?.let { + accountViewModel.loadAndMarkAsRead(it, baseNote.createdAt()) { isNew -> + val newBackgroundColor = if (isNew) { + if (parentBackgroundColor != null) { + newItemColor.compositeOver(parentBackgroundColor.value) } else { - parentBackgroundColor?.value ?: defaultBackgroundColor - } - - if (newBackgroundColor != backgroundColor.value) { - launch(Dispatchers.Main) { - backgroundColor.value = newBackgroundColor - } + newItemColor.compositeOver(defaultBackgroundColor) } + } else { + parentBackgroundColor?.value ?: defaultBackgroundColor } - } ?: run { - val newBackgroundColor = parentBackgroundColor?.value ?: defaultBackgroundColor if (newBackgroundColor != backgroundColor.value) { launch(Dispatchers.Main) { @@ -866,6 +849,14 @@ private fun CheckNewAndRenderNote( } } } + } ?: run { + val newBackgroundColor = parentBackgroundColor?.value ?: defaultBackgroundColor + + if (newBackgroundColor != backgroundColor.value) { + launch(Dispatchers.Main) { + backgroundColor.value = newBackgroundColor + } + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index e2b26e48e..788f7cbae 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -720,6 +720,19 @@ class AccountViewModel(val account: Account) : ViewModel(), Dao { } } + fun loadAndMarkAsRead(routeForLastRead: String, baseNoteCreatedAt: Long?, onIsNew: (Boolean) -> Unit) { + viewModelScope.launch(Dispatchers.IO) { + val lastTime = account.loadLastRead(routeForLastRead) + + if (baseNoteCreatedAt != null) { + account.markAsRead(routeForLastRead, baseNoteCreatedAt) + onIsNew(baseNoteCreatedAt > lastTime) + } else { + onIsNew(false) + } + } + } + class Factory(val account: Account) : ViewModelProvider.Factory { override fun create(modelClass: Class): AccountViewModel { return AccountViewModel(account) as AccountViewModel From af9b0b444c154682497f37100548ad3b63b12ea8 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 15:29:13 -0400 Subject: [PATCH 02/11] Fix for not clearing the new post message. It adds a delay to allow the composer to save the viewModel after calling cancel --- .../amethyst/ui/actions/NewPostView.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index 0b72847d2..74f9103fc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -214,7 +214,10 @@ fun NewPostView( PostButton( onPost = { postViewModel.sendPost(relayList = relayList) - onClose() + scope.launch { + delay(100) + onClose() + } }, isActive = postViewModel.canPost() ) @@ -224,7 +227,10 @@ fun NewPostView( Spacer(modifier = StdHorzSpacer) CloseButton(onPress = { postViewModel.cancel() - onClose() + scope.launch { + delay(100) + onClose() + } }) }, backgroundColor = MaterialTheme.colors.surface, @@ -1220,9 +1226,7 @@ private fun MarkAsSensitive( @Composable fun CloseButton(onPress: () -> Unit) { Button( - onClick = { - onPress() - }, + onClick = onPress, shape = ButtonBorder, colors = ButtonDefaults .buttonColors( From b1edf4e934fa08dbce8e77be210de81986df75cd Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 17:09:36 -0400 Subject: [PATCH 03/11] Improving the Stability of VideoView --- .../amethyst/ui/components/VideoView.kt | 89 +++++++++++-------- .../amethyst/ui/screen/FeedViewModel.kt | 1 + 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index 44b0cb0b0..f8430b2f2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.components +import android.content.Context import android.graphics.Rect import android.graphics.drawable.Drawable import android.net.Uri @@ -206,34 +207,36 @@ fun VideoViewInner( ) } - val mediaItem = remember(videoUri) { - MediaItem.Builder() - .setMediaId(videoUri) - .setUri(videoUri) - .setMediaMetadata( - MediaMetadata.Builder() - .setArtist(authorName?.ifBlank { null }) - .setTitle(title?.ifBlank { null } ?: videoUri) - .setArtworkUri( - try { - if (artworkUri != null) { - Uri.parse(artworkUri) - } else { - null - } - } catch (e: Exception) { - null - } - ) - .build() - ) - .build() - } - if (!automaticallyStartPlayback.value) { ImageUrlWithDownloadButton(url = videoUri, showImage = automaticallyStartPlayback) } else { VideoPlayerActiveMutex(videoUri) { activeOnScreen -> + val mediaItem = remember(videoUri) { + mutableStateOf( + MediaItem.Builder() + .setMediaId(videoUri) + .setUri(videoUri) + .setMediaMetadata( + MediaMetadata.Builder() + .setArtist(authorName?.ifBlank { null }) + .setTitle(title?.ifBlank { null } ?: videoUri) + .setArtworkUri( + try { + if (artworkUri != null) { + Uri.parse(artworkUri) + } else { + null + } + } catch (e: Exception) { + null + } + ) + .build() + ) + .build() + ) + } + GetVideoController( mediaItem = mediaItem, videoUri = videoUri, @@ -258,7 +261,7 @@ fun VideoViewInner( @Composable @OptIn(UnstableApi::class) fun GetVideoController( - mediaItem: MediaItem, + mediaItem: MutableState, videoUri: String, defaultToStart: Boolean = false, nostrUriCallback: String? = null, @@ -311,7 +314,7 @@ fun GetVideoController( } } - controller.value?.setMediaItem(mediaItem) + controller.value?.setMediaItem(mediaItem.value) controller.value?.prepare() } else if (controller.value != it) { // discards the new controller because there is an existing one @@ -329,7 +332,7 @@ fun GetVideoController( it.volume = if (defaultToStart) 0f else 1f } - it.setMediaItem(mediaItem) + it.setMediaItem(mediaItem.value) it.prepare() } } @@ -347,7 +350,7 @@ fun GetVideoController( it.volume = if (defaultToStart) 0f else 1f } - it.setMediaItem(mediaItem) + it.setMediaItem(mediaItem.value) it.prepare() } } @@ -394,7 +397,7 @@ fun GetVideoController( } } - controller.value?.setMediaItem(mediaItem) + controller.value?.setMediaItem(mediaItem.value) controller.value?.prepare() } else if (controller.value != it) { // discards the new controller because there is an existing one @@ -460,7 +463,7 @@ fun VideoPlayerActiveMutex(videoUri: String, inner: @Composable (MutableState, onDialog: ((Boolean) -> Unit)? ) { - val context = LocalContext.current - ControlWhenPlayerIsActive(controller, keepPlaying, automaticallyStartPlayback, activeOnScreen) val controllerVisible = remember(controller) { @@ -520,9 +523,11 @@ private fun RenderVideoPlayer( } BoxWithConstraints() { - AndroidView( - modifier = if (roundedCorner) { - MaterialTheme.colors.imageModifier + val borders = MaterialTheme.colors.imageModifier + + val myModifier = remember { + if (roundedCorner) { + borders .defaultMinSize(minHeight = 100.dp) .align(Alignment.Center) } else { @@ -530,8 +535,11 @@ private fun RenderVideoPlayer( .fillMaxWidth() .defaultMinSize(minHeight = 100.dp) .align(Alignment.Center) - }, - factory = { + } + } + + val factory = remember(controller) { + { context: Context -> PlayerView(context).apply { player = controller layoutParams = FrameLayout.LayoutParams( @@ -556,6 +564,11 @@ private fun RenderVideoPlayer( ) } } + } + + AndroidView( + modifier = myModifier, + factory = factory ) waveform?.let { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt index f245ee538..b37a68596 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt @@ -63,6 +63,7 @@ class NostrChatroomFeedViewModel(val user: ChatroomKey, val account: Account) : } } +@Stable class NostrVideoFeedViewModel(val account: Account) : FeedViewModel(VideoFeedFilter(account)) { class Factory(val account: Account) : ViewModelProvider.Factory { override fun create(modelClass: Class): NostrVideoFeedViewModel { From 288d80d1632e687465f1a59685f6d971567ae82b Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 17:26:41 -0400 Subject: [PATCH 04/11] only updates reports for a different note --- .../vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt index d2edde0df..184d0c780 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt @@ -229,7 +229,7 @@ fun SlidingCarousel( VerticalPager( state = pagerState, beyondBoundsPageCount = 1, - modifier = Modifier.fillMaxSize(1f), + modifier = Modifier.fillMaxSize(), key = { index -> feed.value.getOrNull(index)?.idHex ?: "$index" } @@ -246,7 +246,7 @@ fun LoadedVideoCompose( accountViewModel: AccountViewModel, nav: (String) -> Unit ) { - var state by remember { + var state by remember(note) { mutableStateOf( AccountViewModel.NoteComposeReportState() ) From 69d7e82b7106e45fbf8fe77c6c4b317cb4c4cade Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 17:36:57 -0400 Subject: [PATCH 05/11] Increasing video cache from 90 to 150MB --- app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt index 27709e150..e4ad817e1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/VideoCache.kt @@ -12,7 +12,7 @@ import java.io.File @UnstableApi object VideoCache { - var exoPlayerCacheSize: Long = 90 * 1024 * 1024 // 90MB + var exoPlayerCacheSize: Long = 150 * 1024 * 1024 // 90MB var leastRecentlyUsedCacheEvictor = LeastRecentlyUsedCacheEvictor(exoPlayerCacheSize) From 9704d61a7a2a6a2c5ae7af1c64bdb498f7e56ba8 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 18:28:35 -0400 Subject: [PATCH 06/11] more remembers --- .../com/vitorpamplona/amethyst/ui/components/VideoView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index f8430b2f2..2b6c6144e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -572,7 +572,7 @@ private fun RenderVideoPlayer( ) waveform?.let { - Waveform(it, controller, Modifier.align(Alignment.Center)) + Waveform(it, controller, remember { Modifier.align(Alignment.Center) }) } val startingMuteState = remember(controller) { @@ -593,7 +593,7 @@ private fun RenderVideoPlayer( controller.volume = if (mute) 0f else 1f } - KeepPlayingButton(keepPlaying, controllerVisible, Modifier.align(Alignment.TopEnd)) { newKeepPlaying: Boolean -> + KeepPlayingButton(keepPlaying, controllerVisible, remember { Modifier.align(Alignment.TopEnd) }) { newKeepPlaying: Boolean -> // If something else is playing and the user marks this video to keep playing, stops the other one. if (newKeepPlaying) { if (keepPlayingMutex != null && keepPlayingMutex != controller) { From ee466aa1e4de968ace89f95dd17c0e0ed65a2400 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 25 Sep 2023 18:28:48 -0400 Subject: [PATCH 07/11] v0.78.1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ff673bbc3..b8752911c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.vitorpamplona.amethyst" minSdk 26 targetSdk 34 - versionCode 306 - versionName "0.78.0" + versionCode 307 + versionName "0.78.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { From e3df94338fce6a721ba866980a70945991c1ef78 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 26 Sep 2023 10:55:31 -0400 Subject: [PATCH 08/11] Fixes the access to playback state from the wrong thread --- .../amethyst/ui/components/VideoView.kt | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index 2b6c6144e..3e3f7d44b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -291,8 +291,8 @@ fun GetVideoController( DisposableEffect(key1 = videoUri) { // If it is not null, the user might have come back from a playing video, like clicking on // the notification of the video player. - scope.launch(Dispatchers.IO) { - if (controller.value == null) { + if (controller.value == null) { + scope.launch(Dispatchers.IO) { PlaybackClientController.prepareController( uid, videoUri, @@ -338,21 +338,21 @@ fun GetVideoController( } } } - } else { - controller.value?.let { - if (it.playbackState == Player.STATE_IDLE || it.playbackState == Player.STATE_ENDED) { - if (it.isPlaying) { - // There is a video playing, start this one on mute. - it.volume = 0f - } else { - // There is no other video playing. Use the default mute state to - // decide if sound is on or not. - it.volume = if (defaultToStart) 0f else 1f - } - - it.setMediaItem(mediaItem.value) - it.prepare() + } + } else { + controller.value?.let { + if (it.playbackState == Player.STATE_IDLE || it.playbackState == Player.STATE_ENDED) { + if (it.isPlaying) { + // There is a video playing, start this one on mute. + it.volume = 0f + } else { + // There is no other video playing. Use the default mute state to + // decide if sound is on or not. + it.volume = if (defaultToStart) 0f else 1f } + + it.setMediaItem(mediaItem.value) + it.prepare() } } } From 1387a0f62b04d133091f7a0d56264d5f5104624b Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 26 Sep 2023 10:56:28 -0400 Subject: [PATCH 09/11] Adds note to make sure we know the callback of a prepare video runs in the main thread. --- .../com/vitorpamplona/amethyst/ui/components/VideoView.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index 3e3f7d44b..d46790ddb 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -299,6 +299,8 @@ fun GetVideoController( nostrUriCallback, context ) { + // REQUIRED TO BE RUN IN THE MAIN THREAD + // checks again because of race conditions. if (controller.value == null) { // still prone to race conditions. controller.value = it @@ -382,6 +384,8 @@ fun GetVideoController( nostrUriCallback, context ) { + // REQUIRED TO BE RUN IN THE MAIN THREAD + // checks again to make sure no other thread has created a controller. if (controller.value == null) { controller.value = it From 600c9275946c07f812011a6c4b46b4636a315fe0 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 26 Sep 2023 11:01:42 -0400 Subject: [PATCH 10/11] v0.78.2 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b8752911c..84c9fd55c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.vitorpamplona.amethyst" minSdk 26 targetSdk 34 - versionCode 307 - versionName "0.78.1" + versionCode 308 + versionName "0.78.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { From 88701a97c7a96a939f221f17113f4d90768af154 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 26 Sep 2023 15:03:50 +0000 Subject: [PATCH 11/11] New Crowdin translations by GitHub Action --- app/src/main/res/values-cs/strings.xml | 12 ++++++++++++ app/src/main/res/values-de/strings.xml | 20 ++++++++++++++++++++ app/src/main/res/values-hu/strings.xml | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index b482e4c0f..e6cceb51d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -12,6 +12,7 @@ Nepodařilo se dešifrovat zprávu Obrázek skupiny Explicitní obsah + Spam Zneužívání identity Nezákonné jednání Neznámý @@ -169,6 +170,9 @@ Nostr Adresa nikdy nyní + h + m + d Nahota Neslušnost / Nenávistná řeč Nahlásit nenávistnou řeč @@ -263,6 +267,7 @@ Minimální zaps Maximální zaps Konsensus + (0–100)% Uzavřít po dnech Hlasování je uzavřeno pro nové hlasy @@ -334,6 +339,7 @@ \n5. Nastavte port Socks v této obrazovce \n6. Stiskněte tlačítko Aktivovat Tor + Port Orbot Socks Neplatné číslo portu Použít Orbot Odpojit Tor/Orbot @@ -341,6 +347,7 @@ Upozorní vás, když dorazí soukromá zpráva Přijaté zapsy Upozorní vás, když vás někdo zapsne + %1$s sats Od %1$s pro %1$s Upozornit: @@ -369,6 +376,7 @@ Při pokusu o získání informací z Relay se vyskytla chyba z %1$s Vlastník Verze + Programové vybavení Kontakt Podporované NIPs Vstupné @@ -388,10 +396,12 @@ Minimální PoW Ověření Platba + Cashu Token Vyměnit Není nastavena žádná Lightning adresa Token zkopírován do schránky ŽIVĚ + OFFLINE UKONČENO PLÁNOVÁNO Živé vysílání je offline @@ -467,6 +477,7 @@ Hlasy jsou váženy podle hodnoty zapu. Můžete nastavit minimální částku, abyste se vyhnuli spammerům, a maximální částku, abyste zabránili velkým zapperům, kteří by mohli ovládnout hlasování. Použijte stejnou částku v obou polích, aby byla hodnota každého hlasu stejná. Nechte prázdné pro přijetí libovolné částky. Nelze odeslat zap Poslat zprávu uživateli + OK Nepodařilo se dosáhnout %1$s: %2$s Nepodařilo se dosáhnout %1$s: %2$s Nepodařilo se zpracovat výsledek z %1$s: %2$s @@ -483,6 +494,7 @@ Uživatelské jméno nebo zobrazované jméno Uživatel %1$s nemá nastavenou bleskovou adresu pro přijímání satoshi Procenta + 25 Rozdělování Zapů s Přeposílání Zapů na Bleskové peněženky nenalezený diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 645ec5cb3..492787bcf 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -12,6 +12,7 @@ Nachricht konnte nicht entschlüsselt werden Gruppenbild Expliziter Inhalt + Spam Vortäuschung Illegales Verhalten Unbekannt @@ -35,6 +36,7 @@ Melden Sie sich mit einem privaten Schlüssel an, um Zaps senden zu können Melden Sie sich mit einem privaten Schlüssel an, um zu folgen Melden Sie sich mit einem privaten Schlüssel an, um nicht mehr zu folgen + Zaps Aufrufe Verstärken Verstärkt @@ -76,6 +78,7 @@ Fehler beim Hochladen des Bildes Relay-Adresse Beiträge + Bytes Fehler Startseite Private Nachrichten @@ -162,6 +165,7 @@ anz der Bedingungen ist erforderlich Öffentlicher Chat empfangene Beiträge Entfernen + Automatisch übersetzt von zu Zuerst in %1$s anzeigen @@ -171,6 +175,7 @@ anz der Bedingungen ist erforderlich nie jetzt s + m t Nacktheit Beleidigungen / Hassrede @@ -261,11 +266,13 @@ anz der Bedingungen ist erforderlich Erforderliche Felder: Zap-Empfänger Hauptbeschreibung der Umfrage… + Wahl %s Beschreibung der Umfrageoption Optionale Felder: Mindest-Zap-Betrag Maximaler Zap-Betrag Konsens + (0–100)% Schließen nach Tagen Umfrage ist für neue Stimmen geschlossen @@ -372,6 +379,8 @@ anz der Bedingungen ist erforderlich In Relay schreiben Ein Fehler ist beim Abrufen von Relay-Informationen von %1$s aufgetreten Inhaber + Version + Programme Kontakt Unterstützte NIPs Eintrittsgebühren @@ -379,6 +388,7 @@ anz der Bedingungen ist erforderlich Einschränkungen Länder Sprachen + Tags Veröffentlichungsrichtlinie Nachrichtenlänge Abonnements @@ -394,6 +404,8 @@ anz der Bedingungen ist erforderlich Einlösen Keine Lightning-Adresse festgelegt Token in die Zwischenablage kopiert + LIVE + OFFLINE BEENDET GEPLANT Livestream ist offline @@ -401,6 +413,9 @@ anz der Bedingungen ist erforderlich Das Abmelden löscht alle Ihre lokalen Informationen. Stellen Sie sicher, dass Sie Ihre privaten Schlüssel gesichert haben, um einen Kontoverlust zu vermeiden. Möchten Sie fortfahren? Gefolgte Tags Relais + Live + Gemeinschaft + Chats Genehmigte Beiträge Diese Gruppe hat keine Beschreibung oder Regeln. Sprechen Sie mit dem Eigentümer, um eine hinzuzufügen. Diese Community hat keine Beschreibung. Sprechen Sie mit dem Eigentümer, um eine hinzuzufügen. @@ -410,6 +425,7 @@ anz der Bedingungen ist erforderlich Immer Nur WLAN Nie + System Hell Dunkel Anwendungseinstellungen @@ -465,6 +481,7 @@ anz der Bedingungen ist erforderlich Die Abstimmungen werden nach der Höhe des Zaps gewichtet. Sie können einen Mindestbetrag festlegen, um Spam zu verhindern, und einen Höchstbetrag, um zu verhindern, dass große Zapper die Abstimmung dominieren. Verwenden Sie denselben Betrag in beiden Feldern, um sicherzustellen, dass jeder Stimme der gleiche Wert zukommt. Lassen Sie es leer, um jeden Betrag zu akzeptieren. Zap konnte nicht gesendet werden Mit dem Benutzer kommunizieren + OK Konnte %1$s nicht erreichen: %2$s Konnte %1$s nicht erreichen: %2$s Konnte das Ergebnis von %1$s nicht verarbeiten: %2$s @@ -472,6 +489,8 @@ anz der Bedingungen ist erforderlich Aktiv für: Startseite Nachrichten + Chats + Global Suche Zaps aufteilen und weiterleiten Unterstützende Clients werden Zaps an die hier hinzugefügten Benutzer aufteilen und weiterleiten, anstatt an Sie @@ -479,6 +498,7 @@ anz der Bedingungen ist erforderlich Benutzername oder Anzeigename Benutzer %1$s hat keine Lightning-Adresse eingerichtet, um Sats zu empfangen Prozent + 25 Zaps aufteilen mit Zaps weiterleiten an Lightning-Wallets nicht gefunden diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index a09371f77..54da2b17e 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -430,6 +430,8 @@ Képek/GIF-ek automatikus betöltése Videók automatikus betöltése Az URL előnézetének automatikus megjelenítése + Magával ragadó görgetés + Navigációs sáv görgetés közbeni elrejtése Kép Betöltése Spammerek Lenémítva. Kattínts a feloldásért @@ -502,4 +504,6 @@ Aláírási kérés elutasítva Nem található tárca a Lighning számla kifizetésére (Hiba: %1$s). Kérjük, a zap-ek használatához telepítsen egy Lightning pénztárcát Nem található tárca a Lighning számla kifizetésére. Kérjük, a zap-ek használatához telepítsen egy Lightning pénztárcát + Elrejtett Szavak + Új szó vagy mondat elrejtése