feat: improve notifications

This commit is contained in:
2025-05-29 11:03:15 +01:00
parent ab9fdd6b71
commit c66127cac2
76 changed files with 295 additions and 163 deletions

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="33"
android:viewportHeight="23"
android:tint="#FFFFFF">
<group android:scaleX="0.777027"
android:scaleY="0.5415643"
android:translateX="3.679054"
android:translateY="5.272011">
<path
android:pathData="M32.788,1.721C32.356,0.677 31.344,0 30.216,0H10.68C10.674,0 10.667,0 10.661,0C10.655,0 10.648,0 10.642,0C6.542,0 3.21,3.332 3.21,7.425C3.21,9.578 4.138,11.582 5.704,12.975L0.812,17.867C0.013,18.666 -0.225,19.858 0.207,20.896C0.638,21.94 1.65,22.617 2.778,22.617H22.314C22.32,22.617 22.327,22.617 22.34,22.617C22.346,22.617 22.353,22.617 22.366,22.617C26.458,22.617 29.791,19.285 29.791,15.192C29.791,13.039 28.862,11.035 27.296,9.642L32.188,4.75C32.981,3.951 33.22,2.759 32.788,1.721ZM2.714,19.858C2.694,19.813 2.707,19.8 2.733,19.775L8.109,14.399L22.391,19.452C22.404,19.459 22.424,19.465 22.437,19.465C22.456,19.472 22.475,19.478 22.494,19.491C22.527,19.51 22.552,19.542 22.572,19.581C22.578,19.588 22.578,19.594 22.585,19.601C22.591,19.613 22.591,19.626 22.591,19.639C22.591,19.652 22.598,19.665 22.598,19.678C22.598,19.794 22.469,19.897 22.327,19.897H2.785C2.753,19.91 2.733,19.91 2.714,19.858ZM25.208,18.956C25.208,18.95 25.201,18.937 25.201,18.93C25.176,18.827 25.143,18.73 25.105,18.634C25.098,18.621 25.098,18.608 25.092,18.595C25.053,18.492 25.002,18.395 24.95,18.299C24.944,18.286 24.931,18.266 24.924,18.253C24.815,18.06 24.686,17.88 24.538,17.712C24.525,17.699 24.512,17.686 24.499,17.673C24.422,17.596 24.344,17.519 24.26,17.448C24.248,17.441 24.235,17.428 24.228,17.422C24.151,17.358 24.067,17.299 23.977,17.242C23.964,17.235 23.951,17.222 23.938,17.216C23.848,17.158 23.751,17.106 23.655,17.055C23.635,17.042 23.61,17.035 23.59,17.022C23.493,16.977 23.39,16.932 23.281,16.9L16.674,14.56L9.037,11.86L9.011,11.853C9.004,11.853 9.004,11.853 8.998,11.847C8.811,11.776 8.624,11.692 8.437,11.595C6.884,10.777 5.924,9.178 5.924,7.425C5.924,5.891 6.658,4.525 7.799,3.661C7.799,3.667 7.806,3.68 7.806,3.687C7.831,3.783 7.864,3.88 7.902,3.977C7.915,4.009 7.928,4.041 7.941,4.074C7.973,4.144 8.005,4.209 8.038,4.28C8.051,4.312 8.07,4.344 8.083,4.37C8.128,4.454 8.179,4.531 8.237,4.608C8.263,4.641 8.283,4.673 8.308,4.705C8.353,4.763 8.399,4.821 8.45,4.873C8.469,4.899 8.489,4.924 8.515,4.944C8.579,5.015 8.656,5.079 8.727,5.143C8.753,5.169 8.779,5.189 8.811,5.208C8.882,5.266 8.953,5.317 9.03,5.369C9.043,5.382 9.056,5.388 9.075,5.401C9.166,5.459 9.262,5.511 9.359,5.556C9.385,5.569 9.411,5.582 9.436,5.595C9.539,5.64 9.643,5.685 9.746,5.717L24.009,10.764C24.016,10.764 24.022,10.77 24.022,10.77C24.209,10.841 24.389,10.919 24.563,11.015C26.117,11.834 27.077,13.432 27.077,15.185C27.084,16.726 26.342,18.092 25.208,18.956ZM30.267,2.836L24.892,8.211C24.879,8.205 24.86,8.199 24.847,8.192L10.622,3.165C10.603,3.158 10.584,3.152 10.571,3.145H10.564C10.545,3.139 10.532,3.132 10.513,3.12C10.506,3.113 10.5,3.107 10.493,3.1C10.48,3.094 10.474,3.081 10.467,3.074C10.461,3.068 10.455,3.055 10.455,3.049C10.448,3.036 10.442,3.023 10.435,3.01C10.435,3.004 10.429,2.991 10.429,2.978C10.429,2.965 10.422,2.946 10.422,2.926C10.422,2.913 10.429,2.907 10.429,2.894C10.448,2.797 10.564,2.714 10.687,2.714H30.229C30.261,2.714 30.28,2.714 30.3,2.759C30.306,2.797 30.293,2.817 30.267,2.836Z"
android:fillColor="#ffffff"/>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 771 B

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -17,7 +17,7 @@ class NoVerify extends EventVerifier {
final ndkCache = DbObjectBox();
final eventVerifier = kDebugMode ? NoVerify() : RustEventVerifier();
var ndk = Ndk(
final ndk = Ndk(
NdkConfig(
eventVerifier: eventVerifier,
cache: ndkCache,

View File

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 22
/// Strings: 1628 (74 per locale)
/// Strings: 1650 (75 per locale)
///
/// Built on 2025-05-28 at 12:41 UTC
/// Built on 2025-05-29 at 10:02 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View File

@ -54,7 +54,7 @@ class TranslationsAr extends Translations {
/// عدد مشاهدي البث
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
one: '1 مشاهد',
other: '${NumberFormat.decimalPattern('ar').format(n)} المشاهدين',
other: '{n:decimalPattern} المشاهدين',
);
@override late final _TranslationsStreamAr stream = _TranslationsStreamAr._(_root);
@ -80,6 +80,7 @@ class _TranslationsStreamAr extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusAr status = _TranslationsStreamStatusAr._(_root);
@override String started({required Object timestamp}) => 'بدأ ${timestamp}';
@override String notification({required Object name}) => '${name} بدأ البث المباشر!';
@override late final _TranslationsStreamChatAr chat = _TranslationsStreamChatAr._(_root);
}
@ -381,12 +382,13 @@ extension on TranslationsAr {
case 'anon': return 'هوية مخفية';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
one: '1 مشاهد',
other: '${NumberFormat.decimalPattern('ar').format(n)} المشاهدين',
other: '{n:decimalPattern} المشاهدين',
);
case 'stream.status.live': return 'بث مباشر';
case 'stream.status.ended': return 'انتهى';
case 'stream.status.planned': return 'مخطط';
case 'stream.started': return ({required Object timestamp}) => 'بدأ ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} بدأ البث المباشر!';
case 'stream.chat.disabled': return 'تم تعطيل الدردشة';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'تنتهي المهلة: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamCs extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusCs status = _TranslationsStreamStatusCs._(_root);
@override String started({required Object timestamp}) => 'Založeno ${timestamp}';
@override String notification({required Object name}) => '${name} byl spuštěn!';
@override late final _TranslationsStreamChatCs chat = _TranslationsStreamChatCs._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsCs {
case 'stream.status.ended': return 'KONEC';
case 'stream.status.planned': return 'PLÁNOVANÉ';
case 'stream.started': return ({required Object timestamp}) => 'Založeno ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} byl spuštěn!';
case 'stream.chat.disabled': return 'CHAT ZRUŠEN';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Časový limit vyprší: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamDa extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusDa status = _TranslationsStreamStatusDa._(_root);
@override String started({required Object timestamp}) => 'Startet ${timestamp}';
@override String notification({required Object name}) => '${name} gik live!';
@override late final _TranslationsStreamChatDa chat = _TranslationsStreamChatDa._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsDa {
case 'stream.status.ended': return 'AFSLUTTET';
case 'stream.status.planned': return 'PLANLAGT';
case 'stream.started': return ({required Object timestamp}) => 'Startet ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} gik live!';
case 'stream.chat.disabled': return 'CHAT DEAKTIVERET';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Timeout udløber: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -42,7 +42,7 @@ class TranslationsDe extends Translations {
/// Text, der den Benutzer auffordert, auf den Avatar-Platzhalter zu klicken, um den Upload zu starten
@override String get upload_avatar => 'Avatar hochladen';
/// Überschrift über gelistete Top-Streamer von zaps
/// Überschrift über gelistete Top-Streamer nach Zaps
@override String get most_zapped_streamers => 'Meistgezappte Streamer';
/// Kein Benutzer bei der Suche gefunden
@ -51,7 +51,7 @@ class TranslationsDe extends Translations {
/// Ein anonymer Benutzer
@override String get anon => 'Anon';
/// Anzahl der Betrachter des Streams
/// Anzahl der Zuschauer des Streams
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('de'))(n,
one: '1 Zuschauer',
other: '${NumberFormat.decimalPattern('de').format(n)} Zuschauer',
@ -80,6 +80,7 @@ class _TranslationsStreamDe extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusDe status = _TranslationsStreamStatusDe._(_root);
@override String started({required Object timestamp}) => 'Gestartet ${timestamp}';
@override String notification({required Object name}) => '${name} ging live!';
@override late final _TranslationsStreamChatDe chat = _TranslationsStreamChatDe._(_root);
}
@ -212,7 +213,7 @@ class _TranslationsStreamStatusDe extends TranslationsStreamStatusEn {
// Translations
@override String get live => 'LIVE';
@override String get ended => 'ENDED';
@override String get ended => 'BEENDET';
@override String get planned => 'GEPLANT';
}
@ -224,21 +225,21 @@ class _TranslationsStreamChatDe extends TranslationsStreamChatEn {
// Translations
@override String get disabled => 'CHAT DEAKTIVIERT';
@override String disabled_timeout({required Object time}) => 'Die Zeitüberschreitung läuft ab: ${time}';
@override String disabled_timeout({required Object time}) => 'Timeout läuft ab: ${time}';
/// Chat-Nachricht mit Zeitüberschreitungsereignissen
/// Chat-Nachricht mit Timeout-Ereignissen
@override TextSpan timeout({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [
mod,
const TextSpan(text: ' Zeitüberschreitung '),
const TextSpan(text: ' gibt '),
user,
const TextSpan(text: ' für '),
const TextSpan(text: ' einen Timeout für '),
time,
]);
/// Stream beendet Fußzeile am Ende des Chats
@override String get ended => 'STREAM BEENDET';
/// Chatnachricht mit Stream Zaps
/// Chat-Nachricht mit Stream-Zaps
@override TextSpan zap({required InlineSpan user, required InlineSpan amount}) => TextSpan(children: [
user,
const TextSpan(text: ' hat '),
@ -384,16 +385,17 @@ extension on TranslationsDe {
other: '${NumberFormat.decimalPattern('de').format(n)} Zuschauer',
);
case 'stream.status.live': return 'LIVE';
case 'stream.status.ended': return 'ENDED';
case 'stream.status.ended': return 'BEENDET';
case 'stream.status.planned': return 'GEPLANT';
case 'stream.started': return ({required Object timestamp}) => 'Gestartet ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} ging live!';
case 'stream.chat.disabled': return 'CHAT DEAKTIVIERT';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Die Zeitüberschreitung läuft ab: ${time}';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Timeout läuft ab: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [
mod,
const TextSpan(text: ' Zeitüberschreitung '),
const TextSpan(text: ' gibt '),
user,
const TextSpan(text: ' für '),
const TextSpan(text: ' einen Timeout für '),
time,
]);
case 'stream.chat.ended': return 'STREAM BEENDET';

View File

@ -80,6 +80,7 @@ class _TranslationsStreamEl extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusEl status = _TranslationsStreamStatusEl._(_root);
@override String started({required Object timestamp}) => 'Ξεκίνησε ${timestamp}';
@override String notification({required Object name}) => '${name} βγήκε ζωντανά!';
@override late final _TranslationsStreamChatEl chat = _TranslationsStreamChatEl._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsEl {
case 'stream.status.ended': return 'ENDED';
case 'stream.status.planned': return 'ΣΧΕΔΙΑΣΜΟΣ';
case 'stream.started': return ({required Object timestamp}) => 'Ξεκίνησε ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} βγήκε ζωντανά!';
case 'stream.chat.disabled': return 'ΑΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ ΣΥΝΟΜΙΛΊΑ';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Το χρονικό όριο λήγει: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -81,6 +81,7 @@ class TranslationsStreamEn {
// Translations
late final TranslationsStreamStatusEn status = TranslationsStreamStatusEn.internal(_root);
String started({required Object timestamp}) => 'Started ${timestamp}';
String notification({required Object name}) => '${name} went live!';
late final TranslationsStreamChatEn chat = TranslationsStreamChatEn.internal(_root);
}
@ -388,6 +389,7 @@ extension on Translations {
case 'stream.status.ended': return 'ENDED';
case 'stream.status.planned': return 'PLANNED';
case 'stream.started': return ({required Object timestamp}) => 'Started ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} went live!';
case 'stream.chat.disabled': return 'CHAT DISABLED';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Timeout expires: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamEs extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusEs status = _TranslationsStreamStatusEs._(_root);
@override String started({required Object timestamp}) => 'Comenzó ${timestamp}';
@override String notification({required Object name}) => '${name} ¡se ha puesto en marcha!';
@override late final _TranslationsStreamChatEs chat = _TranslationsStreamChatEs._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsEs {
case 'stream.status.ended': return 'FIN';
case 'stream.status.planned': return 'PLANIFICADO';
case 'stream.started': return ({required Object timestamp}) => 'Comenzó ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} ¡se ha puesto en marcha!';
case 'stream.chat.disabled': return 'CHAT DESHABILITADO';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'El tiempo de espera expira: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamFi extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusFi status = _TranslationsStreamStatusFi._(_root);
@override String started({required Object timestamp}) => 'Aloitettu ${timestamp}';
@override String notification({required Object name}) => '${name} meni suoraksi!';
@override late final _TranslationsStreamChatFi chat = _TranslationsStreamChatFi._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsFi {
case 'stream.status.ended': return 'ENDED';
case 'stream.status.planned': return 'SUUNNITELTU';
case 'stream.started': return ({required Object timestamp}) => 'Aloitettu ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} meni suoraksi!';
case 'stream.chat.disabled': return 'CHAT POISTETTU KÄYTÖSTÄ';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Aikakatkaisu päättyy: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -54,7 +54,7 @@ class TranslationsFr extends Translations {
/// Nombre de spectateurs du flux
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
one: '1 téléspectateur',
other: '${NumberFormat.decimalPattern('fr').format(n)} téléspectateurs',
other: '{n:decimalPattern} téléspectateurs',
);
@override late final _TranslationsStreamFr stream = _TranslationsStreamFr._(_root);
@ -80,6 +80,7 @@ class _TranslationsStreamFr extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusFr status = _TranslationsStreamStatusFr._(_root);
@override String started({required Object timestamp}) => 'Commencé à ${timestamp}';
@override String notification({required Object name}) => '${name} est en ligne !';
@override late final _TranslationsStreamChatFr chat = _TranslationsStreamChatFr._(_root);
}
@ -381,12 +382,13 @@ extension on TranslationsFr {
case 'anon': return 'Anonyme';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
one: '1 téléspectateur',
other: '${NumberFormat.decimalPattern('fr').format(n)} téléspectateurs',
other: '{n:decimalPattern} téléspectateurs',
);
case 'stream.status.live': return 'VIVRE';
case 'stream.status.ended': return 'FINI';
case 'stream.status.planned': return 'PRÉVU';
case 'stream.started': return ({required Object timestamp}) => 'Commencé à ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} est en ligne !';
case 'stream.chat.disabled': return 'CHAT DISABLED';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Le délai expire : ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamHu extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusHu status = _TranslationsStreamStatusHu._(_root);
@override String started({required Object timestamp}) => 'Elindult ${timestamp}';
@override String notification({required Object name}) => '${name} elindult!';
@override late final _TranslationsStreamChatHu chat = _TranslationsStreamChatHu._(_root);
}
@ -388,6 +389,7 @@ extension on TranslationsHu {
case 'stream.status.ended': return 'ENDED';
case 'stream.status.planned': return 'TERVEZETT';
case 'stream.started': return ({required Object timestamp}) => 'Elindult ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} elindult!';
case 'stream.chat.disabled': return 'CHAT KIKAPCSOLVA';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Az időkorlát lejár: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamIt extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusIt status = _TranslationsStreamStatusIt._(_root);
@override String started({required Object timestamp}) => 'Avviato ${timestamp}';
@override String notification({required Object name}) => '${name} è andato in onda!';
@override late final _TranslationsStreamChatIt chat = _TranslationsStreamChatIt._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsIt {
case 'stream.status.ended': return 'FINE';
case 'stream.status.planned': return 'PREVISTO';
case 'stream.started': return ({required Object timestamp}) => 'Avviato ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} è andato in onda!';
case 'stream.chat.disabled': return 'CHAT DISABILITATA';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Il timeout scade: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamJa extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusJa status = _TranslationsStreamStatusJa._(_root);
@override String started({required Object timestamp}) => '${timestamp} を開始';
@override String notification({required Object name}) => '${name} がライブを開始した!';
@override late final _TranslationsStreamChatJa chat = _TranslationsStreamChatJa._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsJa {
case 'stream.status.ended': return '終了';
case 'stream.status.planned': return '予定';
case 'stream.started': return ({required Object timestamp}) => '${timestamp} を開始';
case 'stream.notification': return ({required Object name}) => '${name} がライブを開始した!';
case 'stream.chat.disabled': return 'チャット無効';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'タイムアウト: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -54,7 +54,7 @@ class TranslationsKo extends Translations {
/// 스트림 시청자 수
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
one: '시청자 1명',
other: '${NumberFormat.decimalPattern('ko').format(n)} 시청자',
other: '{n:decimalPattern} 시청자',
);
@override late final _TranslationsStreamKo stream = _TranslationsStreamKo._(_root);
@ -80,6 +80,7 @@ class _TranslationsStreamKo extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusKo status = _TranslationsStreamStatusKo._(_root);
@override String started({required Object timestamp}) => '시작 ${timestamp}';
@override String notification({required Object name}) => '${name} 라이브가 시작되었습니다!';
@override late final _TranslationsStreamChatKo chat = _TranslationsStreamChatKo._(_root);
}
@ -381,12 +382,13 @@ extension on TranslationsKo {
case 'anon': return 'Anon';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
one: '시청자 1명',
other: '${NumberFormat.decimalPattern('ko').format(n)} 시청자',
other: '{n:decimalPattern} 시청자',
);
case 'stream.status.live': return '라이브';
case 'stream.status.ended': return '종료';
case 'stream.status.planned': return '계획된';
case 'stream.started': return ({required Object timestamp}) => '시작 ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} 라이브가 시작되었습니다!';
case 'stream.chat.disabled': return '채팅 사용 안 함';
case 'stream.chat.disabled_timeout': return ({required Object time}) => '시간 초과가 만료되었습니다: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamNl extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusNl status = _TranslationsStreamStatusNl._(_root);
@override String started({required Object timestamp}) => 'Begonnen met ${timestamp}';
@override String notification({required Object name}) => '${name} ging live!';
@override late final _TranslationsStreamChatNl chat = _TranslationsStreamChatNl._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsNl {
case 'stream.status.ended': return 'GESLOTEN';
case 'stream.status.planned': return 'GEPLAND';
case 'stream.started': return ({required Object timestamp}) => 'Begonnen met ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} ging live!';
case 'stream.chat.disabled': return 'CHAT UITGESCHAKELD';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Time-out loopt af: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamPl extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusPl status = _TranslationsStreamStatusPl._(_root);
@override String started({required Object timestamp}) => 'Start ${timestamp}';
@override String notification({required Object name}) => '${name} został uruchomiony!';
@override late final _TranslationsStreamChatPl chat = _TranslationsStreamChatPl._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsPl {
case 'stream.status.ended': return 'ZAKOŃCZONY';
case 'stream.status.planned': return 'PLANOWANE';
case 'stream.started': return ({required Object timestamp}) => 'Start ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} został uruchomiony!';
case 'stream.chat.disabled': return 'CZAT WYŁĄCZONY';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Upłynął limit czasu: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamPt extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusPt status = _TranslationsStreamStatusPt._(_root);
@override String started({required Object timestamp}) => 'Iniciado em ${timestamp}';
@override String notification({required Object name}) => '${name} foi ao ar!';
@override late final _TranslationsStreamChatPt chat = _TranslationsStreamChatPt._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsPt {
case 'stream.status.ended': return 'FINALIZADO';
case 'stream.status.planned': return 'PLANEJADO';
case 'stream.started': return ({required Object timestamp}) => 'Iniciado em ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} foi ao ar!';
case 'stream.chat.disabled': return 'BATE-PAPO DESATIVADO';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'O tempo limite expira: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamRo extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusRo status = _TranslationsStreamStatusRo._(_root);
@override String started({required Object timestamp}) => 'A început ${timestamp}';
@override String notification({required Object name}) => '${name} a intrat în direct!';
@override late final _TranslationsStreamChatRo chat = _TranslationsStreamChatRo._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsRo {
case 'stream.status.ended': return 'TERMINAT';
case 'stream.status.planned': return 'PLANIFICATE';
case 'stream.started': return ({required Object timestamp}) => 'A început ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} a intrat în direct!';
case 'stream.chat.disabled': return 'CHAT DEZACTIVAT';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Timpul expiră: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamRu extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusRu status = _TranslationsStreamStatusRu._(_root);
@override String started({required Object timestamp}) => 'Начало ${timestamp}';
@override String notification({required Object name}) => '${name} запустился!';
@override late final _TranslationsStreamChatRu chat = _TranslationsStreamChatRu._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsRu {
case 'stream.status.ended': return 'КОНЕЦ';
case 'stream.status.planned': return 'ПЛАНИРУЕМЫЙ';
case 'stream.started': return ({required Object timestamp}) => 'Начало ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} запустился!';
case 'stream.chat.disabled': return 'ЧАТ ОТКЛЮЧЕН';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Таймаут истекает: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -43,15 +43,15 @@ class TranslationsSv extends Translations {
@override String get upload_avatar => 'Ladda upp avatar';
/// Rubrik över listade topp streamers av zaps
@override String get most_zapped_streamers => 'De flesta zappade streamers';
@override String get most_zapped_streamers => 'De flest zappade streamers';
/// Ingen användare hittades vid sökning
@override String get no_user_found => 'Ingen användare hittades';
/// En anonym användare
@override String get anon => 'Anon';
@override String get anon => 'Anno';
/// Antal tittare på streamingen
/// Antal tittare på strömmingen
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
one: '1 tittare',
other: '${NumberFormat.decimalPattern('sv').format(n)} tittare',
@ -79,7 +79,8 @@ class _TranslationsStreamSv extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusSv status = _TranslationsStreamStatusSv._(_root);
@override String started({required Object timestamp}) => 'Startade ${timestamp}';
@override String started({required Object timestamp}) => 'Startad ${timestamp}';
@override String notification({required Object name}) => '${name} gick live!';
@override late final _TranslationsStreamChatSv chat = _TranslationsStreamChatSv._(_root);
}
@ -112,7 +113,7 @@ class _TranslationsButtonSv extends TranslationsButtonEn {
/// Knapptext för följ-knappen
@override String get follow => 'Följ';
/// Knapptext för avföljningsknappen
/// Knapptext för sluta följa knappen
@override String get unfollow => 'Sluta följa';
@override String get mute => 'Tysta';
@ -235,7 +236,7 @@ class _TranslationsStreamChatSv extends TranslationsStreamChatEn {
time,
]);
/// Stream avslutade sidfoten längst ner på chatten
/// Streama slutade sidfot längst ned i chatten
@override String get ended => 'STREAM AVSLUTAD';
/// Chattmeddelande som visar strömavbrott
@ -272,8 +273,8 @@ class _TranslationsSettingsProfileSv extends TranslationsSettingsProfileEn {
// Translations
@override String get display_name => 'Visa namn';
@override String get about => 'Om';
@override String get nip05 => 'Nostr Adress';
@override String get lud16 => 'Adress för blixtnedslag';
@override String get nip05 => 'Nostr adress';
@override String get lud16 => 'Lightning-adress';
@override late final _TranslationsSettingsProfileErrorSv error = _TranslationsSettingsProfileErrorSv._(_root);
}
@ -284,9 +285,9 @@ class _TranslationsSettingsWalletSv extends TranslationsSettingsWalletEn {
final TranslationsSv _root; // ignore: unused_field
// Translations
@override String get connect_wallet => 'Connect plånbok (NWC nostr+walletconnect://)';
@override String get connect_wallet => 'Anslut plånbok (NWC nostr+walletconnect://)';
@override String get disconnect_wallet => 'Koppla bort plånboken';
@override String get connect_1tap => '1-Tap-anslutning';
@override String get connect_1tap => '1-tryck anslutning';
@override String get paste => 'Klistra in URL';
@override late final _TranslationsSettingsWalletErrorSv error = _TranslationsSettingsWalletErrorSv._(_root);
}
@ -312,8 +313,8 @@ class _TranslationsStreamChatWriteSv extends TranslationsStreamChatWriteEn {
/// Etikett på inmatningsrutan för chattmeddelanden
@override String get label => 'Skriv meddelande';
/// Chattinmatningsmeddelande som visas när användaren endast är inloggad med pubkey
@override String get no_signer => 'Det går inte att skriva meddelanden med npub-inloggning';
/// Chattinmatningsmeddelande som visas när användaren endast är inloggad med publik nyckel
@override String get no_signer => 'Det går inte att skriva meddelanden med n-pub inloggning';
/// Chattinmatningsmeddelande som visas när användaren är utloggad
@override String get login => 'Logga in för att skicka meddelanden';
@ -327,7 +328,7 @@ class _TranslationsStreamChatBadgeSv extends TranslationsStreamChatBadgeEn {
// Translations
/// Rubrik över lista över användare som tilldelats en badge
/// Rubrik över listan över användare som tilldelas ett märke
@override String get awarded_to => 'Tilldelas till:';
}
@ -339,14 +340,14 @@ class _TranslationsStreamChatRaidSv extends TranslationsStreamChatRaidEn {
// Translations
/// Chatta raidmeddelande till en annan ström
/// Chatt raid meddelande till en annan ström
@override String to({required Object name}) => 'RAIDING ${name}';
/// Chat raid-meddelande från en annan ström
/// Chatt raid meddelande från en annan ström
@override String from({required Object name}) => 'RAID FRÅN ${name}';
/// Nedräkningstimer för auto-raiding
@override String countdown({required Object time}) => 'Raiding ${time}';
/// Nedräkningstimer för auto- radiering
@override String countdown({required Object time}) => 'Radiering i ${time}';
}
// Path: settings.profile.error
@ -366,7 +367,7 @@ class _TranslationsSettingsWalletErrorSv extends TranslationsSettingsWalletError
final TranslationsSv _root; // ignore: unused_field
// Translations
@override String get logged_out => 'Kan inte ansluta plånbok när du är inloggad';
@override String get logged_out => 'Kan inte ansluta plånbok när du är utloggad';
@override String get nwc_auth_event_not_found => 'Inget autentiseringshändelse för plånbok hittades';
}
@ -376,9 +377,9 @@ extension on TranslationsSv {
dynamic _flatMapFunction(String path) {
switch (path) {
case 'upload_avatar': return 'Ladda upp avatar';
case 'most_zapped_streamers': return 'De flesta zappade streamers';
case 'most_zapped_streamers': return 'De flest zappade streamers';
case 'no_user_found': return 'Ingen användare hittades';
case 'anon': return 'Anon';
case 'anon': return 'Anno';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
one: '1 tittare',
other: '${NumberFormat.decimalPattern('sv').format(n)} tittare',
@ -386,7 +387,8 @@ extension on TranslationsSv {
case 'stream.status.live': return 'LIVE';
case 'stream.status.ended': return 'AVSLUTAD';
case 'stream.status.planned': return 'PLANERADE';
case 'stream.started': return ({required Object timestamp}) => 'Startade ${timestamp}';
case 'stream.started': return ({required Object timestamp}) => 'Startad ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} gick live!';
case 'stream.chat.disabled': return 'CHAT AVSTÄNGD';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Tidsgränsen går ut: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [
@ -404,12 +406,12 @@ extension on TranslationsSv {
const TextSpan(text: ' sats'),
]);
case 'stream.chat.write.label': return 'Skriv meddelande';
case 'stream.chat.write.no_signer': return 'Det går inte att skriva meddelanden med npub-inloggning';
case 'stream.chat.write.no_signer': return 'Det går inte att skriva meddelanden med n-pub inloggning';
case 'stream.chat.write.login': return 'Logga in för att skicka meddelanden';
case 'stream.chat.badge.awarded_to': return 'Tilldelas till:';
case 'stream.chat.raid.to': return ({required Object name}) => 'RAIDING ${name}';
case 'stream.chat.raid.from': return ({required Object name}) => 'RAID FRÅN ${name}';
case 'stream.chat.raid.countdown': return ({required Object time}) => 'Raiding ${time}';
case 'stream.chat.raid.countdown': return ({required Object time}) => 'Radiering i ${time}';
case 'goal.title': return ({required Object amount}) => 'Mål: ${amount}';
case 'goal.remaining': return ({required Object amount}) => 'Kvarvarande: ${amount}';
case 'goal.complete': return 'KOMPLETT';
@ -448,14 +450,14 @@ extension on TranslationsSv {
case 'settings.button_wallet': return 'Inställningar för plånbok';
case 'settings.profile.display_name': return 'Visa namn';
case 'settings.profile.about': return 'Om';
case 'settings.profile.nip05': return 'Nostr Adress';
case 'settings.profile.lud16': return 'Adress för blixtnedslag';
case 'settings.profile.nip05': return 'Nostr adress';
case 'settings.profile.lud16': return 'Lightning-adress';
case 'settings.profile.error.logged_out': return 'Kan inte redigera profil när jag är utloggad';
case 'settings.wallet.connect_wallet': return 'Connect plånbok (NWC nostr+walletconnect://)';
case 'settings.wallet.connect_wallet': return 'Anslut plånbok (NWC nostr+walletconnect://)';
case 'settings.wallet.disconnect_wallet': return 'Koppla bort plånboken';
case 'settings.wallet.connect_1tap': return '1-Tap-anslutning';
case 'settings.wallet.connect_1tap': return '1-tryck anslutning';
case 'settings.wallet.paste': return 'Klistra in URL';
case 'settings.wallet.error.logged_out': return 'Kan inte ansluta plånbok när du är inloggad';
case 'settings.wallet.error.logged_out': return 'Kan inte ansluta plånbok när du är utloggad';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Inget autentiseringshändelse för plånbok hittades';
case 'login.username': return 'Användarnamn';
case 'login.amber': return 'Logga in med Amber';

View File

@ -80,6 +80,7 @@ class _TranslationsStreamTr extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusTr status = _TranslationsStreamStatusTr._(_root);
@override String started({required Object timestamp}) => 'Başlatıldı ${timestamp}';
@override String notification({required Object name}) => '${name} yayına girdi!';
@override late final _TranslationsStreamChatTr chat = _TranslationsStreamChatTr._(_root);
}
@ -231,8 +232,9 @@ class _TranslationsStreamChatTr extends TranslationsStreamChatEn {
mod,
const TextSpan(text: ' zaman aşımına uğradı '),
user,
const TextSpan(text: ' için '),
const TextSpan(text: ' '),
time,
const TextSpan(text: 'için'),
]);
/// Sohbetin alt kısmında akış sona erdi altbilgisi
@ -387,14 +389,16 @@ extension on TranslationsTr {
case 'stream.status.ended': return 'SONLANDI';
case 'stream.status.planned': return 'PLANLANMIŞ';
case 'stream.started': return ({required Object timestamp}) => 'Başlatıldı ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} yayına girdi!';
case 'stream.chat.disabled': return 'SOHBET DEVRE DIŞI';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Zaman aşımı sona eriyor: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [
mod,
const TextSpan(text: ' zaman aşımına uğradı '),
user,
const TextSpan(text: ' için '),
const TextSpan(text: ' '),
time,
const TextSpan(text: 'için'),
]);
case 'stream.chat.ended': return 'YAYIN SONLANDI';
case 'stream.chat.zap': return ({required InlineSpan user, required InlineSpan amount}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamUk extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusUk status = _TranslationsStreamStatusUk._(_root);
@override String started({required Object timestamp}) => 'Запустив ${timestamp}';
@override String notification({required Object name}) => '${name} запрацював!';
@override late final _TranslationsStreamChatUk chat = _TranslationsStreamChatUk._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsUk {
case 'stream.status.ended': return 'ЗАКІНЧЕНО';
case 'stream.status.planned': return 'ЗАПЛАНОВАНО';
case 'stream.started': return ({required Object timestamp}) => 'Запустив ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} запрацював!';
case 'stream.chat.disabled': return 'ЧАТ ВІДКЛЮЧЕНО';
case 'stream.chat.disabled_timeout': return ({required Object time}) => 'Тайм-аут закінчився: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -80,6 +80,7 @@ class _TranslationsStreamZh extends TranslationsStreamEn {
// Translations
@override late final _TranslationsStreamStatusZh status = _TranslationsStreamStatusZh._(_root);
@override String started({required Object timestamp}) => '開始 ${timestamp}';
@override String notification({required Object name}) => '${name} 已啟用!';
@override late final _TranslationsStreamChatZh chat = _TranslationsStreamChatZh._(_root);
}
@ -387,6 +388,7 @@ extension on TranslationsZh {
case 'stream.status.ended': return '結束';
case 'stream.status.planned': return '計劃';
case 'stream.started': return ({required Object timestamp}) => '開始 ${timestamp}';
case 'stream.notification': return ({required Object name}) => '${name} 已啟用!';
case 'stream.chat.disabled': return '關閉聊天';
case 'stream.chat.disabled_timeout': return ({required Object time}) => '超時過期: ${time}';
case 'stream.chat.timeout': return ({required InlineSpan mod, required InlineSpan user, required InlineSpan time}) => TextSpan(children: [

View File

@ -10,7 +10,7 @@ no_user_found: لم يتم العثور على مستخدم
anon: هوية مخفية
viewers:
one: 1 مشاهد
other: "${n:decimalPattern} المشاهدين"
other: "{n:decimalPattern} المشاهدين"
"@viewers":
description: عدد مشاهدي البث
"@anon":
@ -21,10 +21,11 @@ stream:
ended: انتهى
planned: مخطط
started: بدأ $timestamp
notification: ${name} بدأ البث المباشر!
chat:
disabled: تم تعطيل الدردشة
disabled_timeout: "تنتهي المهلة: $time"
timeout(rich): $mod انتهى الوقت $user لـ $time
timeout(rich): $mod انتهى الوقت $user لـ ${time}
"@timeout":
description: رسالة دردشة تظهر أحداث المهلة
ended: انتهى البث

View File

@ -22,10 +22,11 @@ stream:
ended: KONEC
planned: PLÁNOVANÉ
started: Založeno $timestamp
notification: ${name} byl spuštěn!
chat:
disabled: CHAT ZRUŠEN
disabled_timeout: "Časový limit vyprší: $time"
timeout(rich): $mod vypršel čas $user pro $time
timeout(rich): $mod vypršel čas $user pro ${time}
"@timeout":
description: Zpráva chatu zobrazující události časového limitu
ended: STREAM UKONČEN

View File

@ -22,10 +22,11 @@ stream:
ended: AFSLUTTET
planned: PLANLAGT
started: Startet $timestamp
notification: ${name} gik live!
chat:
disabled: CHAT DEAKTIVERET
disabled_timeout: "Timeout udløber: $time"
timeout(rich): $mod udløbet $user for $time
timeout(rich): $mod udløbet $user for ${time}
"@timeout":
description: Chatbesked, der viser timeout-hændelser
ended: STREAM AFSLUTTET

View File

@ -4,7 +4,7 @@ upload_avatar: Avatar hochladen
klicken, um den Upload zu starten
most_zapped_streamers: Meistgezappte Streamer
"@most_zapped_streamers":
description: Überschrift über gelistete Top-Streamer von zaps
description: Überschrift über gelistete Top-Streamer nach Zaps
no_user_found: Kein Benutzer gefunden
"@no_user_found":
description: Kein Benutzer bei der Suche gefunden
@ -13,27 +13,28 @@ viewers:
one: 1 Zuschauer
other: ${n:decimalPattern} Zuschauer
"@viewers":
description: Anzahl der Betrachter des Streams
description: Anzahl der Zuschauer des Streams
"@anon":
description: Ein anonymer Benutzer
stream:
status:
live: LIVE
ended: ENDED
ended: BEENDET
planned: GEPLANT
started: Gestartet $timestamp
notification: ${name} ging live!
chat:
disabled: CHAT DEAKTIVIERT
disabled_timeout: "Die Zeitüberschreitung läuft ab: $time"
timeout(rich): $mod Zeitüberschreitung $user für $time
disabled_timeout: "Timeout läuft ab: $time"
timeout(rich): $mod gibt $user einen Timeout für ${time}
"@timeout":
description: Chat-Nachricht mit Zeitüberschreitungsereignissen
description: Chat-Nachricht mit Timeout-Ereignissen
ended: STREAM BEENDET
"@ended":
description: Stream beendet Fußzeile am Ende des Chats
zap(rich): $user hat $amount sats gezappt
"@zap":
description: Chatnachricht mit Stream Zaps
description: Chat-Nachricht mit Stream-Zaps
write:
label: Nachricht schreiben
"@label":

View File

@ -22,10 +22,11 @@ stream:
ended: ENDED
planned: ΣΧΕΔΙΑΣΜΟΣ
started: Ξεκίνησε $timestamp
notification: ${name} βγήκε ζωντανά!
chat:
disabled: ΑΠΕΝΕΡΓΟΠΟΙΗΜΈΝΗ ΣΥΝΟΜΙΛΊΑ
disabled_timeout: "Το χρονικό όριο λήγει: $time"
timeout(rich): $mod χρονομετρημένη λήξη $user για $time
timeout(rich): $mod χρονομετρημένη λήξη $user για ${time}
"@timeout":
description: Μήνυμα συνομιλίας που εμφανίζει συμβάντα timeout
ended: STREAM ΤΕΛΕΙΩΣΕ

View File

@ -21,6 +21,7 @@ stream:
ended: ENDED
planned: PLANNED
started: Started $timestamp
notification: ${name} went live!
chat:
disabled: CHAT DISABLED
disabled_timeout: "Timeout expires: $time"

View File

@ -22,10 +22,11 @@ stream:
ended: FIN
planned: PLANIFICADO
started: Comenzó $timestamp
notification: ${name} ¡se ha puesto en marcha!
chat:
disabled: CHAT DESHABILITADO
disabled_timeout: "El tiempo de espera expira: $time"
timeout(rich): $mod timed out $user para $time
timeout(rich): $mod timed out $user para ${time}
"@timeout":
description: Mensaje de chat que muestra los eventos de tiempo de espera
ended: STREAM FINED

View File

@ -22,10 +22,11 @@ stream:
ended: ENDED
planned: SUUNNITELTU
started: Aloitettu $timestamp
notification: ${name} meni suoraksi!
chat:
disabled: CHAT POISTETTU KÄYTÖSTÄ
disabled_timeout: "Aikakatkaisu päättyy: $time"
timeout(rich): $mod ajastettu $user for $time
timeout(rich): $mod ajastettu $user for ${time}
"@timeout":
description: Chat-viesti, joka näyttää aikakatkaisutapahtumat
ended: STREAM PÄÄTTYNYT

View File

@ -11,7 +11,7 @@ no_user_found: Aucun utilisateur trouvé
anon: Anonyme
viewers:
one: 1 téléspectateur
other: "${n:decimalPattern} téléspectateurs"
other: "{n:decimalPattern} téléspectateurs"
"@viewers":
description: Nombre de spectateurs du flux
"@anon":
@ -22,10 +22,11 @@ stream:
ended: FINI
planned: PRÉVU
started: Commencé à $timestamp
notification: ${name} est en ligne !
chat:
disabled: CHAT DISABLED
disabled_timeout: "Le délai expire : $time"
timeout(rich): $mod $user a expiré dans le temps pour $time
timeout(rich): $mod $user a expiré dans le temps pour ${time}
"@timeout":
description: Message de chat indiquant les événements de dépassement de délai
ended: STREAM ENDED

View File

@ -22,6 +22,7 @@ stream:
ended: ENDED
planned: TERVEZETT
started: Elindult $timestamp
notification: ${name} elindult!
chat:
disabled: CHAT KIKAPCSOLVA
disabled_timeout: "Az időkorlát lejár: $time"

View File

@ -22,10 +22,11 @@ stream:
ended: FINE
planned: PREVISTO
started: Avviato $timestamp
notification: ${name} è andato in onda!
chat:
disabled: CHAT DISABILITATA
disabled_timeout: "Il timeout scade: $time"
timeout(rich): $mod time out $user per $time
timeout(rich): $mod time out $user per ${time}
"@timeout":
description: Messaggio di chat che mostra gli eventi di timeout
ended: STREAM ENDED

View File

@ -21,10 +21,11 @@ stream:
ended: 終了
planned: 予定
started: $timestamp を開始
notification: ${name} がライブを開始した!
chat:
disabled: チャット無効
disabled_timeout: タイムアウト: $time
timeout(rich): $mod タイムアウト $user for $time
timeout(rich): $mod タイムアウト $user for ${time}
"@timeout":
description: タイムアウトイベントを表示するチャットメッセージ
ended: 配信終了

View File

@ -10,7 +10,7 @@ no_user_found: 사용자를 찾을 수 없습니다.
anon: Anon
viewers:
one: 시청자 1명
other: "${n:decimalPattern} 시청자"
other: "{n:decimalPattern} 시청자"
"@viewers":
description: 스트림 시청자 수
"@anon":
@ -21,10 +21,11 @@ stream:
ended: 종료
planned: 계획된
started: 시작 $timestamp
notification: ${name} 라이브가 시작되었습니다!
chat:
disabled: 채팅 사용 안 함
disabled_timeout: "시간 초과가 만료되었습니다: $time"
timeout(rich): $mod 시간 초과됨 $user $time
timeout(rich): $mod 시간 초과됨 $user ${time}
"@timeout":
description: 시간 초과 이벤트를 표시하는 채팅 메시지
ended: 스트림 종료

View File

@ -22,10 +22,11 @@ stream:
ended: GESLOTEN
planned: GEPLAND
started: Begonnen met $timestamp
notification: ${name} ging live!
chat:
disabled: CHAT UITGESCHAKELD
disabled_timeout: "Time-out loopt af: $time"
timeout(rich): $mod timed out $user voor $time
timeout(rich): $mod timed out $user voor ${time}
"@timeout":
description: Chatbericht met time-outgebeurtenissen
ended: STREAM BEËINDIGD

View File

@ -22,10 +22,11 @@ stream:
ended: ZAKOŃCZONY
planned: PLANOWANE
started: Start $timestamp
notification: ${name} został uruchomiony!
chat:
disabled: CZAT WYŁĄCZONY
disabled_timeout: "Upłynął limit czasu: $time"
timeout(rich): $mod upłynął limit czasu $user dla $time
timeout(rich): $mod upłynął limit czasu $user dla ${time}
"@timeout":
description: Komunikat czatu pokazujący zdarzenia przekroczenia limitu czasu
ended: TRANSMISJA ZAKOŃCZONA

View File

@ -22,10 +22,11 @@ stream:
ended: FINALIZADO
planned: PLANEJADO
started: Iniciado em $timestamp
notification: ${name} foi ao ar!
chat:
disabled: BATE-PAPO DESATIVADO
disabled_timeout: "O tempo limite expira: $time"
timeout(rich): $mod Tempo esgotado $user para $time
timeout(rich): $mod Tempo esgotado $user para ${time}
"@timeout":
description: Mensagem de bate-papo mostrando eventos de tempo limite
ended: TRANSMISSÃO ENCERRADA

View File

@ -22,10 +22,11 @@ stream:
ended: TERMINAT
planned: PLANIFICATE
started: A început $timestamp
notification: ${name} a intrat în direct!
chat:
disabled: CHAT DEZACTIVAT
disabled_timeout: "Timpul expiră: $time"
timeout(rich): $mod Timed out $user pentru $time
timeout(rich): $mod Timed out $user pentru ${time}
"@timeout":
description: Mesaj de chat care afișează evenimentele de timeout
ended: STREAM ÎNCHEIAT

View File

@ -22,10 +22,11 @@ stream:
ended: КОНЕЦ
planned: ПЛАНИРУЕМЫЙ
started: Начало $timestamp
notification: ${name} запустился!
chat:
disabled: ЧАТ ОТКЛЮЧЕН
disabled_timeout: "Таймаут истекает: $time"
timeout(rich): $mod тайм-аут $user для $time
timeout(rich): $mod тайм-аут $user для ${time}
"@timeout":
description: Сообщение в чате, показывающее события по тайм-ауту
ended: ТРАНСЛЯЦИЯ ОКОНЧЕНА

View File

@ -2,18 +2,18 @@ upload_avatar: Ladda upp avatar
"@upload_avatar":
description: Text som uppmanar användaren att trycka på avatar platshållaren för
att påbörja uppladdningen
most_zapped_streamers: De flesta zappade streamers
most_zapped_streamers: De flest zappade streamers
"@most_zapped_streamers":
description: Rubrik över listade topp streamers av zaps
no_user_found: Ingen användare hittades
"@no_user_found":
description: Ingen användare hittades vid sökning
anon: Anon
anon: Anno
viewers:
one: 1 tittare
other: ${n:decimalPattern} tittare
"@viewers":
description: Antal tittare på streamingen
description: Antal tittare på strömmingen
"@anon":
description: En anonym användare
stream:
@ -21,16 +21,17 @@ stream:
live: LIVE
ended: AVSLUTAD
planned: PLANERADE
started: Startade $timestamp
started: Startad $timestamp
notification: ${name} gick live!
chat:
disabled: CHAT AVSTÄNGD
disabled_timeout: "Tidsgränsen går ut: $time"
timeout(rich): $mod tidsbegränsad $user för $time
timeout(rich): $mod tidsbegränsad $user för ${time}
"@timeout":
description: Chattmeddelande som visar timeout-händelser
ended: STREAM AVSLUTAD
"@ended":
description: Stream avslutade sidfoten längst ner på chatten
description: Streama slutade sidfot längst ned i chatten
zap(rich): $user zapped $amount sats
"@zap":
description: Chattmeddelande som visar strömavbrott
@ -38,27 +39,27 @@ stream:
label: Skriv meddelande
"@label":
description: Etikett på inmatningsrutan för chattmeddelanden
no_signer: Det går inte att skriva meddelanden med npub-inloggning
no_signer: Det går inte att skriva meddelanden med n-pub inloggning
"@no_signer":
description: Chattinmatningsmeddelande som visas när användaren endast är
inloggad med pubkey
inloggad med publik nyckel
login: Logga in för att skicka meddelanden
"@login":
description: Chattinmatningsmeddelande som visas när användaren är utloggad
badge:
awarded_to: "Tilldelas till:"
"@awarded_to":
description: Rubrik över lista över användare som tilldelats en badge
description: Rubrik över listan över användare som tilldelas ett märke
raid:
to: RAIDING $name
to: RAIDING ${name}
"@to":
description: Chatta raidmeddelande till en annan ström
from: RAID FRÅN $name
description: Chatt raid meddelande till en annan ström
from: RAID FRÅN ${name}
"@from":
description: Chat raid-meddelande från en annan ström
countdown: Raiding $time
description: Chatt raid meddelande från en annan ström
countdown: Radiering i ${time}
"@countdown":
description: Nedräkningstimer för auto-raiding
description: Nedräkningstimer för auto- radiering
goal:
title: "Mål: $amount"
remaining: "Kvarvarande: $amount"
@ -74,7 +75,7 @@ button:
description: Knapptext för följ-knappen
unfollow: Sluta följa
"@unfollow":
description: Knapptext för avföljningsknappen
description: Knapptext för sluta följa knappen
mute: Tysta
unmute: Avtysta
share: Dela
@ -82,9 +83,9 @@ button:
connect: Anslut
settings: Inställningar
embed:
article_by: Artikel av $name
article_by: Artikel av ${name}
note_by: Anteckning av $name
live_stream_by: Direktsändning via $name
live_stream_by: Direktsändning via ${name}
stream_list:
following: Följer
live: Live
@ -114,17 +115,17 @@ settings:
profile:
display_name: Visa namn
about: Om
nip05: Nostr Adress
lud16: Adress för blixtnedslag
nip05: Nostr adress
lud16: Lightning-adress
error:
logged_out: Kan inte redigera profil när jag är utloggad
wallet:
connect_wallet: Connect plånbok (NWC nostr+walletconnect://)
connect_wallet: Anslut plånbok (NWC nostr+walletconnect://)
disconnect_wallet: Koppla bort plånboken
connect_1tap: 1-Tap-anslutning
connect_1tap: 1-tryck anslutning
paste: Klistra in URL
error:
logged_out: Kan inte ansluta plånbok när du är inloggad
logged_out: Kan inte ansluta plånbok när du är utloggad
nwc_auth_event_not_found: Inget autentiseringshändelse för plånbok hittades
login:
username: Användarnamn

View File

@ -22,10 +22,11 @@ stream:
ended: SONLANDI
planned: PLANLANMIŞ
started: Başlatıldı $timestamp
notification: ${name} yayına girdi!
chat:
disabled: SOHBET DEVRE DIŞI
disabled_timeout: "Zaman aşımı sona eriyor: $time"
timeout(rich): $mod zaman aşımına uğradı $user için $time
timeout(rich): $mod zaman aşımına uğradı $user ${time}için
"@timeout":
description: Zaman aşımı olaylarını gösteren sohbet mesajı
ended: YAYIN SONLANDI

View File

@ -22,10 +22,11 @@ stream:
ended: ЗАКІНЧЕНО
planned: ЗАПЛАНОВАНО
started: Запустив $timestamp
notification: ${name} запрацював!
chat:
disabled: ЧАТ ВІДКЛЮЧЕНО
disabled_timeout: "Тайм-аут закінчився: $time"
timeout(rich): $mod таймінг $user для $time
timeout(rich): $mod таймінг $user для ${time}
"@timeout":
description: Повідомлення в чаті про події тайм-ауту
ended: СТРІМ ЗАКІНЧИВСЯ

View File

@ -21,10 +21,11 @@ stream:
ended: 結束
planned: 計劃
started: 開始 $timestamp
notification: ${name} 已啟用!
chat:
disabled: 關閉聊天
disabled_timeout: 超時過期: $time
timeout(rich): $mod 超時 $user for $time
timeout(rich): $mod 超時 $user for ${time}
"@timeout":
description: 顯示逾時事件的聊天訊息
ended: 串流結束

View File

@ -28,7 +28,7 @@ Future<void> main() async {
builder: () => MainPlayer(),
config: AudioServiceConfig(
androidNotificationChannelId: "io.nostrlabs.zap_stream_flutter.player",
androidNotificationChannelName: "player",
androidNotificationChannelName: "Player Status",
androidNotificationOngoing: true
),
);

View File

@ -10,11 +10,14 @@ import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:ndk/ndk.dart';
import 'package:ndk_objectbox/ndk_objectbox.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:zap_stream_flutter/const.dart';
import 'package:http/http.dart' as http;
import 'package:zap_stream_flutter/firebase_options.dart';
import 'package:zap_stream_flutter/i18n/strings.g.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/profile.dart';
class Notepush {
final String base;
@ -183,34 +186,68 @@ class NotificationsStore extends ValueNotifier<NotificationsState?> {
}
}
// global notifications store
final notifications = NotificationsStore(null);
Future<void> _initLocalNotifications() async {
await localNotifications.initialize(
InitializationSettings(
android: AndroidInitializationSettings("@drawable/ic_stat_name"),
iOS: DarwinInitializationSettings(),
),
);
}
Future<void> setupNotifications() async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
@pragma('vm:entry-point')
Future<void> _onBackgroundNotification(RemoteMessage msg) async {
await LocaleSettings.useDeviceLocale();
final cache = DbObjectBox(attach: true);
await _initLocalNotifications();
await _handleNotification(msg, cache);
}
final signer = ndk.accounts.getLoggedAccount()?.signer;
if (signer != null) {
final pusher = Notepush(dotenv.env["NOTEPUSH_URL"]!, signer: signer);
final fbase = FirebaseMessaging.instance;
FirebaseMessaging.onMessage.listen((msg) {
developer.log(msg.notification?.body ?? "");
Future<void> _onNotification(RemoteMessage msg) async {
await _handleNotification(msg, ndkCache);
}
Future<void> _handleNotification(RemoteMessage msg, DbObjectBox cache) async {
final notification = msg.notification;
if (notification != null && notification.android != null) {
FlutterLocalNotificationsPlugin().show(
final String? json = msg.data["nostr_event"];
final event =
json != null ? Nip01Event.fromJson(JsonCodec().decode(json)) : null;
await _showNotification(notification, ndkCache, event);
}
}
Future<void> _showNotification(
RemoteNotification notification,
DbObjectBox cache,
Nip01Event? event,
) async {
final stream = event != null ? StreamEvent(event) : null;
final hostProfile =
stream != null ? await cache.loadMetadata(stream.info.host) : null;
final newTitle =
hostProfile != null
? t.stream.notification(
name: ProfileNameWidget.nameFromProfile(hostProfile),
)
: null;
localNotifications.show(
notification.hashCode,
notification.title,
notification.body,
newTitle ?? notification.title,
stream?.info.title ?? notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
notification.android!.channelId ?? "fcm",
"fcm",
"Push Notifications",
category: AndroidNotificationCategory.social
),
),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((msg) {
Future<void> _onOpenMessage(RemoteMessage msg) async {
try {
final notification = msg.notification;
final String? json = msg.data["nostr_event"];
@ -223,11 +260,26 @@ Future<void> setupNotifications() async {
} catch (e) {
developer.log("Failed to process push notification\n ${e.toString()}");
}
});
}
final settings = await fbase.requestPermission(provisional: true);
await fbase.setAutoInitEnabled(true);
await fbase.setForegroundNotificationPresentationOptions(
// global notifications store
final notifications = NotificationsStore(null);
Future<void> setupNotifications() async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
final signer = ndk.accounts.getLoggedAccount()?.signer;
if (signer != null) {
FirebaseMessaging.onMessage.listen(_onNotification);
//FirebaseMessaging.onBackgroundMessage(_onBackgroundNotification);
FirebaseMessaging.onMessageOpenedApp.listen(_onOpenMessage);
final settings = await FirebaseMessaging.instance.requestPermission(
provisional: true,
);
await FirebaseMessaging.instance.setAutoInitEnabled(true);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
@ -239,13 +291,10 @@ Future<void> setupNotifications() async {
throw "APNS token not availble";
}
}
await localNotifications.initialize(
InitializationSettings(
android: AndroidInitializationSettings("@mipmap/ic_launcher"),
iOS: DarwinInitializationSettings(),
),
);
fbase.onTokenRefresh.listen((token) async {
await _initLocalNotifications();
final pusher = Notepush(dotenv.env["NOTEPUSH_URL"]!, signer: signer);
FirebaseMessaging.instance.onTokenRefresh.listen((token) async {
developer.log("NEW TOKEN: $token");
await pusher.register(token);
await pusher.setNotificationSettings(token, [30_311]);

View File

@ -84,4 +84,4 @@ flutter:
flutter_launcher_icons:
ios: true
image_path: assets/logo.png
image_path: assets/logo.jpg