9 Commits

Author SHA1 Message Date
1575c7dd09 fix: ios 2025-05-30 14:56:18 +01:00
3914768eeb chore: update translations 2025-05-30 14:17:39 +01:00
edfb5bb80d chore: bump version 2025-05-30 14:06:58 +01:00
33ad784e87 fix: missing stream hides live page 2025-05-30 14:03:28 +01:00
0422341bf8 chore: bump flutter version 2025-05-30 13:59:46 +01:00
8af62e0b32 chore: bump ndk 2025-05-30 13:53:40 +01:00
cd6c50f9bd feat: add notifications button to profile page 2025-05-30 13:51:07 +01:00
428771462d feat: live streaming
closes #43
2025-05-30 13:48:37 +01:00
917147605b feat: default ln address to zap.stream for new accounts 2025-05-29 14:31:13 +01:00
68 changed files with 2755 additions and 128 deletions

View File

@ -12,7 +12,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: stable
flutter-version: 3.29.3
flutter-version: 3.32.0
- run: flutter pub get
- run: flutter build appbundle
env:
@ -53,6 +53,6 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: stable
flutter-version: 3.29.3
flutter-version: 3.32.0
- run: flutter pub get
- run: flutter build ios --no-codesign

View File

@ -16,7 +16,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: stable
flutter-version: 3.29.3
flutter-version: 3.32.0
- run: flutter pub get
- name: Build apk
env:

View File

@ -4,7 +4,4 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
</manifest>

View File

@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name="${applicationName}"

View File

@ -1,4 +1,14 @@
PODS:
- apivideo_live_stream (0.0.1):
- ApiVideoLiveStream (= 1.4.1)
- Flutter
- ApiVideoLiveStream (1.4.1):
- HaishinKit (= 1.7.3)
- audio_service (0.0.1):
- Flutter
- FlutterMacOS
- audio_session (0.0.1):
- Flutter
- emoji_picker_flutter (0.0.1):
- Flutter
- Firebase/CoreOnly (11.10.0):
@ -65,17 +75,22 @@ PODS:
- GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- HaishinKit (1.7.3):
- Logboard (~> 2.4.1)
- image_picker_ios (0.0.1):
- Flutter
- Logboard (2.4.2)
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
- ObjectBox (4.2.0)
- native_device_orientation (0.0.1):
- Flutter
- ObjectBox (4.3.0)
- objectbox_flutter_libs (0.0.1):
- Flutter
- ObjectBox (= 4.2.0)
- ObjectBox (= 4.3.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
@ -103,6 +118,9 @@ PODS:
- Flutter
DEPENDENCIES:
- apivideo_live_stream (from `.symlinks/plugins/apivideo_live_stream/ios`)
- audio_service (from `.symlinks/plugins/audio_service/darwin`)
- audio_session (from `.symlinks/plugins/audio_session/ios`)
- emoji_picker_flutter (from `.symlinks/plugins/emoji_picker_flutter/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
@ -110,6 +128,7 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`)
- objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
@ -124,6 +143,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- ApiVideoLiveStream
- Firebase
- FirebaseCore
- FirebaseCoreInternal
@ -131,11 +151,19 @@ SPEC REPOS:
- FirebaseMessaging
- GoogleDataTransport
- GoogleUtilities
- HaishinKit
- Logboard
- nanopb
- ObjectBox
- PromisesObjC
EXTERNAL SOURCES:
apivideo_live_stream:
:path: ".symlinks/plugins/apivideo_live_stream/ios"
audio_service:
:path: ".symlinks/plugins/audio_service/darwin"
audio_session:
:path: ".symlinks/plugins/audio_session/ios"
emoji_picker_flutter:
:path: ".symlinks/plugins/emoji_picker_flutter/ios"
firebase_core:
@ -150,6 +178,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
native_device_orientation:
:path: ".symlinks/plugins/native_device_orientation/ios"
objectbox_flutter_libs:
:path: ".symlinks/plugins/objectbox_flutter_libs/ios"
package_info_plus:
@ -174,6 +204,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
apivideo_live_stream: caab45dd35fb3b140d423c099d0f6672378e7abe
ApiVideoLiveStream: 8f9dce7f6d15d5e4bb3c7a25e406bf2a36337a5a
audio_service: aa99a6ba2ae7565996015322b0bb024e1d25c6fd
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
emoji_picker_flutter: ece213fc274bdddefb77d502d33080dc54e616cc
Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
firebase_core: ba71b44041571da878cb624ce0d80250bcbe58ad
@ -187,10 +221,13 @@ SPEC CHECKSUMS:
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
HaishinKit: 326e27c4d06427ba53bffc68e516a92033293051
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
Logboard: 759d82599c439945d430d5a0958455b5a1974a0c
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
ObjectBox: 2b4c925852ea99f070492f21328bf4002165cbd9
objectbox_flutter_libs: 50402e45f47f385d47fc041aba4607b89c4a3a1f
native_device_orientation: d6a4dc6887cd8a5ce1049962367aec60139ea0f1
ObjectBox: 7760fa9072adcffe102a6adf4646ca84ba70ab6b
objectbox_flutter_libs: 4014e38f57250b074b99893ae84579aba8f02876
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47

View File

@ -322,14 +322,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@ -380,14 +376,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";

View File

@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
@ -54,6 +55,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@ -91,5 +91,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSCameraUsageDescription</key>
<string>Live streaming</string>
<key>NSMicrophoneUsageDescription</key>
<string>Live streaming</string>
</dict>
</plist>

260
lib/api.dart Normal file
View File

@ -0,0 +1,260 @@
import 'dart:convert';
import 'dart:developer' as developer;
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;
import 'package:ndk/ndk.dart';
import 'package:zap_stream_flutter/const.dart';
class IngestEndpoint {
final String name;
final String url;
final String key;
final IngestCost cost;
final List<String> capabilities;
const IngestEndpoint({
required this.name,
required this.url,
required this.key,
required this.cost,
required this.capabilities,
});
static IngestEndpoint fromJson(Map<String, dynamic> json) {
return IngestEndpoint(
name: json["name"],
url: json["url"],
key: json["key"],
cost: IngestCost.fromJson(json["cost"]),
capabilities: List<String>.from(json["capabilities"]),
);
}
@override
int get hashCode => name.hashCode;
@override
bool operator ==(Object other) {
if (other is IngestEndpoint) {
return other.name == name;
}
return false;
}
}
class IngestCost {
final String unit;
final double rate;
const IngestCost({required this.unit, required this.rate});
static IngestCost fromJson(Map<String, dynamic> json) {
return IngestCost(unit: json["unit"], rate: json["rate"]);
}
}
class TosAccepted {
final bool accepted;
final String? link;
const TosAccepted({required this.accepted, required this.link});
static TosAccepted fromJson(Map<String, dynamic> json) {
return TosAccepted(accepted: json["accepted"], link: json["link"]);
}
}
class AccountInfo {
final double balance;
final List<IngestEndpoint> endpoints;
final TosAccepted tos;
final EventInfo? details;
const AccountInfo({
required this.balance,
required this.endpoints,
required this.tos,
this.details,
});
static AccountInfo fromJson(Map<String, dynamic> json) {
final balance = json["balance"] as int;
final endpoints = json["endpoints"] as Iterable<dynamic>;
return AccountInfo(
balance: balance.toDouble(),
endpoints: endpoints.map((e) => IngestEndpoint.fromJson(e)).toList(),
tos: TosAccepted.fromJson(json["tos"]),
details:
json.containsKey("details")
? EventInfo.fromJson(json["details"])
: null,
);
}
}
class EventInfo {
final String? id;
final String? title;
final String? summary;
final String? image;
final String? contentWarning;
final String? goal;
final List<String>? tags;
EventInfo({
required this.id,
required this.title,
required this.summary,
required this.image,
required this.contentWarning,
required this.goal,
required this.tags,
});
static EventInfo fromJson(Map<String, dynamic> json) {
return EventInfo(
id: json["id"],
title: json["title"],
summary: json["summary"],
image: json["image"],
contentWarning: json["content_warning"],
goal: json["goal"],
tags: json.containsKey("tags") ? List<String>.from(json["tags"]) : null,
);
}
}
class ZapStreamApi {
final String base;
final EventSigner signer;
ZapStreamApi(this.base, this.signer);
static ZapStreamApi instance() {
return ZapStreamApi(apiUrl, ndk.accounts.getLoggedAccount()!.signer);
}
Future<AccountInfo> getAccountInfo() async {
final url = "$base/account";
final rsp = await _sendGetRequest(url);
return AccountInfo.fromJson(JsonCodec().decode(rsp.body));
}
Future<void> updateDefaultStreamInfo({
String? title,
String? summary,
String? image,
String? contentWarning,
String? goal,
List<String>? tags,
}) async {
final url = "$base/event";
await _sendPatchRequest(
url,
body: {
"title": title,
"summary": summary,
"image": image,
"content_warning": contentWarning,
"goal": goal,
"tags": tags,
},
);
}
Future<void> acceptTos() async {
await _sendPatchRequest("$base/account", body: {"accept_tos": true});
}
Future<http.Response> _sendPatchRequest(String url, {Object? body}) async {
final jsonBody = body != null ? JsonCodec().encode(body) : null;
final auth = await _makeAuth("PATCH", url, body: jsonBody);
final rsp = await http
.patch(
Uri.parse(url),
body: jsonBody,
headers: {
"authorization": "Nostr $auth",
"accept": "application/json",
"content-type": "application/json",
},
)
.timeout(Duration(seconds: 10));
developer.log(rsp.body);
return rsp;
}
Future<http.Response> _sendPutRequest(String url, {Object? body}) async {
final jsonBody = body != null ? JsonCodec().encode(body) : null;
final auth = await _makeAuth("PUT", url, body: jsonBody);
final rsp = await http
.put(
Uri.parse(url),
body: jsonBody,
headers: {
"authorization": "Nostr $auth",
"accept": "application/json",
"content-type": "application/json",
},
)
.timeout(Duration(seconds: 10));
developer.log(rsp.body);
return rsp;
}
Future<http.Response> _sendGetRequest(String url, {Object? body}) async {
final jsonBody = body != null ? JsonCodec().encode(body) : null;
final auth = await _makeAuth("GET", url, body: jsonBody);
final rsp = await http
.get(
Uri.parse(url),
headers: {
"authorization": "Nostr $auth",
"accept": "application/json",
"content-type": "application/json",
},
)
.timeout(Duration(seconds: 10));
developer.log(rsp.body);
return rsp;
}
Future<http.Response> _sendDeleteRequest(String url, {Object? body}) async {
final jsonBody = body != null ? JsonCodec().encode(body) : null;
final auth = await _makeAuth("DELETE", url, body: jsonBody);
final rsp = await http
.delete(
Uri.parse(url),
headers: {
"authorization": "Nostr $auth",
"accept": "application/json",
"content-type": "application/json",
},
)
.timeout(Duration(seconds: 10));
developer.log(rsp.body);
return rsp;
}
Future<String> _makeAuth(String method, String url, {String? body}) async {
final pubkey = signer.getPublicKey();
var tags = [
["u", url],
["method", method],
];
if (body != null) {
final hash = hex.encode(sha256.convert(utf8.encode(body)).bytes);
tags.add(["payload", hash]);
}
final authEvent = Nip01Event(
pubKey: pubkey,
kind: 27235,
tags: tags,
content: "",
);
await signer.sign(authEvent);
return authEvent.toBase64();
}
}

View File

@ -6,6 +6,7 @@ import 'package:zap_stream_flutter/i18n/strings.g.dart';
import 'package:zap_stream_flutter/pages/category.dart';
import 'package:zap_stream_flutter/pages/hashtag.dart';
import 'package:zap_stream_flutter/pages/home.dart';
import 'package:zap_stream_flutter/pages/live.dart';
import 'package:zap_stream_flutter/pages/login.dart';
import 'package:zap_stream_flutter/pages/login_input.dart';
import 'package:zap_stream_flutter/pages/new_account.dart';
@ -135,6 +136,10 @@ void runZapStream() {
),
],
),
GoRoute(
path: "/live",
builder: (context, state) => LivePage(),
),
GoRoute(
path: "/:id",
redirect: (context, state) {

View File

@ -1,6 +1,7 @@
import 'package:amberflutter/amberflutter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.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_amber/ndk_amber.dart';
@ -36,6 +37,7 @@ const defaultRelays = [
];
const searchRelays = ["wss://relay.nostr.band", "wss://search.nos.today"];
const nwcRelays = ["wss://relay.getalby.com/v1"];
final apiUrl = dotenv.env["API_URL"] ?? "https://api.zap.stream/api/nostr";
final loginData = LoginData();
final RouteObserver<ModalRoute<void>> routeObserver =

View File

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 22
/// Strings: 1653 (75 per locale)
/// Strings: 2010 (91 per locale)
///
/// Built on 2025-05-29 at 11:29 UTC
/// Built on 2025-05-30 at 13:17 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View File

@ -51,6 +51,8 @@ class TranslationsAr extends Translations {
/// مستخدم مجهول
@override String get anon => 'هوية مخفية';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('ar').format(n)} دولار ساتس';
/// عدد مشاهدي البث
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
one: '1 مشاهد',
@ -69,6 +71,7 @@ class TranslationsAr extends Translations {
@override late final _TranslationsProfileAr profile = _TranslationsProfileAr._(_root);
@override late final _TranslationsSettingsAr settings = _TranslationsSettingsAr._(_root);
@override late final _TranslationsLoginAr login = _TranslationsLoginAr._(_root);
@override late final _TranslationsLiveAr live = _TranslationsLiveAr._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginAr extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorAr error = _TranslationsLoginErrorAr._(_root);
}
// Path: live
class _TranslationsLiveAr extends TranslationsLiveEn {
_TranslationsLiveAr._(TranslationsAr root) : this._root = root, super.internal(root);
final TranslationsAr _root; // ignore: unused_field
// Translations
@override String get start => 'ابدأ البث المباشر';
@override String get configure_stream => 'تكوين الدفق';
@override String get endpoint => 'نقطة النهاية';
@override String get accept_tos => 'قبول شروط الخدمة';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'العنوان';
@override String get summary => 'الملخص';
@override String get image => 'صورة الغلاف';
@override String get tags => 'الوسوم';
@override String get nsfw => 'محتوى غير لائق جنسيًا';
@override String get nsfw_description => 'تحقق هنا إذا كان هذا البث يحتوي على محتوى إباحي أو عري.';
@override late final _TranslationsLiveErrorAr error = _TranslationsLiveErrorAr._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusAr extends TranslationsStreamStatusEn {
_TranslationsStreamStatusAr._(TranslationsAr root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletAr extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'محفظة قطع الاتصال';
@override String get connect_1tap => '1-التوصيل بنقرة 1';
@override String get paste => 'لصق عنوان URL';
@override String get balance => 'الرصيد';
@override String get name => 'المحفظة';
@override late final _TranslationsSettingsWalletErrorAr error = _TranslationsSettingsWalletErrorAr._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorAr extends TranslationsLoginErrorEn {
@override String get invalid_key => 'مفتاح غير صالح';
}
// Path: live.error
class _TranslationsLiveErrorAr extends TranslationsLiveErrorEn {
_TranslationsLiveErrorAr._(TranslationsAr root) : this._root = root, super.internal(root);
final TranslationsAr _root; // ignore: unused_field
// Translations
@override String get failed => 'فشل البث';
@override String get connection_error => 'خطأ في الاتصال';
@override String get start_failed => 'فشل بدء البث فشل، يرجى التحقق من رصيدك';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteAr extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteAr._(TranslationsAr root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsAr {
case 'most_zapped_streamers': return 'معظم اللافتات التي يتم بثها';
case 'no_user_found': return 'لم يتم العثور على مستخدم';
case 'anon': return 'هوية مخفية';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('ar').format(n)} دولار ساتس';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
one: '1 مشاهد',
other: '{n:decimalPattern} المشاهدين',
@ -457,6 +499,8 @@ extension on TranslationsAr {
case 'settings.wallet.disconnect_wallet': return 'محفظة قطع الاتصال';
case 'settings.wallet.connect_1tap': return '1-التوصيل بنقرة 1';
case 'settings.wallet.paste': return 'لصق عنوان URL';
case 'settings.wallet.balance': return 'الرصيد';
case 'settings.wallet.name': return 'المحفظة';
case 'settings.wallet.error.logged_out': return 'لا يمكن الاتصال بالمحفظة عند تسجيل الخروج';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'لم يتم العثور على حدث مصادقة المحفظة';
case 'login.username': return 'اسم المستخدم';
@ -464,6 +508,23 @@ extension on TranslationsAr {
case 'login.key': return 'تسجيل الدخول بالمفتاح';
case 'login.create': return 'إنشاء حساب';
case 'login.error.invalid_key': return 'مفتاح غير صالح';
case 'live.start': return 'ابدأ البث المباشر';
case 'live.configure_stream': return 'تكوين الدفق';
case 'live.endpoint': return 'نقطة النهاية';
case 'live.accept_tos': return 'قبول شروط الخدمة';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ar'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'العنوان';
case 'live.summary': return 'الملخص';
case 'live.image': return 'صورة الغلاف';
case 'live.tags': return 'الوسوم';
case 'live.nsfw': return 'محتوى غير لائق جنسيًا';
case 'live.nsfw_description': return 'تحقق هنا إذا كان هذا البث يحتوي على محتوى إباحي أو عري.';
case 'live.error.failed': return 'فشل البث';
case 'live.error.connection_error': return 'خطأ في الاتصال';
case 'live.error.start_failed': return 'فشل بدء البث فشل، يرجى التحقق من رصيدك';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsCs extends Translations {
/// Anonymní uživatel
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('cs').format(n)} sats';
/// Počet diváků streamu
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('cs'))(n,
one: '1 divák',
@ -69,6 +71,7 @@ class TranslationsCs extends Translations {
@override late final _TranslationsProfileCs profile = _TranslationsProfileCs._(_root);
@override late final _TranslationsSettingsCs settings = _TranslationsSettingsCs._(_root);
@override late final _TranslationsLoginCs login = _TranslationsLoginCs._(_root);
@override late final _TranslationsLiveCs live = _TranslationsLiveCs._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginCs extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorCs error = _TranslationsLoginErrorCs._(_root);
}
// Path: live
class _TranslationsLiveCs extends TranslationsLiveEn {
_TranslationsLiveCs._(TranslationsCs root) : this._root = root, super.internal(root);
final TranslationsCs _root; // ignore: unused_field
// Translations
@override String get start => 'PŘEJÍT NA ŽIVOT';
@override String get configure_stream => 'Konfigurace streamu';
@override String get endpoint => 'Koncový bod';
@override String get accept_tos => 'Přijmout TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('cs'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Název';
@override String get summary => 'Souhrn';
@override String get image => 'Obrázek na obálce';
@override String get tags => 'Štítky';
@override String get nsfw => 'Obsah NSFW';
@override String get nsfw_description => 'Zde zkontrolujte, zda tento stream obsahuje nahotu nebo pornografický obsah.';
@override late final _TranslationsLiveErrorCs error = _TranslationsLiveErrorCs._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusCs extends TranslationsStreamStatusEn {
_TranslationsStreamStatusCs._(TranslationsCs root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletCs extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Odpojení peněženky';
@override String get connect_1tap => 'Připojení 1 kohoutku';
@override String get paste => 'Vložit adresu URL';
@override String get balance => 'Bilance';
@override String get name => 'Peněženka';
@override late final _TranslationsSettingsWalletErrorCs error = _TranslationsSettingsWalletErrorCs._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorCs extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Neplatný klíč';
}
// Path: live.error
class _TranslationsLiveErrorCs extends TranslationsLiveErrorEn {
_TranslationsLiveErrorCs._(TranslationsCs root) : this._root = root, super.internal(root);
final TranslationsCs _root; // ignore: unused_field
// Translations
@override String get failed => 'Stream se nezdařil';
@override String get connection_error => 'Chyba připojení';
@override String get start_failed => 'Spuštění streamu se nezdařilo, zkontrolujte prosím zůstatek';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteCs extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteCs._(TranslationsCs root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsCs {
case 'most_zapped_streamers': return 'Nejvíce zapnutých streamerů';
case 'no_user_found': return 'Nebyl nalezen žádný uživatel';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('cs').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('cs'))(n,
one: '1 divák',
other: '${NumberFormat.decimalPattern('cs').format(n)} diváků',
@ -457,6 +499,8 @@ extension on TranslationsCs {
case 'settings.wallet.disconnect_wallet': return 'Odpojení peněženky';
case 'settings.wallet.connect_1tap': return 'Připojení 1 kohoutku';
case 'settings.wallet.paste': return 'Vložit adresu URL';
case 'settings.wallet.balance': return 'Bilance';
case 'settings.wallet.name': return 'Peněženka';
case 'settings.wallet.error.logged_out': return 'Nelze se připojit k peněžence, když jste odhlášeni';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Nebyla nalezena žádná událost autentizace peněženky';
case 'login.username': return 'Uživatelské jméno';
@ -464,6 +508,23 @@ extension on TranslationsCs {
case 'login.key': return 'Přihlášení pomocí klíče';
case 'login.create': return 'Vytvořit účet';
case 'login.error.invalid_key': return 'Neplatný klíč';
case 'live.start': return 'PŘEJÍT NA ŽIVOT';
case 'live.configure_stream': return 'Konfigurace streamu';
case 'live.endpoint': return 'Koncový bod';
case 'live.accept_tos': return 'Přijmout TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('cs'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Název';
case 'live.summary': return 'Souhrn';
case 'live.image': return 'Obrázek na obálce';
case 'live.tags': return 'Štítky';
case 'live.nsfw': return 'Obsah NSFW';
case 'live.nsfw_description': return 'Zde zkontrolujte, zda tento stream obsahuje nahotu nebo pornografický obsah.';
case 'live.error.failed': return 'Stream se nezdařil';
case 'live.error.connection_error': return 'Chyba připojení';
case 'live.error.start_failed': return 'Spuštění streamu se nezdařilo, zkontrolujte prosím zůstatek';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsDa extends Translations {
/// En anonym bruger
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('da').format(n)} sats';
/// Antal seere af streamingen
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('da'))(n,
one: '1 seer',
@ -69,6 +71,7 @@ class TranslationsDa extends Translations {
@override late final _TranslationsProfileDa profile = _TranslationsProfileDa._(_root);
@override late final _TranslationsSettingsDa settings = _TranslationsSettingsDa._(_root);
@override late final _TranslationsLoginDa login = _TranslationsLoginDa._(_root);
@override late final _TranslationsLiveDa live = _TranslationsLiveDa._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginDa extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorDa error = _TranslationsLoginErrorDa._(_root);
}
// Path: live
class _TranslationsLiveDa extends TranslationsLiveEn {
_TranslationsLiveDa._(TranslationsDa root) : this._root = root, super.internal(root);
final TranslationsDa _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Konfigurer stream';
@override String get endpoint => 'Slutpunkt';
@override String get accept_tos => 'Accepter TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('da'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titel';
@override String get summary => 'Sammenfatning';
@override String get image => 'Forsidebillede';
@override String get tags => 'Tags';
@override String get nsfw => 'NSFW-indhold';
@override String get nsfw_description => 'Tjek her, om denne stream indeholder nøgenhed eller pornografisk indhold.';
@override late final _TranslationsLiveErrorDa error = _TranslationsLiveErrorDa._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusDa extends TranslationsStreamStatusEn {
_TranslationsStreamStatusDa._(TranslationsDa root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletDa extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Afbryd forbindelsen til tegnebogen';
@override String get connect_1tap => '1-Tap-forbindelse';
@override String get paste => 'Indsæt URL';
@override String get balance => 'Balance';
@override String get name => 'Tegnebog';
@override late final _TranslationsSettingsWalletErrorDa error = _TranslationsSettingsWalletErrorDa._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorDa extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Ugyldig nøgle';
}
// Path: live.error
class _TranslationsLiveErrorDa extends TranslationsLiveErrorEn {
_TranslationsLiveErrorDa._(TranslationsDa root) : this._root = root, super.internal(root);
final TranslationsDa _root; // ignore: unused_field
// Translations
@override String get failed => 'Strømmen mislykkedes';
@override String get connection_error => 'Forbindelsesfejl';
@override String get start_failed => 'Stream-start mislykkedes, tjek venligst din saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteDa extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteDa._(TranslationsDa root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsDa {
case 'most_zapped_streamers': return 'De fleste zappede streamere';
case 'no_user_found': return 'Ingen bruger fundet';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('da').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('da'))(n,
one: '1 seer',
other: '${NumberFormat.decimalPattern('da').format(n)} seere',
@ -457,6 +499,8 @@ extension on TranslationsDa {
case 'settings.wallet.disconnect_wallet': return 'Afbryd forbindelsen til tegnebogen';
case 'settings.wallet.connect_1tap': return '1-Tap-forbindelse';
case 'settings.wallet.paste': return 'Indsæt URL';
case 'settings.wallet.balance': return 'Balance';
case 'settings.wallet.name': return 'Tegnebog';
case 'settings.wallet.error.logged_out': return 'Kan ikke oprette forbindelse til wallet, når jeg er logget ud';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Ingen wallet-auth-begivenhed fundet';
case 'login.username': return 'Brugernavn';
@ -464,6 +508,23 @@ extension on TranslationsDa {
case 'login.key': return 'Login med nøgle';
case 'login.create': return 'Opret konto';
case 'login.error.invalid_key': return 'Ugyldig nøgle';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Konfigurer stream';
case 'live.endpoint': return 'Slutpunkt';
case 'live.accept_tos': return 'Accepter TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('da'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titel';
case 'live.summary': return 'Sammenfatning';
case 'live.image': return 'Forsidebillede';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'NSFW-indhold';
case 'live.nsfw_description': return 'Tjek her, om denne stream indeholder nøgenhed eller pornografisk indhold.';
case 'live.error.failed': return 'Strømmen mislykkedes';
case 'live.error.connection_error': return 'Forbindelsesfejl';
case 'live.error.start_failed': return 'Stream-start mislykkedes, tjek venligst din saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsDe extends Translations {
/// Ein anonymer Benutzer
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('de').format(n)} sats';
/// Anzahl der Zuschauer des Streams
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('de'))(n,
one: '1 Zuschauer',
@ -69,6 +71,7 @@ class TranslationsDe extends Translations {
@override late final _TranslationsProfileDe profile = _TranslationsProfileDe._(_root);
@override late final _TranslationsSettingsDe settings = _TranslationsSettingsDe._(_root);
@override late final _TranslationsLoginDe login = _TranslationsLoginDe._(_root);
@override late final _TranslationsLiveDe live = _TranslationsLiveDe._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginDe extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorDe error = _TranslationsLoginErrorDe._(_root);
}
// Path: live
class _TranslationsLiveDe extends TranslationsLiveEn {
_TranslationsLiveDe._(TranslationsDe root) : this._root = root, super.internal(root);
final TranslationsDe _root; // ignore: unused_field
// Translations
@override String get start => 'LIVE GEHEN';
@override String get configure_stream => 'Stream konfigurieren';
@override String get endpoint => 'Endpunkt';
@override String get accept_tos => 'TOS akzeptieren';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('de'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titel';
@override String get summary => 'Zusammenfassung';
@override String get image => 'Titelbild';
@override String get tags => 'Tags';
@override String get nsfw => 'NSFW-Inhalt';
@override String get nsfw_description => 'Prüfen Sie hier, ob dieser Stream Nacktheit oder pornografische Inhalte enthält.';
@override late final _TranslationsLiveErrorDe error = _TranslationsLiveErrorDe._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusDe extends TranslationsStreamStatusEn {
_TranslationsStreamStatusDe._(TranslationsDe root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletDe extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Brieftasche abtrennen';
@override String get connect_1tap => '1-Tap-Verbindung';
@override String get paste => 'URL einfügen';
@override String get balance => 'Bilanz';
@override String get name => 'Brieftasche';
@override late final _TranslationsSettingsWalletErrorDe error = _TranslationsSettingsWalletErrorDe._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorDe extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Ungültiger Schlüssel';
}
// Path: live.error
class _TranslationsLiveErrorDe extends TranslationsLiveErrorEn {
_TranslationsLiveErrorDe._(TranslationsDe root) : this._root = root, super.internal(root);
final TranslationsDe _root; // ignore: unused_field
// Translations
@override String get failed => 'Stream fehlgeschlagen';
@override String get connection_error => 'Verbindungsfehler';
@override String get start_failed => 'Streamstart fehlgeschlagen, bitte überprüfen Sie Ihr Guthaben';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteDe extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteDe._(TranslationsDe root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsDe {
case 'most_zapped_streamers': return 'Meistgezappte Streamer';
case 'no_user_found': return 'Kein Benutzer gefunden';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('de').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('de'))(n,
one: '1 Zuschauer',
other: '${NumberFormat.decimalPattern('de').format(n)} Zuschauer',
@ -457,6 +499,8 @@ extension on TranslationsDe {
case 'settings.wallet.disconnect_wallet': return 'Brieftasche abtrennen';
case 'settings.wallet.connect_1tap': return '1-Tap-Verbindung';
case 'settings.wallet.paste': return 'URL einfügen';
case 'settings.wallet.balance': return 'Bilanz';
case 'settings.wallet.name': return 'Brieftasche';
case 'settings.wallet.error.logged_out': return 'Kann keine Verbindung zur Brieftasche herstellen, wenn ich abgemeldet bin';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Kein Wallet-Authentifizierungsereignis gefunden';
case 'login.username': return 'Benutzername';
@ -464,6 +508,23 @@ extension on TranslationsDe {
case 'login.key': return 'Anmeldung mit Schlüssel';
case 'login.create': return 'Konto erstellen';
case 'login.error.invalid_key': return 'Ungültiger Schlüssel';
case 'live.start': return 'LIVE GEHEN';
case 'live.configure_stream': return 'Stream konfigurieren';
case 'live.endpoint': return 'Endpunkt';
case 'live.accept_tos': return 'TOS akzeptieren';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('de'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titel';
case 'live.summary': return 'Zusammenfassung';
case 'live.image': return 'Titelbild';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'NSFW-Inhalt';
case 'live.nsfw_description': return 'Prüfen Sie hier, ob dieser Stream Nacktheit oder pornografische Inhalte enthält.';
case 'live.error.failed': return 'Stream fehlgeschlagen';
case 'live.error.connection_error': return 'Verbindungsfehler';
case 'live.error.start_failed': return 'Streamstart fehlgeschlagen, bitte überprüfen Sie Ihr Guthaben';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsEl extends Translations {
/// Ένας ανώνυμος χρήστης
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('el').format(n)} sats';
/// Αριθμός θεατών της ροής
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('el'))(n,
one: '1 θεατής',
@ -69,6 +71,7 @@ class TranslationsEl extends Translations {
@override late final _TranslationsProfileEl profile = _TranslationsProfileEl._(_root);
@override late final _TranslationsSettingsEl settings = _TranslationsSettingsEl._(_root);
@override late final _TranslationsLoginEl login = _TranslationsLoginEl._(_root);
@override late final _TranslationsLiveEl live = _TranslationsLiveEl._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginEl extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorEl error = _TranslationsLoginErrorEl._(_root);
}
// Path: live
class _TranslationsLiveEl extends TranslationsLiveEn {
_TranslationsLiveEl._(TranslationsEl root) : this._root = root, super.internal(root);
final TranslationsEl _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Διαμόρφωση ροής';
@override String get endpoint => 'Τελικό σημείο';
@override String get accept_tos => 'Αποδοχή TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('el'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Τίτλος';
@override String get summary => 'Περίληψη';
@override String get image => 'Εικόνα εξωφύλλου';
@override String get tags => 'Ετικέτες';
@override String get nsfw => 'Περιεχόμενο NSFW';
@override String get nsfw_description => 'Ελέγξτε εδώ αν αυτή η ροή περιέχει γυμνό ή πορνογραφικό περιεχόμενο.';
@override late final _TranslationsLiveErrorEl error = _TranslationsLiveErrorEl._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusEl extends TranslationsStreamStatusEn {
_TranslationsStreamStatusEl._(TranslationsEl root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletEl extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Αποσύνδεση πορτοφολιού';
@override String get connect_1tap => 'Σύνδεση 1 βρύσης';
@override String get paste => 'Επικόλληση URL';
@override String get balance => 'Υπόλοιπο';
@override String get name => 'Πορτοφόλι';
@override late final _TranslationsSettingsWalletErrorEl error = _TranslationsSettingsWalletErrorEl._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorEl extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Μη έγκυρο κλειδί';
}
// Path: live.error
class _TranslationsLiveErrorEl extends TranslationsLiveErrorEn {
_TranslationsLiveErrorEl._(TranslationsEl root) : this._root = root, super.internal(root);
final TranslationsEl _root; // ignore: unused_field
// Translations
@override String get failed => 'Το ρεύμα απέτυχε';
@override String get connection_error => 'Σφάλμα σύνδεσης';
@override String get start_failed => 'Η εκκίνηση της ροής απέτυχε, παρακαλούμε ελέγξτε το υπόλοιπό σας';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteEl extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteEl._(TranslationsEl root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsEl {
case 'most_zapped_streamers': return 'Τα περισσότερα Zapped Streamers';
case 'no_user_found': return 'Δεν βρέθηκε χρήστης';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('el').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('el'))(n,
one: '1 θεατής',
other: '${NumberFormat.decimalPattern('el').format(n)} θεατές',
@ -457,6 +499,8 @@ extension on TranslationsEl {
case 'settings.wallet.disconnect_wallet': return 'Αποσύνδεση πορτοφολιού';
case 'settings.wallet.connect_1tap': return 'Σύνδεση 1 βρύσης';
case 'settings.wallet.paste': return 'Επικόλληση URL';
case 'settings.wallet.balance': return 'Υπόλοιπο';
case 'settings.wallet.name': return 'Πορτοφόλι';
case 'settings.wallet.error.logged_out': return 'Δεν μπορώ να συνδεθώ με πορτοφόλι όταν έχω αποσυνδεθεί';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Δεν βρέθηκε συμβάν εξουσιοδότησης πορτοφολιού';
case 'login.username': return 'Όνομα χρήστη';
@ -464,6 +508,23 @@ extension on TranslationsEl {
case 'login.key': return 'Σύνδεση με κλειδί';
case 'login.create': return 'Δημιουργία λογαριασμού';
case 'login.error.invalid_key': return 'Μη έγκυρο κλειδί';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Διαμόρφωση ροής';
case 'live.endpoint': return 'Τελικό σημείο';
case 'live.accept_tos': return 'Αποδοχή TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('el'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Τίτλος';
case 'live.summary': return 'Περίληψη';
case 'live.image': return 'Εικόνα εξωφύλλου';
case 'live.tags': return 'Ετικέτες';
case 'live.nsfw': return 'Περιεχόμενο NSFW';
case 'live.nsfw_description': return 'Ελέγξτε εδώ αν αυτή η ροή περιέχει γυμνό ή πορνογραφικό περιεχόμενο.';
case 'live.error.failed': return 'Το ρεύμα απέτυχε';
case 'live.error.connection_error': return 'Σφάλμα σύνδεσης';
case 'live.error.start_failed': return 'Η εκκίνηση της ροής απέτυχε, παρακαλούμε ελέγξτε το υπόλοιπό σας';
default: return null;
}
}

View File

@ -72,6 +72,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
late final TranslationsProfileEn profile = TranslationsProfileEn.internal(_root);
late final TranslationsSettingsEn settings = TranslationsSettingsEn.internal(_root);
late final TranslationsLoginEn login = TranslationsLoginEn.internal(_root);
late final TranslationsLiveEn live = TranslationsLiveEn.internal(_root);
}
// Path: stream
@ -208,6 +209,30 @@ class TranslationsLoginEn {
late final TranslationsLoginErrorEn error = TranslationsLoginErrorEn.internal(_root);
}
// Path: live
class TranslationsLiveEn {
TranslationsLiveEn.internal(this._root);
final Translations _root; // ignore: unused_field
// Translations
String get start => 'GO LIVE';
String get configure_stream => 'Configure Stream';
String get endpoint => 'Endpoint';
String get accept_tos => 'Accept TOS';
String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n,
zero: '',
other: '~${time}',
);
String get title => 'Title';
String get summary => 'Summary';
String get image => 'Cover Image';
String get tags => 'Tags';
String get nsfw => 'NSFW Content';
String get nsfw_description => 'Check here if this stream contains nudity or pornographic content.';
late final TranslationsLiveErrorEn error = TranslationsLiveErrorEn.internal(_root);
}
// Path: stream.status
class TranslationsStreamStatusEn {
TranslationsStreamStatusEn.internal(this._root);
@ -307,6 +332,18 @@ class TranslationsLoginErrorEn {
String get invalid_key => 'Invalid key';
}
// Path: live.error
class TranslationsLiveErrorEn {
TranslationsLiveErrorEn.internal(this._root);
final Translations _root; // ignore: unused_field
// Translations
String get failed => 'Stream failed';
String get connection_error => 'Connection Error';
String get start_failed => 'Stream start failed, please check your balance';
}
// Path: stream.chat.write
class TranslationsStreamChatWriteEn {
TranslationsStreamChatWriteEn.internal(this._root);
@ -472,6 +509,23 @@ extension on Translations {
case 'login.key': return 'Login with Key';
case 'login.create': return 'Create Account';
case 'login.error.invalid_key': return 'Invalid key';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Configure Stream';
case 'live.endpoint': return 'Endpoint';
case 'live.accept_tos': return 'Accept TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Title';
case 'live.summary': return 'Summary';
case 'live.image': return 'Cover Image';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'NSFW Content';
case 'live.nsfw_description': return 'Check here if this stream contains nudity or pornographic content.';
case 'live.error.failed': return 'Stream failed';
case 'live.error.connection_error': return 'Connection Error';
case 'live.error.start_failed': return 'Stream start failed, please check your balance';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsEs extends Translations {
/// Un usuario anónimo
@override String get anon => 'Anónimo';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('es').format(n)} sats';
/// Número de espectadores del flujo
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('es'))(n,
one: '1 espectador',
@ -69,6 +71,7 @@ class TranslationsEs extends Translations {
@override late final _TranslationsProfileEs profile = _TranslationsProfileEs._(_root);
@override late final _TranslationsSettingsEs settings = _TranslationsSettingsEs._(_root);
@override late final _TranslationsLoginEs login = _TranslationsLoginEs._(_root);
@override late final _TranslationsLiveEs live = _TranslationsLiveEs._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginEs extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorEs error = _TranslationsLoginErrorEs._(_root);
}
// Path: live
class _TranslationsLiveEs extends TranslationsLiveEn {
_TranslationsLiveEs._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get start => 'EN VIVO';
@override String get configure_stream => 'Configurar Stream';
@override String get endpoint => 'Punto final';
@override String get accept_tos => 'Aceptar TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('es'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Título';
@override String get summary => 'Resumen';
@override String get image => 'Imagen de portada';
@override String get tags => 'Etiquetas';
@override String get nsfw => 'Contenido NSFW';
@override String get nsfw_description => 'Compruebe aquí si este flujo contiene desnudos o contenido pornográfico.';
@override late final _TranslationsLiveErrorEs error = _TranslationsLiveErrorEs._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusEs extends TranslationsStreamStatusEn {
_TranslationsStreamStatusEs._(TranslationsEs root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletEs extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Desconectar Cartera';
@override String get connect_1tap => 'Conexión de 1 toma';
@override String get paste => 'Pegar URL';
@override String get balance => 'Saldo';
@override String get name => 'Cartera';
@override late final _TranslationsSettingsWalletErrorEs error = _TranslationsSettingsWalletErrorEs._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorEs extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Clave no válida';
}
// Path: live.error
class _TranslationsLiveErrorEs extends TranslationsLiveErrorEn {
_TranslationsLiveErrorEs._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get failed => 'Corriente fallida';
@override String get connection_error => 'Error de conexión';
@override String get start_failed => 'Error en el inicio de la transmisión, compruebe su saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteEs extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteEs._(TranslationsEs root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsEs {
case 'most_zapped_streamers': return 'Serpentinas más derribadas';
case 'no_user_found': return 'No se ha encontrado ningún usuario';
case 'anon': return 'Anónimo';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('es').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('es'))(n,
one: '1 espectador',
other: '${NumberFormat.decimalPattern('es').format(n)} espectadores',
@ -457,6 +499,8 @@ extension on TranslationsEs {
case 'settings.wallet.disconnect_wallet': return 'Desconectar Cartera';
case 'settings.wallet.connect_1tap': return 'Conexión de 1 toma';
case 'settings.wallet.paste': return 'Pegar URL';
case 'settings.wallet.balance': return 'Saldo';
case 'settings.wallet.name': return 'Cartera';
case 'settings.wallet.error.logged_out': return 'No se puede conectar el monedero al cerrar la sesión';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'No se ha encontrado ningún evento de autenticación de cartera';
case 'login.username': return 'Usuario';
@ -464,6 +508,23 @@ extension on TranslationsEs {
case 'login.key': return 'Inicio de sesión con clave';
case 'login.create': return 'Crear una cuenta';
case 'login.error.invalid_key': return 'Clave no válida';
case 'live.start': return 'EN VIVO';
case 'live.configure_stream': return 'Configurar Stream';
case 'live.endpoint': return 'Punto final';
case 'live.accept_tos': return 'Aceptar TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('es'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Título';
case 'live.summary': return 'Resumen';
case 'live.image': return 'Imagen de portada';
case 'live.tags': return 'Etiquetas';
case 'live.nsfw': return 'Contenido NSFW';
case 'live.nsfw_description': return 'Compruebe aquí si este flujo contiene desnudos o contenido pornográfico.';
case 'live.error.failed': return 'Corriente fallida';
case 'live.error.connection_error': return 'Error de conexión';
case 'live.error.start_failed': return 'Error en el inicio de la transmisión, compruebe su saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsFi extends Translations {
/// Nimetön käyttäjä
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('fi').format(n)} sats';
/// Streamin katsojien määrä
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fi'))(n,
one: '1 katsoja',
@ -69,6 +71,7 @@ class TranslationsFi extends Translations {
@override late final _TranslationsProfileFi profile = _TranslationsProfileFi._(_root);
@override late final _TranslationsSettingsFi settings = _TranslationsSettingsFi._(_root);
@override late final _TranslationsLoginFi login = _TranslationsLoginFi._(_root);
@override late final _TranslationsLiveFi live = _TranslationsLiveFi._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginFi extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorFi error = _TranslationsLoginErrorFi._(_root);
}
// Path: live
class _TranslationsLiveFi extends TranslationsLiveEn {
_TranslationsLiveFi._(TranslationsFi root) : this._root = root, super.internal(root);
final TranslationsFi _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Määritä Stream';
@override String get endpoint => 'Loppupiste';
@override String get accept_tos => 'Hyväksy TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fi'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Otsikko';
@override String get summary => 'Yhteenveto';
@override String get image => 'Kansikuva';
@override String get tags => 'Tunnisteet';
@override String get nsfw => 'NSFW-sisältö';
@override String get nsfw_description => 'Tarkista täältä, jos tämä stream sisältää alastomuutta tai pornografista sisältöä.';
@override late final _TranslationsLiveErrorFi error = _TranslationsLiveErrorFi._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusFi extends TranslationsStreamStatusEn {
_TranslationsStreamStatusFi._(TranslationsFi root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletFi extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Irrota lompakko';
@override String get connect_1tap => '1-Tap-liitäntä';
@override String get paste => 'Liitä URL-osoite';
@override String get balance => 'Balance';
@override String get name => 'Lompakko';
@override late final _TranslationsSettingsWalletErrorFi error = _TranslationsSettingsWalletErrorFi._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorFi extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Virheellinen avain';
}
// Path: live.error
class _TranslationsLiveErrorFi extends TranslationsLiveErrorEn {
_TranslationsLiveErrorFi._(TranslationsFi root) : this._root = root, super.internal(root);
final TranslationsFi _root; // ignore: unused_field
// Translations
@override String get failed => 'Stream epäonnistui';
@override String get connection_error => 'Yhteysvirhe';
@override String get start_failed => 'Virran käynnistys epäonnistui, tarkista saldosi';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteFi extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteFi._(TranslationsFi root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsFi {
case 'most_zapped_streamers': return 'Eniten Zapped Streamers';
case 'no_user_found': return 'Käyttäjää ei löytynyt';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('fi').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fi'))(n,
one: '1 katsoja',
other: '${NumberFormat.decimalPattern('fi').format(n)} katsojat',
@ -457,6 +499,8 @@ extension on TranslationsFi {
case 'settings.wallet.disconnect_wallet': return 'Irrota lompakko';
case 'settings.wallet.connect_1tap': return '1-Tap-liitäntä';
case 'settings.wallet.paste': return 'Liitä URL-osoite';
case 'settings.wallet.balance': return 'Balance';
case 'settings.wallet.name': return 'Lompakko';
case 'settings.wallet.error.logged_out': return 'Ei voi muodostaa yhteyttä lompakkoon, kun on kirjautunut ulos';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Ei lompakko-auth-tapahtumaa löydetty';
case 'login.username': return 'Käyttäjätunnus';
@ -464,6 +508,23 @@ extension on TranslationsFi {
case 'login.key': return 'Kirjaudu sisään avaimella';
case 'login.create': return 'Luo tili';
case 'login.error.invalid_key': return 'Virheellinen avain';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Määritä Stream';
case 'live.endpoint': return 'Loppupiste';
case 'live.accept_tos': return 'Hyväksy TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fi'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Otsikko';
case 'live.summary': return 'Yhteenveto';
case 'live.image': return 'Kansikuva';
case 'live.tags': return 'Tunnisteet';
case 'live.nsfw': return 'NSFW-sisältö';
case 'live.nsfw_description': return 'Tarkista täältä, jos tämä stream sisältää alastomuutta tai pornografista sisältöä.';
case 'live.error.failed': return 'Stream epäonnistui';
case 'live.error.connection_error': return 'Yhteysvirhe';
case 'live.error.start_failed': return 'Virran käynnistys epäonnistui, tarkista saldosi';
default: return null;
}
}

View File

@ -51,10 +51,12 @@ class TranslationsFr extends Translations {
/// Un utilisateur anonyme
@override String get anon => 'Anonyme';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('fr').format(n)} sats';
/// Nombre de spectateurs du flux
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
one: '1 téléspectateur',
other: '{n:decimalPattern} téléspectateurs',
other: '${NumberFormat.decimalPattern('fr').format(n)} téléspectateurs',
);
@override late final _TranslationsStreamFr stream = _TranslationsStreamFr._(_root);
@ -69,6 +71,7 @@ class TranslationsFr extends Translations {
@override late final _TranslationsProfileFr profile = _TranslationsProfileFr._(_root);
@override late final _TranslationsSettingsFr settings = _TranslationsSettingsFr._(_root);
@override late final _TranslationsLoginFr login = _TranslationsLoginFr._(_root);
@override late final _TranslationsLiveFr live = _TranslationsLiveFr._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginFr extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorFr error = _TranslationsLoginErrorFr._(_root);
}
// Path: live
class _TranslationsLiveFr extends TranslationsLiveEn {
_TranslationsLiveFr._(TranslationsFr root) : this._root = root, super.internal(root);
final TranslationsFr _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Configurer le flux';
@override String get endpoint => 'Point final';
@override String get accept_tos => 'Accepter les CGU';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titre';
@override String get summary => 'Résumé';
@override String get image => 'Image de couverture';
@override String get tags => 'Tags';
@override String get nsfw => 'Contenu NSFW';
@override String get nsfw_description => 'Cochez cette case si ce flux contient de la nudité ou du contenu pornographique.';
@override late final _TranslationsLiveErrorFr error = _TranslationsLiveErrorFr._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusFr extends TranslationsStreamStatusEn {
_TranslationsStreamStatusFr._(TranslationsFr root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletFr extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Déconnecter le portefeuille';
@override String get connect_1tap => 'Connexion à 1 robinet';
@override String get paste => 'Coller l\'URL';
@override String get balance => 'Équilibre';
@override String get name => 'Portefeuille';
@override late final _TranslationsSettingsWalletErrorFr error = _TranslationsSettingsWalletErrorFr._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorFr extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Clé non valide';
}
// Path: live.error
class _TranslationsLiveErrorFr extends TranslationsLiveErrorEn {
_TranslationsLiveErrorFr._(TranslationsFr root) : this._root = root, super.internal(root);
final TranslationsFr _root; // ignore: unused_field
// Translations
@override String get failed => 'Échec du flux';
@override String get connection_error => 'Erreur de connexion';
@override String get start_failed => 'Le démarrage du flux a échoué, veuillez vérifier votre solde';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteFr extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteFr._(TranslationsFr root) : this._root = root, super.internal(root);
@ -380,9 +421,10 @@ extension on TranslationsFr {
case 'most_zapped_streamers': return 'Les Streamers les plus zappés';
case 'no_user_found': return 'Aucun utilisateur trouvé';
case 'anon': return 'Anonyme';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('fr').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
one: '1 téléspectateur',
other: '{n:decimalPattern} téléspectateurs',
other: '${NumberFormat.decimalPattern('fr').format(n)} téléspectateurs',
);
case 'stream.status.live': return 'VIVRE';
case 'stream.status.ended': return 'FINI';
@ -457,6 +499,8 @@ extension on TranslationsFr {
case 'settings.wallet.disconnect_wallet': return 'Déconnecter le portefeuille';
case 'settings.wallet.connect_1tap': return 'Connexion à 1 robinet';
case 'settings.wallet.paste': return 'Coller l\'URL';
case 'settings.wallet.balance': return 'Équilibre';
case 'settings.wallet.name': return 'Portefeuille';
case 'settings.wallet.error.logged_out': return 'Impossible de se connecter au portefeuille lorsque l\'on est déconnecté';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Aucun événement d\'authentification de portefeuille n\'a été trouvé';
case 'login.username': return 'Nom dutilisateur';
@ -464,6 +508,23 @@ extension on TranslationsFr {
case 'login.key': return 'Connexion avec la clé';
case 'login.create': return 'Créer un Compte';
case 'login.error.invalid_key': return 'Clé non valide';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Configurer le flux';
case 'live.endpoint': return 'Point final';
case 'live.accept_tos': return 'Accepter les CGU';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('fr'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titre';
case 'live.summary': return 'Résumé';
case 'live.image': return 'Image de couverture';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'Contenu NSFW';
case 'live.nsfw_description': return 'Cochez cette case si ce flux contient de la nudité ou du contenu pornographique.';
case 'live.error.failed': return 'Échec du flux';
case 'live.error.connection_error': return 'Erreur de connexion';
case 'live.error.start_failed': return 'Le démarrage du flux a échoué, veuillez vérifier votre solde';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsIt extends Translations {
/// Un utente anonimo
@override String get anon => 'Anonimo';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('it').format(n)} sats';
/// Numero di spettatori del flusso
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('it'))(n,
one: '1 spettatore',
@ -69,6 +71,7 @@ class TranslationsIt extends Translations {
@override late final _TranslationsProfileIt profile = _TranslationsProfileIt._(_root);
@override late final _TranslationsSettingsIt settings = _TranslationsSettingsIt._(_root);
@override late final _TranslationsLoginIt login = _TranslationsLoginIt._(_root);
@override late final _TranslationsLiveIt live = _TranslationsLiveIt._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginIt extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorIt error = _TranslationsLoginErrorIt._(_root);
}
// Path: live
class _TranslationsLiveIt extends TranslationsLiveEn {
_TranslationsLiveIt._(TranslationsIt root) : this._root = root, super.internal(root);
final TranslationsIt _root; // ignore: unused_field
// Translations
@override String get start => 'VAI IN DIRETTA';
@override String get configure_stream => 'Configurare il flusso';
@override String get endpoint => 'Punto finale';
@override String get accept_tos => 'Accettare i TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('it'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titolo';
@override String get summary => 'Sintesi';
@override String get image => 'Immagine di copertina';
@override String get tags => 'Tag';
@override String get nsfw => 'Contenuto NSFW';
@override String get nsfw_description => 'Controllare qui se questo streaming contiene nudità o contenuti pornografici.';
@override late final _TranslationsLiveErrorIt error = _TranslationsLiveErrorIt._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusIt extends TranslationsStreamStatusEn {
_TranslationsStreamStatusIt._(TranslationsIt root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletIt extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Disconnettere il portafoglio';
@override String get connect_1tap => 'Connessione a 1 rubinetto';
@override String get paste => 'Incolla URL';
@override String get balance => 'Equilibrio';
@override String get name => 'Portafoglio';
@override late final _TranslationsSettingsWalletErrorIt error = _TranslationsSettingsWalletErrorIt._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorIt extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Chiave non valida';
}
// Path: live.error
class _TranslationsLiveErrorIt extends TranslationsLiveErrorEn {
_TranslationsLiveErrorIt._(TranslationsIt root) : this._root = root, super.internal(root);
final TranslationsIt _root; // ignore: unused_field
// Translations
@override String get failed => 'Flusso fallito';
@override String get connection_error => 'Errore di connessione';
@override String get start_failed => 'Avvio del flusso fallito, controllare il saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteIt extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteIt._(TranslationsIt root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsIt {
case 'most_zapped_streamers': return 'Il maggior numero di streamer bloccati';
case 'no_user_found': return 'Nessun utente trovato';
case 'anon': return 'Anonimo';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('it').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('it'))(n,
one: '1 spettatore',
other: '${NumberFormat.decimalPattern('it').format(n)} spettatori',
@ -457,6 +499,8 @@ extension on TranslationsIt {
case 'settings.wallet.disconnect_wallet': return 'Disconnettere il portafoglio';
case 'settings.wallet.connect_1tap': return 'Connessione a 1 rubinetto';
case 'settings.wallet.paste': return 'Incolla URL';
case 'settings.wallet.balance': return 'Equilibrio';
case 'settings.wallet.name': return 'Portafoglio';
case 'settings.wallet.error.logged_out': return 'Impossibile connettere il portafoglio quando si è disconnessi';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Nessun evento wallet auth trovato';
case 'login.username': return 'Nome utente';
@ -464,6 +508,23 @@ extension on TranslationsIt {
case 'login.key': return 'Accesso con chiave';
case 'login.create': return 'Crea un account';
case 'login.error.invalid_key': return 'Chiave non valida';
case 'live.start': return 'VAI IN DIRETTA';
case 'live.configure_stream': return 'Configurare il flusso';
case 'live.endpoint': return 'Punto finale';
case 'live.accept_tos': return 'Accettare i TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('it'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titolo';
case 'live.summary': return 'Sintesi';
case 'live.image': return 'Immagine di copertina';
case 'live.tags': return 'Tag';
case 'live.nsfw': return 'Contenuto NSFW';
case 'live.nsfw_description': return 'Controllare qui se questo streaming contiene nudità o contenuti pornografici.';
case 'live.error.failed': return 'Flusso fallito';
case 'live.error.connection_error': return 'Errore di connessione';
case 'live.error.start_failed': return 'Avvio del flusso fallito, controllare il saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsJa extends Translations {
/// 匿名ユーザー
@override String get anon => '匿名';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('ja').format(n)} サッツ';
/// ストリームの視聴者数
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ja'))(n,
one: '1 視聴者',
@ -69,6 +71,7 @@ class TranslationsJa extends Translations {
@override late final _TranslationsProfileJa profile = _TranslationsProfileJa._(_root);
@override late final _TranslationsSettingsJa settings = _TranslationsSettingsJa._(_root);
@override late final _TranslationsLoginJa login = _TranslationsLoginJa._(_root);
@override late final _TranslationsLiveJa live = _TranslationsLiveJa._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginJa extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorJa error = _TranslationsLoginErrorJa._(_root);
}
// Path: live
class _TranslationsLiveJa extends TranslationsLiveEn {
_TranslationsLiveJa._(TranslationsJa root) : this._root = root, super.internal(root);
final TranslationsJa _root; // ignore: unused_field
// Translations
@override String get start => 'ライブ中継';
@override String get configure_stream => 'ストリームの設定';
@override String get endpoint => 'エンドポイント';
@override String get accept_tos => 'TOSを受け入れる';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ja'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'タイトル';
@override String get summary => '概要';
@override String get image => '表紙画像';
@override String get tags => 'タグ';
@override String get nsfw => 'NSFWコンテンツ';
@override String get nsfw_description => 'このストリームにヌードやポルノが含まれている場合は、ここをチェックしてください。';
@override late final _TranslationsLiveErrorJa error = _TranslationsLiveErrorJa._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusJa extends TranslationsStreamStatusEn {
_TranslationsStreamStatusJa._(TranslationsJa root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletJa extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'ウォレットの切断';
@override String get connect_1tap => '1タップ接続';
@override String get paste => 'URLを貼り付ける';
@override String get balance => 'バランス';
@override String get name => '財布';
@override late final _TranslationsSettingsWalletErrorJa error = _TranslationsSettingsWalletErrorJa._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorJa extends TranslationsLoginErrorEn {
@override String get invalid_key => '無効なキー';
}
// Path: live.error
class _TranslationsLiveErrorJa extends TranslationsLiveErrorEn {
_TranslationsLiveErrorJa._(TranslationsJa root) : this._root = root, super.internal(root);
final TranslationsJa _root; // ignore: unused_field
// Translations
@override String get failed => 'ストリーム失敗';
@override String get connection_error => '接続エラー';
@override String get start_failed => 'ストリームの開始に失敗しました。';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteJa extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteJa._(TranslationsJa root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsJa {
case 'most_zapped_streamers': return '最もザッピングされたストリーマー';
case 'no_user_found': return 'ユーザーが見つかりません';
case 'anon': return '匿名';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('ja').format(n)} サッツ';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ja'))(n,
one: '1 視聴者',
other: '${NumberFormat.decimalPattern('ja').format(n)} 人が視聴中',
@ -457,6 +499,8 @@ extension on TranslationsJa {
case 'settings.wallet.disconnect_wallet': return 'ウォレットの切断';
case 'settings.wallet.connect_1tap': return '1タップ接続';
case 'settings.wallet.paste': return 'URLを貼り付ける';
case 'settings.wallet.balance': return 'バランス';
case 'settings.wallet.name': return '財布';
case 'settings.wallet.error.logged_out': return 'ログアウト時にウォレットに接続できない';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'ウォレットの認証イベントが見つかりません';
case 'login.username': return 'ユーザー名';
@ -464,6 +508,23 @@ extension on TranslationsJa {
case 'login.key': return 'キーでログイン';
case 'login.create': return 'アカウントを作成する';
case 'login.error.invalid_key': return '無効なキー';
case 'live.start': return 'ライブ中継';
case 'live.configure_stream': return 'ストリームの設定';
case 'live.endpoint': return 'エンドポイント';
case 'live.accept_tos': return 'TOSを受け入れる';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ja'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'タイトル';
case 'live.summary': return '概要';
case 'live.image': return '表紙画像';
case 'live.tags': return 'タグ';
case 'live.nsfw': return 'NSFWコンテンツ';
case 'live.nsfw_description': return 'このストリームにヌードやポルノが含まれている場合は、ここをチェックしてください。';
case 'live.error.failed': return 'ストリーム失敗';
case 'live.error.connection_error': return '接続エラー';
case 'live.error.start_failed': return 'ストリームの開始に失敗しました。';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsKo extends Translations {
/// 익명 사용자
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('ko').format(n)} sats';
/// 스트림 시청자 수
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
one: '시청자 1명',
@ -69,6 +71,7 @@ class TranslationsKo extends Translations {
@override late final _TranslationsProfileKo profile = _TranslationsProfileKo._(_root);
@override late final _TranslationsSettingsKo settings = _TranslationsSettingsKo._(_root);
@override late final _TranslationsLoginKo login = _TranslationsLoginKo._(_root);
@override late final _TranslationsLiveKo live = _TranslationsLiveKo._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginKo extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorKo error = _TranslationsLoginErrorKo._(_root);
}
// Path: live
class _TranslationsLiveKo extends TranslationsLiveEn {
_TranslationsLiveKo._(TranslationsKo root) : this._root = root, super.internal(root);
final TranslationsKo _root; // ignore: unused_field
// Translations
@override String get start => '라이브 시작하기';
@override String get configure_stream => '스트림 구성';
@override String get endpoint => '엔드포인트';
@override String get accept_tos => 'TOS 수락';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
zero: '',
other: '~${time}',
);
@override String get title => '제목';
@override String get summary => '요약';
@override String get image => '표지 이미지';
@override String get tags => '태그';
@override String get nsfw => 'NSFW 콘텐츠';
@override String get nsfw_description => '이 스트림에 노출 또는 음란 콘텐츠가 포함되어 있는지 여기에서 확인하세요.';
@override late final _TranslationsLiveErrorKo error = _TranslationsLiveErrorKo._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusKo extends TranslationsStreamStatusEn {
_TranslationsStreamStatusKo._(TranslationsKo root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletKo extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => '지갑 연결 해제';
@override String get connect_1tap => '1-탭 연결';
@override String get paste => 'URL 붙여넣기';
@override String get balance => '잔액';
@override String get name => '지갑';
@override late final _TranslationsSettingsWalletErrorKo error = _TranslationsSettingsWalletErrorKo._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorKo extends TranslationsLoginErrorEn {
@override String get invalid_key => '잘못된 키';
}
// Path: live.error
class _TranslationsLiveErrorKo extends TranslationsLiveErrorEn {
_TranslationsLiveErrorKo._(TranslationsKo root) : this._root = root, super.internal(root);
final TranslationsKo _root; // ignore: unused_field
// Translations
@override String get failed => '스트림 실패';
@override String get connection_error => '연결 오류';
@override String get start_failed => '스트림 시작에 실패했습니다. 잔액을 확인해 주세요.';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteKo extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteKo._(TranslationsKo root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsKo {
case 'most_zapped_streamers': return '가장 많이 재핑된 스트리머';
case 'no_user_found': return '사용자를 찾을 수 없습니다.';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('ko').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
one: '시청자 1명',
other: '{n:decimalPattern} 시청자',
@ -457,6 +499,8 @@ extension on TranslationsKo {
case 'settings.wallet.disconnect_wallet': return '지갑 연결 해제';
case 'settings.wallet.connect_1tap': return '1-탭 연결';
case 'settings.wallet.paste': return 'URL 붙여넣기';
case 'settings.wallet.balance': return '잔액';
case 'settings.wallet.name': return '지갑';
case 'settings.wallet.error.logged_out': return '로그아웃 시 지갑 연결 불가';
case 'settings.wallet.error.nwc_auth_event_not_found': return '지갑 인증 이벤트를 찾을 수 없습니다.';
case 'login.username': return '사용자 이름';
@ -464,6 +508,23 @@ extension on TranslationsKo {
case 'login.key': return '키로 로그인';
case 'login.create': return '계정 만들기';
case 'login.error.invalid_key': return '잘못된 키';
case 'live.start': return '라이브 시작하기';
case 'live.configure_stream': return '스트림 구성';
case 'live.endpoint': return '엔드포인트';
case 'live.accept_tos': return 'TOS 수락';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ko'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return '제목';
case 'live.summary': return '요약';
case 'live.image': return '표지 이미지';
case 'live.tags': return '태그';
case 'live.nsfw': return 'NSFW 콘텐츠';
case 'live.nsfw_description': return '이 스트림에 노출 또는 음란 콘텐츠가 포함되어 있는지 여기에서 확인하세요.';
case 'live.error.failed': return '스트림 실패';
case 'live.error.connection_error': return '연결 오류';
case 'live.error.start_failed': return '스트림 시작에 실패했습니다. 잔액을 확인해 주세요.';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsNl extends Translations {
/// Een anonieme gebruiker
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('nl').format(n)} sats';
/// Aantal kijkers van de stream
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('nl'))(n,
one: '1 kijker',
@ -69,6 +71,7 @@ class TranslationsNl extends Translations {
@override late final _TranslationsProfileNl profile = _TranslationsProfileNl._(_root);
@override late final _TranslationsSettingsNl settings = _TranslationsSettingsNl._(_root);
@override late final _TranslationsLoginNl login = _TranslationsLoginNl._(_root);
@override late final _TranslationsLiveNl live = _TranslationsLiveNl._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginNl extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorNl error = _TranslationsLoginErrorNl._(_root);
}
// Path: live
class _TranslationsLiveNl extends TranslationsLiveEn {
_TranslationsLiveNl._(TranslationsNl root) : this._root = root, super.internal(root);
final TranslationsNl _root; // ignore: unused_field
// Translations
@override String get start => 'LIVE GAAN';
@override String get configure_stream => 'Stream configureren';
@override String get endpoint => 'Eindpunt';
@override String get accept_tos => 'TOS accepteren';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('nl'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titel';
@override String get summary => 'Samenvatting';
@override String get image => 'Afbeelding omslag';
@override String get tags => 'Tags';
@override String get nsfw => 'NSFW-inhoud';
@override String get nsfw_description => 'Controleer hier of deze stream naaktheid of pornografische inhoud bevat.';
@override late final _TranslationsLiveErrorNl error = _TranslationsLiveErrorNl._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusNl extends TranslationsStreamStatusEn {
_TranslationsStreamStatusNl._(TranslationsNl root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletNl extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Portefeuille loskoppelen';
@override String get connect_1tap => '1-Tap Aansluiting';
@override String get paste => 'URL plakken';
@override String get balance => 'Saldo';
@override String get name => 'Portemonnee';
@override late final _TranslationsSettingsWalletErrorNl error = _TranslationsSettingsWalletErrorNl._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorNl extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Ongeldige sleutel';
}
// Path: live.error
class _TranslationsLiveErrorNl extends TranslationsLiveErrorEn {
_TranslationsLiveErrorNl._(TranslationsNl root) : this._root = root, super.internal(root);
final TranslationsNl _root; // ignore: unused_field
// Translations
@override String get failed => 'Stream mislukt';
@override String get connection_error => 'Fout bij verbinding';
@override String get start_failed => 'Stream start mislukt, controleer uw saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteNl extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteNl._(TranslationsNl root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsNl {
case 'most_zapped_streamers': return 'Meeste Zapped Streamers';
case 'no_user_found': return 'Geen gebruiker gevonden';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('nl').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('nl'))(n,
one: '1 kijker',
other: '${NumberFormat.decimalPattern('nl').format(n)} kijkers',
@ -457,6 +499,8 @@ extension on TranslationsNl {
case 'settings.wallet.disconnect_wallet': return 'Portefeuille loskoppelen';
case 'settings.wallet.connect_1tap': return '1-Tap Aansluiting';
case 'settings.wallet.paste': return 'URL plakken';
case 'settings.wallet.balance': return 'Saldo';
case 'settings.wallet.name': return 'Portemonnee';
case 'settings.wallet.error.logged_out': return 'Kan geen verbinding maken met portemonnee als ik ben uitgelogd';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Geen portemonnee-auth-gebeurtenis gevonden';
case 'login.username': return 'Gebruikersnaam';
@ -464,6 +508,23 @@ extension on TranslationsNl {
case 'login.key': return 'Inloggen met sleutel';
case 'login.create': return 'Account aanmaken';
case 'login.error.invalid_key': return 'Ongeldige sleutel';
case 'live.start': return 'LIVE GAAN';
case 'live.configure_stream': return 'Stream configureren';
case 'live.endpoint': return 'Eindpunt';
case 'live.accept_tos': return 'TOS accepteren';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('nl'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titel';
case 'live.summary': return 'Samenvatting';
case 'live.image': return 'Afbeelding omslag';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'NSFW-inhoud';
case 'live.nsfw_description': return 'Controleer hier of deze stream naaktheid of pornografische inhoud bevat.';
case 'live.error.failed': return 'Stream mislukt';
case 'live.error.connection_error': return 'Fout bij verbinding';
case 'live.error.start_failed': return 'Stream start mislukt, controleer uw saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsPl extends Translations {
/// Anonimowy użytkownik
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('pl').format(n)} sats';
/// Liczba widzów strumienia
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pl'))(n,
one: '1 przeglądarka',
@ -69,6 +71,7 @@ class TranslationsPl extends Translations {
@override late final _TranslationsProfilePl profile = _TranslationsProfilePl._(_root);
@override late final _TranslationsSettingsPl settings = _TranslationsSettingsPl._(_root);
@override late final _TranslationsLoginPl login = _TranslationsLoginPl._(_root);
@override late final _TranslationsLivePl live = _TranslationsLivePl._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginPl extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorPl error = _TranslationsLoginErrorPl._(_root);
}
// Path: live
class _TranslationsLivePl extends TranslationsLiveEn {
_TranslationsLivePl._(TranslationsPl root) : this._root = root, super.internal(root);
final TranslationsPl _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Konfiguracja strumienia';
@override String get endpoint => 'Punkt końcowy';
@override String get accept_tos => 'Zaakceptuj Regulamin';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pl'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Tytuł';
@override String get summary => 'Podsumowanie';
@override String get image => 'Obraz na okładce';
@override String get tags => 'Tagi';
@override String get nsfw => 'Treści NSFW';
@override String get nsfw_description => 'Sprawdź tutaj, czy ten stream zawiera nagość lub treści pornograficzne.';
@override late final _TranslationsLiveErrorPl error = _TranslationsLiveErrorPl._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusPl extends TranslationsStreamStatusEn {
_TranslationsStreamStatusPl._(TranslationsPl root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletPl extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Odłącz portfel';
@override String get connect_1tap => 'Połączenie 1-wtykowe';
@override String get paste => 'Wklej adres URL';
@override String get balance => 'Równowaga';
@override String get name => 'Portfel';
@override late final _TranslationsSettingsWalletErrorPl error = _TranslationsSettingsWalletErrorPl._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorPl extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Nieprawidłowy klucz';
}
// Path: live.error
class _TranslationsLiveErrorPl extends TranslationsLiveErrorEn {
_TranslationsLiveErrorPl._(TranslationsPl root) : this._root = root, super.internal(root);
final TranslationsPl _root; // ignore: unused_field
// Translations
@override String get failed => 'Strumień nie powiódł się';
@override String get connection_error => 'Błąd połączenia';
@override String get start_failed => 'Uruchomienie strumienia nie powiodło się, sprawdź saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWritePl extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWritePl._(TranslationsPl root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsPl {
case 'most_zapped_streamers': return 'Większość zapped streamerów';
case 'no_user_found': return 'Nie znaleziono użytkownika';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('pl').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pl'))(n,
one: '1 przeglądarka',
other: '{n:decimalPattern} widzów',
@ -457,6 +499,8 @@ extension on TranslationsPl {
case 'settings.wallet.disconnect_wallet': return 'Odłącz portfel';
case 'settings.wallet.connect_1tap': return 'Połączenie 1-wtykowe';
case 'settings.wallet.paste': return 'Wklej adres URL';
case 'settings.wallet.balance': return 'Równowaga';
case 'settings.wallet.name': return 'Portfel';
case 'settings.wallet.error.logged_out': return 'Nie można połączyć portfela po wylogowaniu';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Nie znaleziono zdarzenia autoryzacji portfela';
case 'login.username': return 'Nazwa użytkownika';
@ -464,6 +508,23 @@ extension on TranslationsPl {
case 'login.key': return 'Logowanie za pomocą klucza';
case 'login.create': return 'Utwórz konto';
case 'login.error.invalid_key': return 'Nieprawidłowy klucz';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Konfiguracja strumienia';
case 'live.endpoint': return 'Punkt końcowy';
case 'live.accept_tos': return 'Zaakceptuj Regulamin';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pl'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Tytuł';
case 'live.summary': return 'Podsumowanie';
case 'live.image': return 'Obraz na okładce';
case 'live.tags': return 'Tagi';
case 'live.nsfw': return 'Treści NSFW';
case 'live.nsfw_description': return 'Sprawdź tutaj, czy ten stream zawiera nagość lub treści pornograficzne.';
case 'live.error.failed': return 'Strumień nie powiódł się';
case 'live.error.connection_error': return 'Błąd połączenia';
case 'live.error.start_failed': return 'Uruchomienie strumienia nie powiodło się, sprawdź saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsPt extends Translations {
/// Um usuário anônimo
@override String get anon => 'Anônimo';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('pt').format(n)} sats';
/// Número de espectadores da transmissão
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pt'))(n,
one: '1 visualizador',
@ -69,6 +71,7 @@ class TranslationsPt extends Translations {
@override late final _TranslationsProfilePt profile = _TranslationsProfilePt._(_root);
@override late final _TranslationsSettingsPt settings = _TranslationsSettingsPt._(_root);
@override late final _TranslationsLoginPt login = _TranslationsLoginPt._(_root);
@override late final _TranslationsLivePt live = _TranslationsLivePt._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginPt extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorPt error = _TranslationsLoginErrorPt._(_root);
}
// Path: live
class _TranslationsLivePt extends TranslationsLiveEn {
_TranslationsLivePt._(TranslationsPt root) : this._root = root, super.internal(root);
final TranslationsPt _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Configurar fluxo';
@override String get endpoint => 'Ponto final';
@override String get accept_tos => 'Aceitar os Termos de Serviço';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pt'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Título';
@override String get summary => 'Resumo';
@override String get image => 'Imagem da capa';
@override String get tags => 'Tags';
@override String get nsfw => 'Conteúdo NSFW';
@override String get nsfw_description => 'Verifique aqui se essa transmissão contém nudez ou conteúdo pornográfico.';
@override late final _TranslationsLiveErrorPt error = _TranslationsLiveErrorPt._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusPt extends TranslationsStreamStatusEn {
_TranslationsStreamStatusPt._(TranslationsPt root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletPt extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Desconectar carteira';
@override String get connect_1tap => 'Conexão de 1 torneira';
@override String get paste => 'Colar URL';
@override String get balance => 'Equilíbrio';
@override String get name => 'Carteira';
@override late final _TranslationsSettingsWalletErrorPt error = _TranslationsSettingsWalletErrorPt._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorPt extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Chave inválida';
}
// Path: live.error
class _TranslationsLiveErrorPt extends TranslationsLiveErrorEn {
_TranslationsLiveErrorPt._(TranslationsPt root) : this._root = root, super.internal(root);
final TranslationsPt _root; // ignore: unused_field
// Translations
@override String get failed => 'O fluxo falhou';
@override String get connection_error => 'Erro de conexão';
@override String get start_failed => 'Falha no início do fluxo, verifique seu saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWritePt extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWritePt._(TranslationsPt root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsPt {
case 'most_zapped_streamers': return 'Streamers mais afetados';
case 'no_user_found': return 'Nenhum usuário encontrado';
case 'anon': return 'Anônimo';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('pt').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pt'))(n,
one: '1 visualizador',
other: '${NumberFormat.decimalPattern('pt').format(n)} espectadores',
@ -457,6 +499,8 @@ extension on TranslationsPt {
case 'settings.wallet.disconnect_wallet': return 'Desconectar carteira';
case 'settings.wallet.connect_1tap': return 'Conexão de 1 torneira';
case 'settings.wallet.paste': return 'Colar URL';
case 'settings.wallet.balance': return 'Equilíbrio';
case 'settings.wallet.name': return 'Carteira';
case 'settings.wallet.error.logged_out': return 'Não consigo conectar a carteira quando estou desconectado';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Nenhum evento de autenticação de carteira encontrado';
case 'login.username': return 'Nome de usuário';
@ -464,6 +508,23 @@ extension on TranslationsPt {
case 'login.key': return 'Login com chave';
case 'login.create': return 'Criar Conta';
case 'login.error.invalid_key': return 'Chave inválida';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Configurar fluxo';
case 'live.endpoint': return 'Ponto final';
case 'live.accept_tos': return 'Aceitar os Termos de Serviço';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('pt'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Título';
case 'live.summary': return 'Resumo';
case 'live.image': return 'Imagem da capa';
case 'live.tags': return 'Tags';
case 'live.nsfw': return 'Conteúdo NSFW';
case 'live.nsfw_description': return 'Verifique aqui se essa transmissão contém nudez ou conteúdo pornográfico.';
case 'live.error.failed': return 'O fluxo falhou';
case 'live.error.connection_error': return 'Erro de conexão';
case 'live.error.start_failed': return 'Falha no início do fluxo, verifique seu saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsRo extends Translations {
/// Un utilizator anonim
@override String get anon => 'Anon';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('ro').format(n)} sats';
/// Numărul de telespectatori ai fluxului
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ro'))(n,
one: '1 vizualizator',
@ -69,6 +71,7 @@ class TranslationsRo extends Translations {
@override late final _TranslationsProfileRo profile = _TranslationsProfileRo._(_root);
@override late final _TranslationsSettingsRo settings = _TranslationsSettingsRo._(_root);
@override late final _TranslationsLoginRo login = _TranslationsLoginRo._(_root);
@override late final _TranslationsLiveRo live = _TranslationsLiveRo._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginRo extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorRo error = _TranslationsLoginErrorRo._(_root);
}
// Path: live
class _TranslationsLiveRo extends TranslationsLiveEn {
_TranslationsLiveRo._(TranslationsRo root) : this._root = root, super.internal(root);
final TranslationsRo _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Configurați fluxul';
@override String get endpoint => 'Punct final';
@override String get accept_tos => 'Acceptați TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ro'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titlu';
@override String get summary => 'Rezumat';
@override String get image => 'Imagine de copertă';
@override String get tags => 'Etichete';
@override String get nsfw => 'Conținut NSFW';
@override String get nsfw_description => 'Bifați aici dacă acest flux conține nuditate sau conținut pornografic.';
@override late final _TranslationsLiveErrorRo error = _TranslationsLiveErrorRo._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusRo extends TranslationsStreamStatusEn {
_TranslationsStreamStatusRo._(TranslationsRo root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletRo extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Deconectați portofelul';
@override String get connect_1tap => 'Conexiune 1-Tap';
@override String get paste => 'Lipiți URL';
@override String get balance => 'Echilibru';
@override String get name => 'Portofel';
@override late final _TranslationsSettingsWalletErrorRo error = _TranslationsSettingsWalletErrorRo._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorRo extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Cheie invalidă';
}
// Path: live.error
class _TranslationsLiveErrorRo extends TranslationsLiveErrorEn {
_TranslationsLiveErrorRo._(TranslationsRo root) : this._root = root, super.internal(root);
final TranslationsRo _root; // ignore: unused_field
// Translations
@override String get failed => 'Fluxul a eșuat';
@override String get connection_error => 'Eroare de conectare';
@override String get start_failed => 'Pornirea fluxului a eșuat, vă rugăm să verificați soldul';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteRo extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteRo._(TranslationsRo root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsRo {
case 'most_zapped_streamers': return 'Cele mai multe Streamers Zapped';
case 'no_user_found': return 'Niciun utilizator găsit';
case 'anon': return 'Anon';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('ro').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ro'))(n,
one: '1 vizualizator',
other: '${NumberFormat.decimalPattern('ro').format(n)} telespectatori',
@ -457,6 +499,8 @@ extension on TranslationsRo {
case 'settings.wallet.disconnect_wallet': return 'Deconectați portofelul';
case 'settings.wallet.connect_1tap': return 'Conexiune 1-Tap';
case 'settings.wallet.paste': return 'Lipiți URL';
case 'settings.wallet.balance': return 'Echilibru';
case 'settings.wallet.name': return 'Portofel';
case 'settings.wallet.error.logged_out': return 'Nu puteți conecta portofelul atunci când sunteți deconectat';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Nu a fost găsit niciun eveniment de autorizare a portofelului';
case 'login.username': return 'Nume utilizator';
@ -464,6 +508,23 @@ extension on TranslationsRo {
case 'login.key': return 'Autentificare cu cheie';
case 'login.create': return 'Creare cont';
case 'login.error.invalid_key': return 'Cheie invalidă';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Configurați fluxul';
case 'live.endpoint': return 'Punct final';
case 'live.accept_tos': return 'Acceptați TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ro'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titlu';
case 'live.summary': return 'Rezumat';
case 'live.image': return 'Imagine de copertă';
case 'live.tags': return 'Etichete';
case 'live.nsfw': return 'Conținut NSFW';
case 'live.nsfw_description': return 'Bifați aici dacă acest flux conține nuditate sau conținut pornografic.';
case 'live.error.failed': return 'Fluxul a eșuat';
case 'live.error.connection_error': return 'Eroare de conectare';
case 'live.error.start_failed': return 'Pornirea fluxului a eșuat, vă rugăm să verificați soldul';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsRu extends Translations {
/// Анонимный пользователь
@override String get anon => 'Аноним';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('ru').format(n)} sats';
/// Количество зрителей потока
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
one: '1 зритель',
@ -69,6 +71,7 @@ class TranslationsRu extends Translations {
@override late final _TranslationsProfileRu profile = _TranslationsProfileRu._(_root);
@override late final _TranslationsSettingsRu settings = _TranslationsSettingsRu._(_root);
@override late final _TranslationsLoginRu login = _TranslationsLoginRu._(_root);
@override late final _TranslationsLiveRu live = _TranslationsLiveRu._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginRu extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorRu error = _TranslationsLoginErrorRu._(_root);
}
// Path: live
class _TranslationsLiveRu extends TranslationsLiveEn {
_TranslationsLiveRu._(TranslationsRu root) : this._root = root, super.internal(root);
final TranslationsRu _root; // ignore: unused_field
// Translations
@override String get start => 'ПЕРЕЙТИ В ПРЯМОЙ ЭФИР';
@override String get configure_stream => 'Настроить поток';
@override String get endpoint => 'Конечная точка';
@override String get accept_tos => 'Принять TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Название';
@override String get summary => 'Резюме';
@override String get image => 'Изображение на обложке';
@override String get tags => 'Теги';
@override String get nsfw => 'NSFW-контент';
@override String get nsfw_description => 'Отметьте здесь, если этот поток содержит наготу или порнографические материалы.';
@override late final _TranslationsLiveErrorRu error = _TranslationsLiveErrorRu._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusRu extends TranslationsStreamStatusEn {
_TranslationsStreamStatusRu._(TranslationsRu root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletRu extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Отключить кошелек';
@override String get connect_1tap => '1-кратное соединение';
@override String get paste => 'Вставить URL';
@override String get balance => 'Баланс';
@override String get name => 'Кошелек';
@override late final _TranslationsSettingsWalletErrorRu error = _TranslationsSettingsWalletErrorRu._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorRu extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Неверный ключ';
}
// Path: live.error
class _TranslationsLiveErrorRu extends TranslationsLiveErrorEn {
_TranslationsLiveErrorRu._(TranslationsRu root) : this._root = root, super.internal(root);
final TranslationsRu _root; // ignore: unused_field
// Translations
@override String get failed => 'Сбой потока';
@override String get connection_error => 'Ошибка подключения';
@override String get start_failed => 'Запуск потока не удался, пожалуйста, проверьте баланс';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteRu extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteRu._(TranslationsRu root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsRu {
case 'most_zapped_streamers': return 'Самые прыткие стримеры';
case 'no_user_found': return 'Пользователь не найден';
case 'anon': return 'Аноним';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('ru').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
one: '1 зритель',
other: '${NumberFormat.decimalPattern('ru').format(n)} зрителей',
@ -457,6 +499,8 @@ extension on TranslationsRu {
case 'settings.wallet.disconnect_wallet': return 'Отключить кошелек';
case 'settings.wallet.connect_1tap': return '1-кратное соединение';
case 'settings.wallet.paste': return 'Вставить URL';
case 'settings.wallet.balance': return 'Баланс';
case 'settings.wallet.name': return 'Кошелек';
case 'settings.wallet.error.logged_out': return 'Невозможно подключить кошелек при выходе из системы';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Событие аутентификации кошелька не найдено';
case 'login.username': return 'Имя пользователя';
@ -464,6 +508,23 @@ extension on TranslationsRu {
case 'login.key': return 'Вход в систему с помощью ключа';
case 'login.create': return 'Создать аккаунт';
case 'login.error.invalid_key': return 'Неверный ключ';
case 'live.start': return 'ПЕРЕЙТИ В ПРЯМОЙ ЭФИР';
case 'live.configure_stream': return 'Настроить поток';
case 'live.endpoint': return 'Конечная точка';
case 'live.accept_tos': return 'Принять TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Название';
case 'live.summary': return 'Резюме';
case 'live.image': return 'Изображение на обложке';
case 'live.tags': return 'Теги';
case 'live.nsfw': return 'NSFW-контент';
case 'live.nsfw_description': return 'Отметьте здесь, если этот поток содержит наготу или порнографические материалы.';
case 'live.error.failed': return 'Сбой потока';
case 'live.error.connection_error': return 'Ошибка подключения';
case 'live.error.start_failed': return 'Запуск потока не удался, пожалуйста, проверьте баланс';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsSv extends Translations {
/// En anonym användare
@override String get anon => 'Anno';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('sv').format(n)} sats';
/// Antal tittare på strömmingen
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
one: '1 tittare',
@ -69,6 +71,7 @@ class TranslationsSv extends Translations {
@override late final _TranslationsProfileSv profile = _TranslationsProfileSv._(_root);
@override late final _TranslationsSettingsSv settings = _TranslationsSettingsSv._(_root);
@override late final _TranslationsLoginSv login = _TranslationsLoginSv._(_root);
@override late final _TranslationsLiveSv live = _TranslationsLiveSv._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginSv extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorSv error = _TranslationsLoginErrorSv._(_root);
}
// Path: live
class _TranslationsLiveSv extends TranslationsLiveEn {
_TranslationsLiveSv._(TranslationsSv root) : this._root = root, super.internal(root);
final TranslationsSv _root; // ignore: unused_field
// Translations
@override String get start => 'GÅ DIREKT';
@override String get configure_stream => 'Konfigurera ström';
@override String get endpoint => 'Slutpunkt';
@override String get accept_tos => 'Acceptera TOS';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Titel';
@override String get summary => 'Sammanfattning';
@override String get image => 'Omslagsbild';
@override String get tags => 'Etiketter';
@override String get nsfw => 'NSFW-innehåll';
@override String get nsfw_description => 'Markera här om denna stream innehåller nakenhet eller pornografiskt innehåll.';
@override late final _TranslationsLiveErrorSv error = _TranslationsLiveErrorSv._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusSv extends TranslationsStreamStatusEn {
_TranslationsStreamStatusSv._(TranslationsSv root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletSv extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Koppla bort plånboken';
@override String get connect_1tap => '1-tryck anslutning';
@override String get paste => 'Klistra in URL';
@override String get balance => 'Balans';
@override String get name => 'Plånbok';
@override late final _TranslationsSettingsWalletErrorSv error = _TranslationsSettingsWalletErrorSv._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorSv extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Ogiltig nyckel';
}
// Path: live.error
class _TranslationsLiveErrorSv extends TranslationsLiveErrorEn {
_TranslationsLiveErrorSv._(TranslationsSv root) : this._root = root, super.internal(root);
final TranslationsSv _root; // ignore: unused_field
// Translations
@override String get failed => 'Strömmen misslyckades';
@override String get connection_error => 'Anslutningsfel';
@override String get start_failed => 'Stream start misslyckades, vänligen kontrollera ditt saldo';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteSv extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteSv._(TranslationsSv root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsSv {
case 'most_zapped_streamers': return 'De flest zappade streamers';
case 'no_user_found': return 'Ingen användare hittades';
case 'anon': return 'Anno';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('sv').format(n)} sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
one: '1 tittare',
other: '${NumberFormat.decimalPattern('sv').format(n)} tittare',
@ -457,6 +499,8 @@ extension on TranslationsSv {
case 'settings.wallet.disconnect_wallet': return 'Koppla bort plånboken';
case 'settings.wallet.connect_1tap': return '1-tryck anslutning';
case 'settings.wallet.paste': return 'Klistra in URL';
case 'settings.wallet.balance': return 'Balans';
case 'settings.wallet.name': return 'Plånbok';
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';
@ -464,6 +508,23 @@ extension on TranslationsSv {
case 'login.key': return 'Logga in med nyckel';
case 'login.create': return 'Skapa konto';
case 'login.error.invalid_key': return 'Ogiltig nyckel';
case 'live.start': return 'GÅ DIREKT';
case 'live.configure_stream': return 'Konfigurera ström';
case 'live.endpoint': return 'Slutpunkt';
case 'live.accept_tos': return 'Acceptera TOS';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('sv'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Titel';
case 'live.summary': return 'Sammanfattning';
case 'live.image': return 'Omslagsbild';
case 'live.tags': return 'Etiketter';
case 'live.nsfw': return 'NSFW-innehåll';
case 'live.nsfw_description': return 'Markera här om denna stream innehåller nakenhet eller pornografiskt innehåll.';
case 'live.error.failed': return 'Strömmen misslyckades';
case 'live.error.connection_error': return 'Anslutningsfel';
case 'live.error.start_failed': return 'Stream start misslyckades, vänligen kontrollera ditt saldo';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsUk extends Translations {
/// Анонімний користувач
@override String get anon => 'Анонім.';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('uk').format(n)} сатів';
/// Кількість глядачів стріму
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('uk'))(n,
one: '1 глядач',
@ -69,6 +71,7 @@ class TranslationsUk extends Translations {
@override late final _TranslationsProfileUk profile = _TranslationsProfileUk._(_root);
@override late final _TranslationsSettingsUk settings = _TranslationsSettingsUk._(_root);
@override late final _TranslationsLoginUk login = _TranslationsLoginUk._(_root);
@override late final _TranslationsLiveUk live = _TranslationsLiveUk._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginUk extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorUk error = _TranslationsLoginErrorUk._(_root);
}
// Path: live
class _TranslationsLiveUk extends TranslationsLiveEn {
_TranslationsLiveUk._(TranslationsUk root) : this._root = root, super.internal(root);
final TranslationsUk _root; // ignore: unused_field
// Translations
@override String get start => 'GO LIVE';
@override String get configure_stream => 'Налаштувати потік';
@override String get endpoint => 'Кінцева точка';
@override String get accept_tos => 'Прийміть ТЗ';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('uk'))(n,
zero: '',
other: '~${time}',
);
@override String get title => 'Назва';
@override String get summary => 'Підсумок';
@override String get image => 'Зображення обкладинки';
@override String get tags => 'Теги';
@override String get nsfw => 'Нецензурна лексика';
@override String get nsfw_description => 'Перевірте тут, чи містить цей потік оголену натуру або порнографічний контент.';
@override late final _TranslationsLiveErrorUk error = _TranslationsLiveErrorUk._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusUk extends TranslationsStreamStatusEn {
_TranslationsStreamStatusUk._(TranslationsUk root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletUk extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => 'Відключити гаманець';
@override String get connect_1tap => 'Підключення в 1 кран';
@override String get paste => 'Вставити URL-адресу';
@override String get balance => 'Баланс';
@override String get name => 'Гаманець';
@override late final _TranslationsSettingsWalletErrorUk error = _TranslationsSettingsWalletErrorUk._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorUk extends TranslationsLoginErrorEn {
@override String get invalid_key => 'Неправильний ключ';
}
// Path: live.error
class _TranslationsLiveErrorUk extends TranslationsLiveErrorEn {
_TranslationsLiveErrorUk._(TranslationsUk root) : this._root = root, super.internal(root);
final TranslationsUk _root; // ignore: unused_field
// Translations
@override String get failed => 'Потік не вдалося запустити';
@override String get connection_error => 'Помилка з\'єднання';
@override String get start_failed => 'Не вдалося запустити трансляцію, будь ласка, перевірте свій баланс';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteUk extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteUk._(TranslationsUk root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsUk {
case 'most_zapped_streamers': return 'Більшість стримерів, які були під напругою';
case 'no_user_found': return 'Користувача не знайдено';
case 'anon': return 'Анонім.';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('uk').format(n)} сатів';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('uk'))(n,
one: '1 глядач',
other: '${NumberFormat.decimalPattern('uk').format(n)} глядачів',
@ -457,6 +499,8 @@ extension on TranslationsUk {
case 'settings.wallet.disconnect_wallet': return 'Відключити гаманець';
case 'settings.wallet.connect_1tap': return 'Підключення в 1 кран';
case 'settings.wallet.paste': return 'Вставити URL-адресу';
case 'settings.wallet.balance': return 'Баланс';
case 'settings.wallet.name': return 'Гаманець';
case 'settings.wallet.error.logged_out': return 'Не вдається підключити гаманець, коли ви вийшли з системи';
case 'settings.wallet.error.nwc_auth_event_not_found': return 'Не знайдено жодної події авторизації гаманця';
case 'login.username': return 'Ім\'я користувача';
@ -464,6 +508,23 @@ extension on TranslationsUk {
case 'login.key': return 'Увійдіть за допомогою ключа';
case 'login.create': return 'Створити обліковий запис';
case 'login.error.invalid_key': return 'Неправильний ключ';
case 'live.start': return 'GO LIVE';
case 'live.configure_stream': return 'Налаштувати потік';
case 'live.endpoint': return 'Кінцева точка';
case 'live.accept_tos': return 'Прийміть ТЗ';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('uk'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return 'Назва';
case 'live.summary': return 'Підсумок';
case 'live.image': return 'Зображення обкладинки';
case 'live.tags': return 'Теги';
case 'live.nsfw': return 'Нецензурна лексика';
case 'live.nsfw_description': return 'Перевірте тут, чи містить цей потік оголену натуру або порнографічний контент.';
case 'live.error.failed': return 'Потік не вдалося запустити';
case 'live.error.connection_error': return 'Помилка з\'єднання';
case 'live.error.start_failed': return 'Не вдалося запустити трансляцію, будь ласка, перевірте свій баланс';
default: return null;
}
}

View File

@ -51,6 +51,8 @@ class TranslationsZh extends Translations {
/// 匿名使用者
@override String get anon => '匿名';
@override String full_amount_sats({required num n}) => '${NumberFormat.decimalPattern('zh').format(n)} Sats';
/// 串流的觀看者人數
@override String viewers({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n,
one: '1 個檢視器',
@ -69,6 +71,7 @@ class TranslationsZh extends Translations {
@override late final _TranslationsProfileZh profile = _TranslationsProfileZh._(_root);
@override late final _TranslationsSettingsZh settings = _TranslationsSettingsZh._(_root);
@override late final _TranslationsLoginZh login = _TranslationsLoginZh._(_root);
@override late final _TranslationsLiveZh live = _TranslationsLiveZh._(_root);
}
// Path: stream
@ -205,6 +208,30 @@ class _TranslationsLoginZh extends TranslationsLoginEn {
@override late final _TranslationsLoginErrorZh error = _TranslationsLoginErrorZh._(_root);
}
// Path: live
class _TranslationsLiveZh extends TranslationsLiveEn {
_TranslationsLiveZh._(TranslationsZh root) : this._root = root, super.internal(root);
final TranslationsZh _root; // ignore: unused_field
// Translations
@override String get start => '開始直播';
@override String get configure_stream => '設定串流';
@override String get endpoint => '終點';
@override String get accept_tos => '接受服務條款';
@override String balance_left({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n,
zero: '',
other: '~${time}',
);
@override String get title => '標題';
@override String get summary => '摘要';
@override String get image => '封面圖片';
@override String get tags => '標籤';
@override String get nsfw => 'NSFW 內容';
@override String get nsfw_description => '請檢查此串流是否包含裸體或色情內容。';
@override late final _TranslationsLiveErrorZh error = _TranslationsLiveErrorZh._(_root);
}
// Path: stream.status
class _TranslationsStreamStatusZh extends TranslationsStreamStatusEn {
_TranslationsStreamStatusZh._(TranslationsZh root) : this._root = root, super.internal(root);
@ -289,6 +316,8 @@ class _TranslationsSettingsWalletZh extends TranslationsSettingsWalletEn {
@override String get disconnect_wallet => '斷開錢包';
@override String get connect_1tap => '1 抽頭連接';
@override String get paste => '貼上 URL';
@override String get balance => '平衡';
@override String get name => '錢包';
@override late final _TranslationsSettingsWalletErrorZh error = _TranslationsSettingsWalletErrorZh._(_root);
}
@ -302,6 +331,18 @@ class _TranslationsLoginErrorZh extends TranslationsLoginErrorEn {
@override String get invalid_key => '無效按鍵';
}
// Path: live.error
class _TranslationsLiveErrorZh extends TranslationsLiveErrorEn {
_TranslationsLiveErrorZh._(TranslationsZh root) : this._root = root, super.internal(root);
final TranslationsZh _root; // ignore: unused_field
// Translations
@override String get failed => '串流失敗';
@override String get connection_error => '連線錯誤';
@override String get start_failed => '串流啟動失敗,請檢查您的餘額';
}
// Path: stream.chat.write
class _TranslationsStreamChatWriteZh extends TranslationsStreamChatWriteEn {
_TranslationsStreamChatWriteZh._(TranslationsZh root) : this._root = root, super.internal(root);
@ -380,6 +421,7 @@ extension on TranslationsZh {
case 'most_zapped_streamers': return '最多被擊中的溪流';
case 'no_user_found': return '未找到使用者';
case 'anon': return '匿名';
case 'full_amount_sats': return ({required num n}) => '${NumberFormat.decimalPattern('zh').format(n)} Sats';
case 'viewers': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n,
one: '1 個檢視器',
other: '${NumberFormat.decimalPattern('zh').format(n)} 觀眾',
@ -457,6 +499,8 @@ extension on TranslationsZh {
case 'settings.wallet.disconnect_wallet': return '斷開錢包';
case 'settings.wallet.connect_1tap': return '1 抽頭連接';
case 'settings.wallet.paste': return '貼上 URL';
case 'settings.wallet.balance': return '平衡';
case 'settings.wallet.name': return '錢包';
case 'settings.wallet.error.logged_out': return '登出時無法連接錢包';
case 'settings.wallet.error.nwc_auth_event_not_found': return '未找到錢包認證事件';
case 'login.username': return '用戶名';
@ -464,6 +508,23 @@ extension on TranslationsZh {
case 'login.key': return '使用鑰匙登入';
case 'login.create': return '創建帳戶';
case 'login.error.invalid_key': return '無效按鍵';
case 'live.start': return '開始直播';
case 'live.configure_stream': return '設定串流';
case 'live.endpoint': return '終點';
case 'live.accept_tos': return '接受服務條款';
case 'live.balance_left': return ({required num n, required Object time}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('zh'))(n,
zero: '',
other: '~${time}',
);
case 'live.title': return '標題';
case 'live.summary': return '摘要';
case 'live.image': return '封面圖片';
case 'live.tags': return '標籤';
case 'live.nsfw': return 'NSFW 內容';
case 'live.nsfw_description': return '請檢查此串流是否包含裸體或色情內容。';
case 'live.error.failed': return '串流失敗';
case 'live.error.connection_error': return '連線錯誤';
case 'live.error.start_failed': return '串流啟動失敗,請檢查您的餘額';
default: return null;
}
}

View File

@ -8,6 +8,7 @@ no_user_found: لم يتم العثور على مستخدم
"@no_user_found":
description: لم يتم العثور على مستخدم عند البحث
anon: هوية مخفية
full_amount_sats: "${n:decimalPattern} دولار ساتس"
viewers:
one: 1 مشاهد
other: "{n:decimalPattern} المشاهدين"
@ -123,6 +124,8 @@ settings:
disconnect_wallet: محفظة قطع الاتصال
connect_1tap: 1-التوصيل بنقرة 1
paste: لصق عنوان URL
balance: الرصيد
name: المحفظة
error:
logged_out: لا يمكن الاتصال بالمحفظة عند تسجيل الخروج
nwc_auth_event_not_found: لم يتم العثور على حدث مصادقة المحفظة
@ -133,3 +136,21 @@ login:
create: إنشاء حساب
error:
invalid_key: مفتاح غير صالح
live:
start: ابدأ البث المباشر
configure_stream: تكوين الدفق
endpoint: نقطة النهاية
accept_tos: قبول شروط الخدمة
balance_left:
zero:
other: ~${time}
title: العنوان
summary: الملخص
image: صورة الغلاف
tags: الوسوم
nsfw: محتوى غير لائق جنسيًا
nsfw_description: تحقق هنا إذا كان هذا البث يحتوي على محتوى إباحي أو عري.
error:
failed: فشل البث
connection_error: خطأ في الاتصال
start_failed: فشل بدء البث فشل، يرجى التحقق من رصيدك

View File

@ -9,6 +9,7 @@ no_user_found: Nebyl nalezen žádný uživatel
"@no_user_found":
description: Při vyhledávání nebyl nalezen žádný uživatel
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 divák
other: ${n:decimalPattern} diváků
@ -124,6 +125,8 @@ settings:
disconnect_wallet: Odpojení peněženky
connect_1tap: Připojení 1 kohoutku
paste: Vložit adresu URL
balance: Bilance
name: Peněženka
error:
logged_out: Nelze se připojit k peněžence, když jste odhlášeni
nwc_auth_event_not_found: Nebyla nalezena žádná událost autentizace peněženky
@ -134,3 +137,21 @@ login:
create: Vytvořit účet
error:
invalid_key: Neplatný klíč
live:
start: PŘEJÍT NA ŽIVOT
configure_stream: Konfigurace streamu
endpoint: Koncový bod
accept_tos: Přijmout TOS
balance_left:
zero:
other: ~${time}
title: Název
summary: Souhrn
image: Obrázek na obálce
tags: Štítky
nsfw: Obsah NSFW
nsfw_description: Zde zkontrolujte, zda tento stream obsahuje nahotu nebo pornografický obsah.
error:
failed: Stream se nezdařil
connection_error: Chyba připojení
start_failed: Spuštění streamu se nezdařilo, zkontrolujte prosím zůstatek

View File

@ -9,6 +9,7 @@ no_user_found: Ingen bruger fundet
"@no_user_found":
description: Ingen bruger fundet ved søgning
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 seer
other: ${n:decimalPattern} seere
@ -124,6 +125,8 @@ settings:
disconnect_wallet: Afbryd forbindelsen til tegnebogen
connect_1tap: 1-Tap-forbindelse
paste: Indsæt URL
balance: Balance
name: Tegnebog
error:
logged_out: Kan ikke oprette forbindelse til wallet, når jeg er logget ud
nwc_auth_event_not_found: Ingen wallet-auth-begivenhed fundet
@ -134,3 +137,21 @@ login:
create: Opret konto
error:
invalid_key: Ugyldig nøgle
live:
start: GO LIVE
configure_stream: Konfigurer stream
endpoint: Slutpunkt
accept_tos: Accepter TOS
balance_left:
zero:
other: ~${time}
title: Titel
summary: Sammenfatning
image: Forsidebillede
tags: Tags
nsfw: NSFW-indhold
nsfw_description: Tjek her, om denne stream indeholder nøgenhed eller pornografisk indhold.
error:
failed: Strømmen mislykkedes
connection_error: Forbindelsesfejl
start_failed: Stream-start mislykkedes, tjek venligst din saldo

View File

@ -9,6 +9,7 @@ no_user_found: Kein Benutzer gefunden
"@no_user_found":
description: Kein Benutzer bei der Suche gefunden
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 Zuschauer
other: ${n:decimalPattern} Zuschauer
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Brieftasche abtrennen
connect_1tap: 1-Tap-Verbindung
paste: URL einfügen
balance: Bilanz
name: Brieftasche
error:
logged_out: Kann keine Verbindung zur Brieftasche herstellen, wenn ich abgemeldet bin
nwc_auth_event_not_found: Kein Wallet-Authentifizierungsereignis gefunden
@ -135,3 +138,22 @@ login:
create: Konto erstellen
error:
invalid_key: Ungültiger Schlüssel
live:
start: LIVE GEHEN
configure_stream: Stream konfigurieren
endpoint: Endpunkt
accept_tos: TOS akzeptieren
balance_left:
zero:
other: ~${time}
title: Titel
summary: Zusammenfassung
image: Titelbild
tags: Tags
nsfw: NSFW-Inhalt
nsfw_description: Prüfen Sie hier, ob dieser Stream Nacktheit oder
pornografische Inhalte enthält.
error:
failed: Stream fehlgeschlagen
connection_error: Verbindungsfehler
start_failed: Streamstart fehlgeschlagen, bitte überprüfen Sie Ihr Guthaben

View File

@ -9,6 +9,7 @@ no_user_found: Δεν βρέθηκε χρήστης
"@no_user_found":
description: Δεν βρέθηκε χρήστης κατά την αναζήτηση
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 θεατής
other: ${n:decimalPattern} θεατές
@ -127,6 +128,8 @@ settings:
disconnect_wallet: Αποσύνδεση πορτοφολιού
connect_1tap: Σύνδεση 1 βρύσης
paste: Επικόλληση URL
balance: Υπόλοιπο
name: Πορτοφόλι
error:
logged_out: Δεν μπορώ να συνδεθώ με πορτοφόλι όταν έχω αποσυνδεθεί
nwc_auth_event_not_found: Δεν βρέθηκε συμβάν εξουσιοδότησης πορτοφολιού
@ -137,3 +140,21 @@ login:
create: Δημιουργία λογαριασμού
error:
invalid_key: Μη έγκυρο κλειδί
live:
start: GO LIVE
configure_stream: Διαμόρφωση ροής
endpoint: Τελικό σημείο
accept_tos: Αποδοχή TOS
balance_left:
zero:
other: ~${time}
title: Τίτλος
summary: Περίληψη
image: Εικόνα εξωφύλλου
tags: Ετικέτες
nsfw: Περιεχόμενο NSFW
nsfw_description: Ελέγξτε εδώ αν αυτή η ροή περιέχει γυμνό ή πορνογραφικό περιεχόμενο.
error:
failed: Το ρεύμα απέτυχε
connection_error: Σφάλμα σύνδεσης
start_failed: Η εκκίνηση της ροής απέτυχε, παρακαλούμε ελέγξτε το υπόλοιπό σας

View File

@ -135,3 +135,21 @@ login:
create: Create Account
error:
invalid_key: Invalid key
live:
start: GO LIVE
configure_stream: Configure Stream
endpoint: Endpoint
accept_tos: Accept TOS
balance_left:
zero:
other: ~${time}
title: Title
summary: Summary
image: Cover Image
tags: Tags
nsfw: NSFW Content
nsfw_description: Check here if this stream contains nudity or pornographic content.
error:
failed: Stream failed
connection_error: Connection Error
start_failed: Stream start failed, please check your balance

View File

@ -9,6 +9,7 @@ no_user_found: No se ha encontrado ningún usuario
"@no_user_found":
description: No se ha encontrado ningún usuario al realizar la búsqueda
anon: Anónimo
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 espectador
other: ${n:decimalPattern} espectadores
@ -127,6 +128,8 @@ settings:
disconnect_wallet: Desconectar Cartera
connect_1tap: Conexión de 1 toma
paste: Pegar URL
balance: Saldo
name: Cartera
error:
logged_out: No se puede conectar el monedero al cerrar la sesión
nwc_auth_event_not_found: No se ha encontrado ningún evento de autenticación de cartera
@ -137,3 +140,21 @@ login:
create: Crear una cuenta
error:
invalid_key: Clave no válida
live:
start: EN VIVO
configure_stream: Configurar Stream
endpoint: Punto final
accept_tos: Aceptar TOS
balance_left:
zero:
other: ~${time}
title: Título
summary: Resumen
image: Imagen de portada
tags: Etiquetas
nsfw: Contenido NSFW
nsfw_description: Compruebe aquí si este flujo contiene desnudos o contenido pornográfico.
error:
failed: Corriente fallida
connection_error: Error de conexión
start_failed: Error en el inicio de la transmisión, compruebe su saldo

View File

@ -9,6 +9,7 @@ no_user_found: Käyttäjää ei löytynyt
"@no_user_found":
description: Käyttäjää ei löytynyt haun yhteydessä
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 katsoja
other: ${n:decimalPattern} katsojat
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Irrota lompakko
connect_1tap: 1-Tap-liitäntä
paste: Liitä URL-osoite
balance: Balance
name: Lompakko
error:
logged_out: Ei voi muodostaa yhteyttä lompakkoon, kun on kirjautunut ulos
nwc_auth_event_not_found: Ei lompakko-auth-tapahtumaa löydetty
@ -135,3 +138,22 @@ login:
create: Luo tili
error:
invalid_key: Virheellinen avain
live:
start: GO LIVE
configure_stream: Määritä Stream
endpoint: Loppupiste
accept_tos: Hyväksy TOS
balance_left:
zero:
other: ~${time}
title: Otsikko
summary: Yhteenveto
image: Kansikuva
tags: Tunnisteet
nsfw: NSFW-sisältö
nsfw_description: Tarkista täältä, jos tämä stream sisältää alastomuutta tai
pornografista sisältöä.
error:
failed: Stream epäonnistui
connection_error: Yhteysvirhe
start_failed: Virran käynnistys epäonnistui, tarkista saldosi

View File

@ -9,9 +9,10 @@ no_user_found: Aucun utilisateur trouvé
"@no_user_found":
description: Aucun utilisateur n'a été trouvé lors de la recherche
anon: Anonyme
full_amount_sats: "${n:decimalPattern} sats"
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":
@ -124,6 +125,8 @@ settings:
disconnect_wallet: Déconnecter le portefeuille
connect_1tap: Connexion à 1 robinet
paste: Coller l'URL
balance: Équilibre
name: Portefeuille
error:
logged_out: Impossible de se connecter au portefeuille lorsque l'on est déconnecté
nwc_auth_event_not_found: Aucun événement d'authentification de portefeuille n'a été trouvé
@ -134,3 +137,22 @@ login:
create: Créer un Compte
error:
invalid_key: Clé non valide
live:
start: GO LIVE
configure_stream: Configurer le flux
endpoint: Point final
accept_tos: Accepter les CGU
balance_left:
zero:
other: ~${time}
title: Titre
summary: Résumé
image: Image de couverture
tags: Tags
nsfw: Contenu NSFW
nsfw_description: Cochez cette case si ce flux contient de la nudité ou du
contenu pornographique.
error:
failed: Échec du flux
connection_error: Erreur de connexion
start_failed: Le démarrage du flux a échoué, veuillez vérifier votre solde

View File

@ -9,6 +9,7 @@ no_user_found: Nessun utente trovato
"@no_user_found":
description: Nessun utente trovato durante la ricerca
anon: Anonimo
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 spettatore
other: ${n:decimalPattern} spettatori
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Disconnettere il portafoglio
connect_1tap: Connessione a 1 rubinetto
paste: Incolla URL
balance: Equilibrio
name: Portafoglio
error:
logged_out: Impossibile connettere il portafoglio quando si è disconnessi
nwc_auth_event_not_found: Nessun evento wallet auth trovato
@ -135,3 +138,21 @@ login:
create: Crea un account
error:
invalid_key: Chiave non valida
live:
start: VAI IN DIRETTA
configure_stream: Configurare il flusso
endpoint: Punto finale
accept_tos: Accettare i TOS
balance_left:
zero:
other: ~${time}
title: Titolo
summary: Sintesi
image: Immagine di copertina
tags: Tag
nsfw: Contenuto NSFW
nsfw_description: Controllare qui se questo streaming contiene nudità o contenuti pornografici.
error:
failed: Flusso fallito
connection_error: Errore di connessione
start_failed: Avvio del flusso fallito, controllare il saldo

View File

@ -8,6 +8,7 @@ no_user_found: ユーザーが見つかりません
"@no_user_found":
description: 検索してもユーザーが見つからない
anon: 匿名
full_amount_sats: "${n:decimalPattern} サッツ"
viewers:
one: 1 視聴者
other: ${n:decimalPattern} 人が視聴中
@ -122,6 +123,8 @@ settings:
disconnect_wallet: ウォレットの切断
connect_1tap: 1タップ接続
paste: URLを貼り付ける
balance: バランス
name: 財布
error:
logged_out: ログアウト時にウォレットに接続できない
nwc_auth_event_not_found: ウォレットの認証イベントが見つかりません
@ -132,3 +135,21 @@ login:
create: アカウントを作成する
error:
invalid_key: 無効なキー
live:
start: ライブ中継
configure_stream: ストリームの設定
endpoint: エンドポイント
accept_tos: TOSを受け入れる
balance_left:
zero:
other: ~${time}
title: タイトル
summary: 概要
image: 表紙画像
tags: タグ
nsfw: NSFWコンテンツ
nsfw_description: このストリームにヌードやポルノが含まれている場合は、ここをチェックしてください。
error:
failed: ストリーム失敗
connection_error: 接続エラー
start_failed: ストリームの開始に失敗しました。

View File

@ -8,6 +8,7 @@ no_user_found: 사용자를 찾을 수 없습니다.
"@no_user_found":
description: 검색 시 사용자를 찾을 수 없음
anon: Anon
full_amount_sats: "${n:decimalPattern} sats"
viewers:
one: 시청자 1명
other: "{n:decimalPattern} 시청자"
@ -122,6 +123,8 @@ settings:
disconnect_wallet: 지갑 연결 해제
connect_1tap: 1-탭 연결
paste: URL 붙여넣기
balance: 잔액
name: 지갑
error:
logged_out: 로그아웃 시 지갑 연결 불가
nwc_auth_event_not_found: 지갑 인증 이벤트를 찾을 수 없습니다.
@ -132,3 +135,21 @@ login:
create: 계정 만들기
error:
invalid_key: 잘못된 키
live:
start: 라이브 시작하기
configure_stream: 스트림 구성
endpoint: 엔드포인트
accept_tos: TOS 수락
balance_left:
zero:
other: ~${time}
title: 제목
summary: 요약
image: 표지 이미지
tags: 태그
nsfw: NSFW 콘텐츠
nsfw_description: 이 스트림에 노출 또는 음란 콘텐츠가 포함되어 있는지 여기에서 확인하세요.
error:
failed: 스트림 실패
connection_error: 연결 오류
start_failed: 스트림 시작에 실패했습니다. 잔액을 확인해 주세요.

View File

@ -9,6 +9,7 @@ no_user_found: Geen gebruiker gevonden
"@no_user_found":
description: Geen gebruiker gevonden bij het zoeken
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 kijker
other: ${n:decimalPattern} kijkers
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Portefeuille loskoppelen
connect_1tap: 1-Tap Aansluiting
paste: URL plakken
balance: Saldo
name: Portemonnee
error:
logged_out: Kan geen verbinding maken met portemonnee als ik ben uitgelogd
nwc_auth_event_not_found: Geen portemonnee-auth-gebeurtenis gevonden
@ -135,3 +138,21 @@ login:
create: Account aanmaken
error:
invalid_key: Ongeldige sleutel
live:
start: LIVE GAAN
configure_stream: Stream configureren
endpoint: Eindpunt
accept_tos: TOS accepteren
balance_left:
zero:
other: ~${time}
title: Titel
summary: Samenvatting
image: Afbeelding omslag
tags: Tags
nsfw: NSFW-inhoud
nsfw_description: Controleer hier of deze stream naaktheid of pornografische inhoud bevat.
error:
failed: Stream mislukt
connection_error: Fout bij verbinding
start_failed: Stream start mislukt, controleer uw saldo

View File

@ -9,6 +9,7 @@ no_user_found: Nie znaleziono użytkownika
"@no_user_found":
description: Nie znaleziono użytkownika podczas wyszukiwania
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 przeglądarka
other: "{n:decimalPattern} widzów"
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Odłącz portfel
connect_1tap: Połączenie 1-wtykowe
paste: Wklej adres URL
balance: Równowaga
name: Portfel
error:
logged_out: Nie można połączyć portfela po wylogowaniu
nwc_auth_event_not_found: Nie znaleziono zdarzenia autoryzacji portfela
@ -135,3 +138,21 @@ login:
create: Utwórz konto
error:
invalid_key: Nieprawidłowy klucz
live:
start: GO LIVE
configure_stream: Konfiguracja strumienia
endpoint: Punkt końcowy
accept_tos: Zaakceptuj Regulamin
balance_left:
zero:
other: ~${time}
title: Tytuł
summary: Podsumowanie
image: Obraz na okładce
tags: Tagi
nsfw: Treści NSFW
nsfw_description: Sprawdź tutaj, czy ten stream zawiera nagość lub treści pornograficzne.
error:
failed: Strumień nie powiódł się
connection_error: Błąd połączenia
start_failed: Uruchomienie strumienia nie powiodło się, sprawdź saldo

View File

@ -9,6 +9,7 @@ no_user_found: Nenhum usuário encontrado
"@no_user_found":
description: Nenhum usuário foi encontrado durante a pesquisa
anon: Anônimo
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 visualizador
other: ${n:decimalPattern} espectadores
@ -125,6 +126,8 @@ settings:
disconnect_wallet: Desconectar carteira
connect_1tap: Conexão de 1 torneira
paste: Colar URL
balance: Equilíbrio
name: Carteira
error:
logged_out: Não consigo conectar a carteira quando estou desconectado
nwc_auth_event_not_found: Nenhum evento de autenticação de carteira encontrado
@ -135,3 +138,21 @@ login:
create: Criar Conta
error:
invalid_key: Chave inválida
live:
start: GO LIVE
configure_stream: Configurar fluxo
endpoint: Ponto final
accept_tos: Aceitar os Termos de Serviço
balance_left:
zero:
other: ~${time}
title: Título
summary: Resumo
image: Imagem da capa
tags: Tags
nsfw: Conteúdo NSFW
nsfw_description: Verifique aqui se essa transmissão contém nudez ou conteúdo pornográfico.
error:
failed: O fluxo falhou
connection_error: Erro de conexão
start_failed: Falha no início do fluxo, verifique seu saldo

View File

@ -9,6 +9,7 @@ no_user_found: Niciun utilizator găsit
"@no_user_found":
description: Nu s-a găsit niciun utilizator la căutare
anon: Anon
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 vizualizator
other: ${n:decimalPattern} telespectatori
@ -126,6 +127,8 @@ settings:
disconnect_wallet: Deconectați portofelul
connect_1tap: Conexiune 1-Tap
paste: Lipiți URL
balance: Echilibru
name: Portofel
error:
logged_out: Nu puteți conecta portofelul atunci când sunteți deconectat
nwc_auth_event_not_found: Nu a fost găsit niciun eveniment de autorizare a portofelului
@ -136,3 +139,21 @@ login:
create: Creare cont
error:
invalid_key: Cheie invalidă
live:
start: GO LIVE
configure_stream: Configurați fluxul
endpoint: Punct final
accept_tos: Acceptați TOS
balance_left:
zero:
other: ~${time}
title: Titlu
summary: Rezumat
image: Imagine de copertă
tags: Etichete
nsfw: Conținut NSFW
nsfw_description: Bifați aici dacă acest flux conține nuditate sau conținut pornografic.
error:
failed: Fluxul a eșuat
connection_error: Eroare de conectare
start_failed: Pornirea fluxului a eșuat, vă rugăm să verificați soldul

View File

@ -9,6 +9,7 @@ no_user_found: Пользователь не найден
"@no_user_found":
description: Пользователь не найден при поиске
anon: Аноним
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 зритель
other: ${n:decimalPattern} зрителей
@ -126,6 +127,8 @@ settings:
disconnect_wallet: Отключить кошелек
connect_1tap: 1-кратное соединение
paste: Вставить URL
balance: Баланс
name: Кошелек
error:
logged_out: Невозможно подключить кошелек при выходе из системы
nwc_auth_event_not_found: Событие аутентификации кошелька не найдено
@ -136,3 +139,22 @@ login:
create: Создать аккаунт
error:
invalid_key: Неверный ключ
live:
start: ПЕРЕЙТИ В ПРЯМОЙ ЭФИР
configure_stream: Настроить поток
endpoint: Конечная точка
accept_tos: Принять TOS
balance_left:
zero:
other: ~${time}
title: Название
summary: Резюме
image: Изображение на обложке
tags: Теги
nsfw: NSFW-контент
nsfw_description: Отметьте здесь, если этот поток содержит наготу или
порнографические материалы.
error:
failed: Сбой потока
connection_error: Ошибка подключения
start_failed: Запуск потока не удался, пожалуйста, проверьте баланс

View File

@ -9,6 +9,7 @@ no_user_found: Ingen användare hittades
"@no_user_found":
description: Ingen användare hittades vid sökning
anon: Anno
full_amount_sats: ${n:decimalPattern} sats
viewers:
one: 1 tittare
other: ${n:decimalPattern} tittare
@ -124,6 +125,8 @@ settings:
disconnect_wallet: Koppla bort plånboken
connect_1tap: 1-tryck anslutning
paste: Klistra in URL
balance: Balans
name: Plånbok
error:
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
@ -134,3 +137,21 @@ login:
create: Skapa konto
error:
invalid_key: Ogiltig nyckel
live:
start: GÅ DIREKT
configure_stream: Konfigurera ström
endpoint: Slutpunkt
accept_tos: Acceptera TOS
balance_left:
zero:
other: ~${time}
title: Titel
summary: Sammanfattning
image: Omslagsbild
tags: Etiketter
nsfw: NSFW-innehåll
nsfw_description: Markera här om denna stream innehåller nakenhet eller pornografiskt innehåll.
error:
failed: Strömmen misslyckades
connection_error: Anslutningsfel
start_failed: Stream start misslyckades, vänligen kontrollera ditt saldo

View File

@ -9,6 +9,7 @@ no_user_found: Користувача не знайдено
"@no_user_found":
description: Користувача не знайдено при пошуку
anon: Анонім.
full_amount_sats: ${n:decimalPattern} сатів
viewers:
one: 1 глядач
other: ${n:decimalPattern} глядачів
@ -126,6 +127,8 @@ settings:
disconnect_wallet: Відключити гаманець
connect_1tap: Підключення в 1 кран
paste: Вставити URL-адресу
balance: Баланс
name: Гаманець
error:
logged_out: Не вдається підключити гаманець, коли ви вийшли з системи
nwc_auth_event_not_found: Не знайдено жодної події авторизації гаманця
@ -136,3 +139,22 @@ login:
create: Створити обліковий запис
error:
invalid_key: Неправильний ключ
live:
start: GO LIVE
configure_stream: Налаштувати потік
endpoint: Кінцева точка
accept_tos: Прийміть ТЗ
balance_left:
zero:
other: ~${time}
title: Назва
summary: Підсумок
image: Зображення обкладинки
tags: Теги
nsfw: Нецензурна лексика
nsfw_description: Перевірте тут, чи містить цей потік оголену натуру або
порнографічний контент.
error:
failed: Потік не вдалося запустити
connection_error: Помилка з'єднання
start_failed: Не вдалося запустити трансляцію, будь ласка, перевірте свій баланс

View File

@ -8,6 +8,7 @@ no_user_found: 未找到使用者
"@no_user_found":
description: 搜尋時未找到使用者
anon: 匿名
full_amount_sats: ${n:decimalPattern} Sats
viewers:
one: 1 個檢視器
other: ${n:decimalPattern} 觀眾
@ -122,6 +123,8 @@ settings:
disconnect_wallet: 斷開錢包
connect_1tap: 1 抽頭連接
paste: 貼上 URL
balance: 平衡
name: 錢包
error:
logged_out: 登出時無法連接錢包
nwc_auth_event_not_found: 未找到錢包認證事件
@ -132,3 +135,21 @@ login:
create: 創建帳戶
error:
invalid_key: 無效按鍵
live:
start: 開始直播
configure_stream: 設定串流
endpoint: 終點
accept_tos: 接受服務條款
balance_left:
zero:
other: ~${time}
title: 標題
summary: 摘要
image: 封面圖片
tags: 標籤
nsfw: NSFW 內容
nsfw_description: 請檢查此串流是否包含裸體或色情內容。
error:
failed: 串流失敗
connection_error: 連線錯誤
start_failed: 串流啟動失敗,請檢查您的餘額

View File

@ -83,6 +83,7 @@ class LoginAccount {
final String? privateKey;
final List<String>? signerRelays;
final WalletConfig? wallet;
final String? streamEndpoint;
SimpleWallet? _cachedWallet;
@ -92,6 +93,7 @@ class LoginAccount {
this.privateKey,
this.signerRelays,
this.wallet,
this.streamEndpoint,
});
static LoginAccount nip19(String key) {
@ -139,6 +141,7 @@ class LoginAccount {
"pubKey": acc?.pubkey,
"privateKey": acc?.privateKey,
"wallet": acc?.wallet?.toJson(),
"streamEndpoint": acc?.streamEndpoint,
};
static LoginAccount? fromJson(Map<String, dynamic> json) {
@ -162,6 +165,7 @@ class LoginAccount {
json.containsKey("wallet") && json["wallet"] != null
? WalletConfig.fromJson(json["wallet"])
: null,
streamEndpoint: json["streamEndpoint"],
);
}
return null;
@ -215,4 +219,21 @@ class LoginData extends ValueNotifier<LoginAccount?> {
}
}
}
void configure({
List<String>? signerRelays,
WalletConfig? wallet,
String? streamEndpoint,
}) {
if (value != null) {
value = LoginAccount(
type: value!.type,
pubkey: value!.pubkey,
privateKey: value!.privateKey,
signerRelays: signerRelays ?? value!.signerRelays,
wallet: wallet,
streamEndpoint: streamEndpoint ?? value!.streamEndpoint,
);
}
}
}

429
lib/pages/live.dart Normal file
View File

@ -0,0 +1,429 @@
import 'dart:async';
import 'dart:developer' as developer;
import 'package:apivideo_live_stream/apivideo_live_stream.dart';
import 'package:collection/collection.dart';
import 'package:duration/duration.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:ndk/ndk.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:zap_stream_flutter/api.dart';
import 'package:zap_stream_flutter/const.dart';
import 'package:zap_stream_flutter/i18n/strings.g.dart';
import 'package:zap_stream_flutter/rx_filter.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/button.dart';
import 'package:zap_stream_flutter/widgets/chat.dart';
import 'package:zap_stream_flutter/widgets/pill.dart';
import 'package:zap_stream_flutter/widgets/stream_config.dart';
Future<bool?> showExitStreamDialog(BuildContext context) {
return showDialog<bool>(
context: context,
barrierDismissible: false,
useRootNavigator: false,
builder: (context) {
return Dialog(
child: Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
spacing: 16,
children: [
Text("Exit live stream?", style: TextStyle(fontSize: 24)),
Row(
spacing: 16,
children: [
Flexible(
child: BasicButton.text(
"Yes, stop stream",
onTap: (context) => context.pop(true),
),
),
Flexible(
child: BasicButton.text(
"No",
onTap: (context) => context.pop(false),
),
),
],
),
],
),
),
);
},
);
}
class LivePage extends StatefulWidget {
const LivePage({super.key});
@override
State<StatefulWidget> createState() => _LivePage();
}
class _LivePage extends State<LivePage>
implements ApiVideoLiveStreamEventsListener {
late final ApiVideoLiveStreamController _controller;
late final ZapStreamApi _api;
AccountInfo? _account;
late final Timer _accountTimer;
bool _streaming = false;
Future<void> _reloadAccount() async {
final info = await _api.getAccountInfo();
setState(() {
_account = info;
});
}
@override
void initState() {
_controller = ApiVideoLiveStreamController(
initialAudioConfig: AudioConfig(),
initialVideoConfig: VideoConfig.withDefaultBitrate(),
);
_controller.initialize();
_api = ZapStreamApi.instance();
_reloadAccount();
_accountTimer = Timer.periodic(Duration(seconds: 30), (_) async {
await _reloadAccount();
});
_controller.addEventsListener(this);
WakelockPlus.enable();
super.initState();
}
@override
void dispose() {
_accountTimer.cancel();
_controller.stopStreaming();
_controller.dispose();
WakelockPlus.disable();
super.dispose();
}
void _showError(BuildContext context, String msg, {Exception? error}) {
if (error != null) {
developer.log(error.toString());
}
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: WARNING,
content: Text(msg, style: TextStyle(fontWeight: FontWeight.bold)),
),
);
}
String _calcTimeRemaining(IngestEndpoint endpoint, double balance) {
if (endpoint.cost.rate == 0) {
return "";
}
final units = balance / endpoint.cost.rate;
if (endpoint.cost.unit == "min") {
return Duration(
seconds: (units * 60).clamp(0, double.infinity).floor(),
).pretty(abbreviated: true);
}
return "0s";
}
@override
Widget build(BuildContext context) {
final mq = MediaQuery.of(context);
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) async {
if (_streaming) {
final go = await showExitStreamDialog(context);
if (context.mounted) {
if (go == true) {
context.go("/");
}
}
} else {
context.go("/");
}
},
child: ValueListenableBuilder(
valueListenable: loginData,
builder: (context, state, _) {
final endpoint = _account?.endpoints.firstWhereOrNull(
(e) => e.name == state?.streamEndpoint,
);
final balance = _account?.balance ?? 0;
return RxFilter<Nip01Event>(
Key("live-stream"),
filters: [
Filter(
kinds: [30_311],
limit: 100,
pTags: [loginData.value!.pubkey],
),
Filter(
kinds: [30_311],
limit: 100,
authors: [loginData.value!.pubkey],
),
],
builder: (context, streamState) {
final ev = streamState
?.sortedBy((e) => e.createdAt)
.firstWhereOrNull((e) => e.getFirstTag("status") == "live");
final stream = ev != null ? StreamEvent(ev) : null;
return Stack(
children: [
ApiVideoCameraPreview(controller: _controller),
Positioned(
top: 10,
left: 10,
width: mq.size.width - 20,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PillWidget(
color: LAYER_2,
child: Row(
spacing: 4,
children: [
Text(t.full_amount_sats(n: balance)),
if (endpoint != null)
Text(
t.live.balance_left(
n: endpoint.cost.rate,
time: _calcTimeRemaining(endpoint, balance),
),
style: TextStyle(color: LAYER_5),
),
],
),
),
if ((stream?.info.participants ?? 0) > 0)
PillWidget(
color: LAYER_2,
child: Text(
t.viewers(n: stream?.info.participants ?? 0),
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
),
),
],
),
),
if (_account != null)
Positioned(
width: mq.size.width,
bottom: 15,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton.filled(
iconSize: 40,
style: ButtonStyle(
iconColor: WidgetStateColor.resolveWith(
(_) => FONT_COLOR,
),
backgroundColor: WidgetStateColor.resolveWith(
(_) => LAYER_3,
),
),
onPressed: () {
_controller.switchCamera();
},
icon: Icon(Icons.cameraswitch_rounded),
),
Spacer(),
if (_account != null && !_account!.tos.accepted)
Column(
spacing: 16,
children: [
BasicButton.text(
"Read TOS",
onTap: (context) {
if (_account?.tos.link != null) {
launchUrl(Uri.parse(_account!.tos.link!));
}
},
),
BasicButton.text(
t.live.accept_tos,
color: WARNING,
onTap: (context) {
_api
.acceptTos()
.then((_) {
_reloadAccount();
})
.catchError((e) {
_showError(
context,
e.toString(),
error: e,
);
});
},
),
],
)
else if (state?.streamEndpoint == null ||
endpoint == null)
BasicButton.text(
t.live.configure_stream,
color: WARNING,
),
if (endpoint != null)
IconButton.filled(
iconSize: 40,
style: ButtonStyle(
iconColor: WidgetStateColor.resolveWith(
(_) => WARNING,
),
backgroundColor: WidgetStateColor.resolveWith(
(_) => LAYER_3,
),
),
onPressed: () async {
if (_streaming) {
_controller.stopStreaming().catchError((e) {
_showError(context, e.toString(), error: e);
});
} else {
_controller
.startStreaming(
streamKey: endpoint.key,
url: endpoint.url,
)
.catchError((e) {
_showError(
context,
t.live.error.start_failed,
error: e,
);
});
}
},
icon: Icon(
_streaming ? Icons.stop : Icons.circle,
),
),
Spacer(),
IconButton.filled(
iconSize: 40,
style: ButtonStyle(
iconColor: WidgetStateColor.resolveWith(
(_) => FONT_COLOR,
),
backgroundColor: WidgetStateColor.resolveWith(
(_) => LAYER_3,
),
),
onPressed: () {
showModalBottomSheet(
context: context,
constraints: BoxConstraints.expand(),
builder: (context) {
return StreamConfigWidget(
api: _api,
account: _account!,
hideEndpointConfig: _streaming,
);
},
).then((_) {
_reloadAccount();
});
},
icon: Icon(Icons.settings),
),
],
),
),
if (_account != null && stream != null)
Positioned(
bottom: 80,
child: Container(
width: mq.size.width,
padding: EdgeInsets.symmetric(horizontal: 10),
constraints: BoxConstraints(
maxHeight: mq.size.height * 0.3,
minHeight: 200,
),
child: ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.white.withAlpha(255),
Colors.white.withAlpha(200),
Colors.white.withAlpha(0),
],
stops: [0.0, 0.7, 1.0],
).createShader(bounds);
},
blendMode: BlendMode.dstIn,
child: ChatWidget(
stream: stream,
showGoals: false,
showTopZappers: false,
),
),
),
),
],
);
},
);
},
),
);
}
@override
get onConnectionFailed => (s) {
developer.log(s, name: "onConnectionFailed");
_showError(context, t.live.error.connection_error);
};
@override
get onConnectionSuccess => () {
developer.log("Connected", name: "onConnectionSuccess");
setState(() {
_streaming = true;
});
};
@override
get onDisconnection => () {
developer.log("Disconnected", name: "onDisconnection");
setState(() {
_streaming = false;
});
};
@override
get onError => (e) {
developer.log(e.toString(), name: "onError");
if (e is PlatformException) {
if (e.details is String &&
(e.details as String).contains("Connection error")) {
_showError(context, t.live.error.connection_error, error: e);
}
}
};
@override
get onVideoSizeChanged => (s) {
developer.log(s.toString(), name: "onVideoSizeChanged");
};
}

View File

@ -38,6 +38,7 @@ class _NewAccountPage extends State<NewAccountPage> {
pubKey: _privateKey.publicKey,
name: _name.text,
picture: _avatar,
lud16: "${_privateKey.publicKey}@zap.stream",
),
);
}

View File

@ -12,6 +12,7 @@ import 'package:zap_stream_flutter/widgets/button.dart';
import 'package:zap_stream_flutter/widgets/button_follow.dart';
import 'package:zap_stream_flutter/widgets/header.dart';
import 'package:zap_stream_flutter/widgets/nostr_text.dart';
import 'package:zap_stream_flutter/widgets/notifications_button.dart';
import 'package:zap_stream_flutter/widgets/profile.dart';
import 'package:zap_stream_flutter/widgets/stream_grid.dart';
@ -91,7 +92,14 @@ class ProfilePage extends StatelessWidget {
),
],
),
if (!isMe) FollowButton(pubkey: hexPubkey),
if (!isMe)
Row(
spacing: 8,
children: [
FollowButton(pubkey: hexPubkey),
NotificationsButtonWidget(pubkey: hexPubkey),
],
),
Text(
t.profile.past_streams,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),

View File

@ -100,13 +100,7 @@ class _Inner extends State<SettingsWalletPage> with ProtocolListener {
}
_setWallet(WalletConfig? cfg) {
loginData.value = LoginAccount(
type: loginData.value!.type,
pubkey: loginData.value!.pubkey,
privateKey: loginData.value!.privateKey,
signerRelays: loginData.value!.signerRelays,
wallet: cfg,
);
loginData.configure(wallet: cfg);
}
@override

View File

@ -144,10 +144,8 @@ class _StreamPage extends State<StreamPage> with RouteAware {
? MainVideoPlayerWidget(
url: stream.info.stream!,
placeholder: stream.info.image,
aspectRatio: 16 / 9,
isLive: true,
title: stream.info.title,
)
: (stream.info.image?.isNotEmpty ?? false)
? ProxyImg(url: stream.info.image)
@ -161,7 +159,7 @@ class _StreamPage extends State<StreamPage> with RouteAware {
ProfileWidget.pubkey(
stream.info.host,
children: [
NotificationsButtonWidget(stream: widget.stream),
NotificationsButtonWidget(pubkey: widget.stream.info.host),
BasicButton(
Row(
children: [Icon(Icons.bolt, size: 14), Text(t.zap.button_zap)],

View File

@ -375,14 +375,6 @@ Map<String, TopZaps> topZapReceiver(Iterable<ZapReceipt> zaps) {
);
}
String formatSecondsToHHMMSS(int seconds) {
int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60;
int remainingSeconds = seconds % 60;
return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
}
String bech32ToHex(String bech32) {
final decoder = Bech32Decoder();
final data = decoder.convert(bech32, 10_000);

View File

@ -3,6 +3,7 @@ import 'package:zap_stream_flutter/theme.dart';
class BasicButton extends StatelessWidget {
final Widget? child;
final Color? color;
final BoxDecoration? decoration;
final EdgeInsetsGeometry? padding;
final EdgeInsetsGeometry? margin;
@ -12,6 +13,7 @@ class BasicButton extends StatelessWidget {
const BasicButton(
this.child, {
super.key,
this.color,
this.decoration,
this.padding,
this.margin,
@ -21,6 +23,7 @@ class BasicButton extends StatelessWidget {
static Widget text(
String text, {
Color? color,
BoxDecoration? decoration,
EdgeInsetsGeometry? padding,
EdgeInsetsGeometry? margin,
@ -46,6 +49,7 @@ class BasicButton extends StatelessWidget {
),
),
disabled: disabled,
color: color,
decoration: decoration,
padding: padding ?? EdgeInsets.symmetric(vertical: 4, horizontal: 12),
margin: margin,
@ -55,12 +59,17 @@ class BasicButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(
!(color != null && decoration != null),
"Cant set both 'color' and 'decoration'",
);
final defaultBr = BorderRadius.all(Radius.circular(100));
final inner = Container(
padding: padding,
margin: margin,
decoration:
decoration ?? BoxDecoration(color: LAYER_2, borderRadius: defaultBr),
decoration ??
BoxDecoration(color: color ?? LAYER_2, borderRadius: defaultBr),
child: Center(child: child),
);
return GestureDetector(

View File

@ -18,8 +18,17 @@ import 'package:zap_stream_flutter/widgets/profile.dart';
class ChatWidget extends StatelessWidget {
final StreamEvent stream;
final bool? showGoals;
final bool? showTopZappers;
final bool? showRaids;
const ChatWidget({super.key, required this.stream});
const ChatWidget({
super.key,
required this.stream,
this.showGoals,
this.showTopZappers,
this.showRaids,
});
@override
Widget build(BuildContext context) {
@ -31,7 +40,8 @@ class ChatWidget extends StatelessWidget {
var filters = [
Filter(kinds: [1311, 9735], limit: 200, aTags: [stream.aTag]),
Filter(kinds: [1312, 1313], limit: 200, aTags: [stream.aTag]),
if (showRaids ?? true)
Filter(kinds: [1312, 1313], limit: 200, aTags: [stream.aTag]),
Filter(kinds: [Nip51List.kMute], authors: moderators),
Filter(kinds: [1314], authors: moderators),
Filter(kinds: [8], authors: [stream.info.host]),
@ -108,10 +118,13 @@ class ChatWidget extends StatelessWidget {
spacing: 8,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (zaps.isNotEmpty) _TopZappersWidget(events: zaps),
if (stream.info.goal != null) GoalWidget.id(stream.info.goal!),
if (zaps.isNotEmpty && (showTopZappers ?? true))
_TopZappersWidget(events: zaps),
if (stream.info.goal != null && (showGoals ?? true))
GoalWidget.id(stream.info.goal!),
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(top: 80),
reverse: true,
itemCount: filteredChat.length,
itemBuilder: (ctx, idx) {

View File

@ -24,6 +24,7 @@ class __WriteMessageWidget extends State<WriteMessageWidget> {
OverlayEntry? _entry;
late FocusNode _focusNode;
List<List<String>> _tags = List.empty(growable: true);
final GlobalKey _positioned = GlobalKey();
@override
void initState() {
@ -69,7 +70,8 @@ class __WriteMessageWidget extends State<WriteMessageWidget> {
_entry = null;
}
final pos = context.findRenderObject() as RenderBox?;
final pos = _positioned.currentContext!.findRenderObject() as RenderBox?;
final posGlobal = pos?.localToGlobal(Offset.zero);
_entry = OverlayEntry(
builder: (context) {
return ValueListenableBuilder(
@ -85,12 +87,13 @@ class __WriteMessageWidget extends State<WriteMessageWidget> {
if (search.isEmpty) {
return SizedBox();
}
final mq = MediaQuery.of(context);
return Stack(
children: [
Positioned(
left: 0,
bottom: (pos?.paintBounds.bottom ?? 0),
width: MediaQuery.of(context).size.width,
left: posGlobal?.dx,
bottom: mq.size.height - (posGlobal?.dy ?? 0) - 30,
width: pos?.size.width,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 8),
decoration: BoxDecoration(
@ -162,15 +165,17 @@ class __WriteMessageWidget extends State<WriteMessageWidget> {
_entry = null;
}
final pos = context.findRenderObject() as RenderBox?;
final pos = _positioned.currentContext!.findRenderObject() as RenderBox?;
final posGlobal = pos?.localToGlobal(Offset.zero);
_entry = OverlayEntry(
builder: (context) {
final mq = MediaQuery.of(context);
return Stack(
children: [
Positioned(
left: 0,
bottom: (pos?.paintBounds.bottom ?? 0),
width: MediaQuery.of(context).size.width,
left: posGlobal?.dx,
bottom: mq.size.height - (posGlobal?.dy ?? 0) - 30,
width: pos?.size.width,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 8),
decoration: BoxDecoration(
@ -239,9 +244,13 @@ class __WriteMessageWidget extends State<WriteMessageWidget> {
final isLogin = ndk.accounts.isLoggedIn;
return Container(
key: _positioned,
margin: EdgeInsets.fromLTRB(4, 8, 4, 0),
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: LAYER_2, borderRadius: DEFAULT_BR),
decoration: BoxDecoration(
color: LAYER_2.withAlpha(200),
borderRadius: DEFAULT_BR,
),
child:
canSign
? Row(

View File

@ -6,6 +6,7 @@ import 'package:zap_stream_flutter/i18n/strings.g.dart';
import 'package:zap_stream_flutter/const.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/widgets/avatar.dart';
import 'package:zap_stream_flutter/widgets/button.dart';
class HeaderWidget extends StatefulWidget {
const HeaderWidget({super.key});
@ -39,12 +40,36 @@ class LoginButtonWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (ndk.accounts.isLoggedIn) {
return GestureDetector(
onTap:
() => context.go(
"/p/${Nip19.encodePubKey(ndk.accounts.getPublicKey()!)}",
return Row(
spacing: 8,
children: [
BasicButton(
padding: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
border: Border.all(color: WARNING),
borderRadius: DEFAULT_BR,
),
child: AvatarWidget.pubkey(ndk.accounts.getPublicKey()!),
Row(
spacing: 4,
children: [
Icon(Icons.videocam),
Text(
t.live.start,
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
onTap: (context) => context.push("/live"),
),
GestureDetector(
onTap:
() => context.push(
"/p/${Nip19.encodePubKey(ndk.accounts.getPublicKey()!)}",
),
child: AvatarWidget.pubkey(ndk.accounts.getPublicKey()!),
),
],
);
} else {
return GestureDetector(
@ -59,10 +84,7 @@ class LoginButtonWidget extends StatelessWidget {
),
child: Row(
spacing: 8,
children: [
Text(t.button.login),
Icon(Icons.login, size: 16),
],
children: [Text(t.button.login), Icon(Icons.login, size: 16)],
),
),
);

View File

@ -1,7 +1,7 @@
import 'dart:async';
import 'package:duration/duration.dart';
import 'package:flutter/material.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
import 'package:zap_stream_flutter/widgets/pill.dart';
class LiveTimerWidget extends StatefulWidget {
@ -37,12 +37,13 @@ class _LiveTimerWidget extends State<LiveTimerWidget> {
return PillWidget(
color: LAYER_2,
child: Text(
formatSecondsToHHMMSS(
((DateTime.now().millisecondsSinceEpoch -
widget.started.millisecondsSinceEpoch) /
1000)
.toInt(),
),
Duration(
seconds:
((DateTime.now().millisecondsSinceEpoch -
widget.started.millisecondsSinceEpoch) /
1000)
.toInt(),
).pretty(abbreviated: true),
),
);
}

View File

@ -1,12 +1,11 @@
import 'package:flutter/material.dart';
import 'package:zap_stream_flutter/notifications.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/utils.dart';
class NotificationsButtonWidget extends StatefulWidget {
final StreamEvent stream;
final String pubkey;
const NotificationsButtonWidget({super.key, required this.stream});
const NotificationsButtonWidget({super.key, required this.pubkey});
@override
State<StatefulWidget> createState() => _NotificationsButtonWidget();
@ -18,9 +17,7 @@ class _NotificationsButtonWidget extends State<NotificationsButtonWidget> {
return ValueListenableBuilder(
valueListenable: notifications,
builder: (context, state, _) {
final isNotified = (state?.notifyKeys ?? []).contains(
widget.stream.info.host,
);
final isNotified = (state?.notifyKeys ?? []).contains(widget.pubkey);
return IconButton(
iconSize: 20,
onPressed: () async {
@ -28,9 +25,9 @@ class _NotificationsButtonWidget extends State<NotificationsButtonWidget> {
if (n == null) return;
if (isNotified) {
await n.removeWatchPubkey(widget.stream.info.host);
await n.removeWatchPubkey(widget.pubkey);
} else {
await n.watchPubkey(widget.stream.info.host, [30311]);
await n.watchPubkey(widget.pubkey, [30311]);
}
await notifications.reload();
},

View File

@ -0,0 +1,174 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:zap_stream_flutter/api.dart';
import 'package:zap_stream_flutter/const.dart';
import 'package:zap_stream_flutter/i18n/strings.g.dart';
import 'package:zap_stream_flutter/theme.dart';
import 'package:zap_stream_flutter/widgets/button.dart';
import 'package:zap_stream_flutter/widgets/pill.dart';
class StreamConfigWidget extends StatefulWidget {
final ZapStreamApi api;
final AccountInfo account;
final bool? hideEndpointConfig;
const StreamConfigWidget({
super.key,
required this.api,
required this.account,
this.hideEndpointConfig,
});
@override
State<StatefulWidget> createState() => _StreamConfigWidget();
}
class _StreamConfigWidget extends State<StreamConfigWidget> {
late bool _nsfw;
late final TextEditingController _title;
late final TextEditingController _summary;
late final TextEditingController _tags;
@override
void initState() {
_title = TextEditingController(text: widget.account.details?.title);
_summary = TextEditingController(text: widget.account.details?.summary);
_tags = TextEditingController(
text: widget.account.details?.tags?.join(",") ?? "irl",
);
_nsfw = widget.account.details?.contentWarning?.isNotEmpty ?? false;
super.initState();
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: loginData,
builder: (context, state, _) {
final endpoint = widget.account.endpoints.firstWhereOrNull(
(e) => e.name == state?.streamEndpoint,
);
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Text(t.live.configure_stream, style: TextStyle(fontSize: 24)),
if (!(widget.hideEndpointConfig ?? false))
Row(
spacing: 8,
children: [
Icon(Icons.power),
Expanded(
child: DropdownButton<IngestEndpoint>(
value: endpoint,
hint: Text(t.live.endpoint),
items:
widget.account.endpoints
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(e.name),
),
)
.toList(),
onChanged: (x) {
if (x != null) {
loginData.configure(streamEndpoint: x.name);
}
},
),
),
if (endpoint != null)
Text(
"${t.full_amount_sats(n: endpoint.cost.rate)}/${endpoint.cost.unit}",
),
],
),
if (endpoint != null && !(widget.hideEndpointConfig ?? false))
Row(
spacing: 8,
children:
endpoint.capabilities
.map(
(e) => PillWidget(color: LAYER_3, child: Text(e)),
)
.toList(),
),
TextField(
controller: _title,
decoration: InputDecoration(labelText: t.live.title),
),
TextField(
controller: _summary,
decoration: InputDecoration(labelText: t.live.summary),
minLines: 3,
maxLines: 5,
),
GestureDetector(
onTap: () {
setState(() {
_nsfw = !_nsfw;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: WARNING),
borderRadius: DEFAULT_BR,
),
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Checkbox(
value: _nsfw,
onChanged: (v) {
setState(() {
_nsfw = !_nsfw;
});
},
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
t.live.nsfw,
style: TextStyle(
color: WARNING,
fontWeight: FontWeight.bold,
),
),
Text(t.live.nsfw_description),
],
),
),
],
),
),
),
BasicButton.text(
t.button.save,
onTap: (context) async {
await widget.api.updateDefaultStreamInfo(
title: _title.text,
summary: _summary.text,
contentWarning: _nsfw ? "nsfw" : null,
tags: _tags.text.split(","),
);
if (context.mounted) {
context.pop();
}
},
),
],
),
);
},
);
}
}

View File

@ -17,6 +17,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.0.9"
apivideo_live_stream:
dependency: "direct main"
description:
name: apivideo_live_stream
sha256: f873f8cdd3e35838d6e32ce55c1963f8889b9bfccf4a37f9ed86cfe79512b309
url: "https://pub.dev"
source: hosted
version: "1.2.0"
archive:
dependency: transitive
description:
@ -45,10 +53,10 @@ packages:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.12.0"
version: "2.13.0"
audio_service:
dependency: "direct main"
description:
@ -294,10 +302,10 @@ packages:
dependency: transitive
description:
name: fake_async
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.2"
version: "1.3.3"
ffi:
dependency: transitive
description:
@ -326,10 +334,10 @@ packages:
dependency: transitive
description:
name: file_selector_macos
sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc"
sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711"
url: "https://pub.dev"
source: hosted
version: "0.9.4+2"
version: "0.9.4+3"
file_selector_platform_interface:
dependency: transitive
description:
@ -504,10 +512,10 @@ packages:
dependency: transitive
description:
name: flutter_rust_bridge
sha256: "35c257fc7f98e34c1314d6c145e5ed54e7c94e8a9f469947e31c9298177d546f"
sha256: b416ff56002789e636244fb4cc449f587656eff995e5a7169457eb0593fcaddb
url: "https://pub.dev"
source: hosted
version: "2.7.0"
version: "2.10.0"
flutter_secure_storage:
dependency: "direct main"
description:
@ -690,10 +698,10 @@ packages:
dependency: "direct main"
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.dev"
source: hosted
version: "0.19.0"
version: "0.20.2"
js:
dependency: transitive
description:
@ -714,10 +722,10 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.dev"
source: hosted
version: "10.0.8"
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
@ -798,41 +806,50 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
native_device_orientation:
dependency: transitive
description:
name: native_device_orientation
sha256: "744a03030fad5a332a54833cd34f1e2ee51ae9acf477b4ef85bacc8823af9937"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
ndk:
dependency: "direct main"
description:
path: "packages/ndk"
ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
resolved-ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
resolved-ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
url: "https://github.com/relaystr/ndk"
source: git
version: "0.3.2"
version: "0.4.0"
ndk_amber:
dependency: "direct main"
description:
path: "packages/amber"
ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
resolved-ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
resolved-ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
url: "https://github.com/relaystr/ndk"
source: git
version: "0.3.0"
version: "0.3.1"
ndk_objectbox:
dependency: "direct main"
description:
path: "packages/objectbox"
ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
resolved-ref: "6242899ee4ff7f65e57518d4eb29e2a253b3c4da"
ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
resolved-ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
url: "https://github.com/relaystr/ndk"
source: git
version: "0.2.3"
version: "0.2.4"
ndk_rust_verifier:
dependency: "direct main"
description:
name: ndk_rust_verifier
sha256: f82d536042634ad3bb1c1af0afd59abd149e7544e88697ef14302f7e170581b7
url: "https://pub.dev"
source: hosted
version: "0.3.1"
path: "packages/rust_verifier"
ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
resolved-ref: "00eee5460ca478a02ec9a91c0a6100f2e50eddce"
url: "https://github.com/relaystr/ndk"
source: git
version: "0.4.0"
nested:
dependency: transitive
description:
@ -845,18 +862,18 @@ packages:
dependency: transitive
description:
name: objectbox
sha256: a07f93ea6b6a7c6cfe2efce743e12842ccd876d92dc6b6da532cc5221c507ef0
sha256: "25c2e24b417d938decb5598682dc831bc6a21856eaae65affbc57cfad326808d"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
version: "4.3.0"
objectbox_flutter_libs:
dependency: transitive
description:
name: objectbox_flutter_libs
sha256: "43b2b86b61aa4a6ef9e3b44d3cc09471586975d100c6620ef22960e490c9bcd5"
sha256: "574b0233ba79a7159fca9049c67974f790a2180b6141d4951112b20bd146016a"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
version: "4.3.0"
octo_image:
dependency: transitive
description:
@ -1061,10 +1078,10 @@ packages:
dependency: transitive
description:
name: rust_lib_ndk
sha256: "47dcfda62051315e869256c705e7c1c07649772d849eaad0474df11b10a2e1b0"
sha256: f06a1a47c6fbadf25250eac796b65b91ea99797b6377304abb152f06205c28ff
url: "https://pub.dev"
source: hosted
version: "0.1.5"
version: "0.1.7"
rxdart:
dependency: "direct main"
description:
@ -1154,10 +1171,10 @@ packages:
dependency: "direct main"
description:
name: slang
sha256: "13132690084bef34fb74dbc698a1e5496f97afbcd3eb58e20c09393e77ac46e6"
sha256: "6668a08355b370d5cb5446fc869c4492ed23c6433934fe88228876460fedac22"
url: "https://pub.dev"
source: hosted
version: "4.7.1"
version: "4.7.2"
slang_flutter:
dependency: "direct main"
description:
@ -1386,10 +1403,10 @@ packages:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
sha256: "557a315b7d2a6dbb0aaaff84d857967ce6bdc96a63dc6ee2a57ce5a6ee5d3331"
url: "https://pub.dev"
source: hosted
version: "1.1.16"
version: "1.1.17"
vector_math:
dependency: transitive
description:
@ -1410,10 +1427,10 @@ packages:
dependency: transitive
description:
name: video_player_android
sha256: "28dcc4122079f40f93a0965b3679aff1a5f4251cf79611bd8011f937eb6b69de"
sha256: "4a5135754a62dbc827a64a42ef1f8ed72c962e191c97e2d48744225c2b9ebb73"
url: "https://pub.dev"
source: hosted
version: "2.8.4"
version: "2.8.7"
video_player_avfoundation:
dependency: transitive
description:
@ -1442,10 +1459,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "14.3.1"
version: "15.0.0"
wakelock_plus:
dependency: "direct main"
description:
@ -1498,10 +1515,10 @@ packages:
dependency: transitive
description:
name: web_socket_client
sha256: "0ec5230852349191188c013112e4d2be03e3fc83dbe80139ead9bf3a136e53b5"
sha256: "394789177aa3bc1b7b071622a1dbf52a4631d7ce23c555c39bb2523e92316b07"
url: "https://pub.dev"
source: hosted
version: "0.1.5"
version: "0.2.1"
win32:
dependency: transitive
description:
@ -1552,4 +1569,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.7.2 <4.0.0"
flutter: ">=3.27.1"
flutter: ">=3.32.0"

View File

@ -1,7 +1,7 @@
name: zap_stream_flutter
description: "zap.stream"
publish_to: "none"
version: 1.0.0+13
version: 1.1.0+14
environment:
sdk: ^3.7.2
@ -36,7 +36,7 @@ dependencies:
duration: ^4.0.3
slang: ^4.7.1
slang_flutter: ^4.7.0
intl: ^0.19.0
intl: ^0.20.2
flutter_localizations:
sdk: flutter
firebase_core: ^3.13.1
@ -46,23 +46,29 @@ dependencies:
flutter_dotenv: ^5.2.1
protocol_handler: ^0.2.0
audio_service: ^0.18.18
apivideo_live_stream: ^1.2.0
dependency_overrides:
ndk:
git:
url: https://github.com/relaystr/ndk
path: packages/ndk
ref: 6242899ee4ff7f65e57518d4eb29e2a253b3c4da
ref: 00eee5460ca478a02ec9a91c0a6100f2e50eddce
ndk_objectbox:
git:
url: https://github.com/relaystr/ndk
path: packages/objectbox
ref: 6242899ee4ff7f65e57518d4eb29e2a253b3c4da
ref: 00eee5460ca478a02ec9a91c0a6100f2e50eddce
ndk_amber:
git:
url: https://github.com/relaystr/ndk
path: packages/amber
ref: 6242899ee4ff7f65e57518d4eb29e2a253b3c4da
ref: 00eee5460ca478a02ec9a91c0a6100f2e50eddce
ndk_rust_verifier:
git:
url: https://github.com/relaystr/ndk
path: packages/rust_verifier
ref: 00eee5460ca478a02ec9a91c0a6100f2e50eddce
emoji_picker_flutter:
git:
url: https://github.com/nostrlabs-io/emoji_picker_flutter