From 8184a8a680763035606b1bcdf0047dc2d318a5b9 Mon Sep 17 00:00:00 2001 From: grunch Date: Fri, 23 Oct 2026 18:08:28 -0300 Subject: [PATCH 1/6] feat(announcements): bridge the cache to Dart and add the Announcements toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 3 of specs/006 §10. rust/src/api/announcements.rs exposes the cache (whole, critical first), a stream that re-emits it after every sweep, arrival or flag, the read/dismissed flags, and the toggle. The toggle is the settings key announcements_enabled, device-scoped: off closes the subscription at the tap and the relay pump discards what arrives behind the close; on re-issues the filter. Dart gets a fifth row in Notification settings, persisted through Rust, in all seven locales. The spec records what the bridge settled (§6.1, §7). --- .../providers/announcements_provider.dart | 75 ++ .../settings/providers/log_provider.dart | 10 +- .../settings/providers/nwc_provider.dart | 22 +- .../settings/providers/settings_provider.dart | 25 +- .../screens/notification_settings_screen.dart | 150 ++- .../widgets/currency_selector_dialog.dart | 80 +- .../settings/widgets/language_selector.dart | 17 +- lib/l10n/app_de.arb | 3 + lib/l10n/app_en.arb | 12 + lib/l10n/app_es.arb | 3 + lib/l10n/app_fr.arb | 3 + lib/l10n/app_it.arb | 3 + lib/l10n/app_localizations.dart | 18 + lib/l10n/app_localizations_de.dart | 11 + lib/l10n/app_localizations_en.dart | 11 + lib/l10n/app_localizations_es.dart | 11 + lib/l10n/app_localizations_fr.dart | 11 + lib/l10n/app_localizations_it.dart | 11 + lib/l10n/app_localizations_nl.dart | 11 + lib/l10n/app_localizations_pt.dart | 11 + lib/l10n/app_nl.arb | 3 + lib/l10n/app_pt.arb | 3 + lib/src/rust/api/announcements.dart | 56 + lib/src/rust/api/types.dart | 112 +- lib/src/rust/frb_generated.dart | 1034 ++++++++++++---- lib/src/rust/frb_generated.io.dart | 162 +++ lib/src/rust/frb_generated.web.dart | 154 +++ rust/src/api/announcements.rs | 275 +++++ rust/src/api/mod.rs | 1 + rust/src/api/types.rs | 48 + rust/src/db/mod.rs | 7 + rust/src/frb_generated.rs | 1040 +++++++++++++---- rust/src/nostr/announcement_reader.rs | 195 +++- specs/006-announcement-channel/spec.md | 35 +- .../announcements_provider_test.dart | 89 ++ .../screens/settings_screens_test.dart | 75 +- 36 files changed, 3225 insertions(+), 562 deletions(-) create mode 100644 lib/features/settings/providers/announcements_provider.dart create mode 100644 lib/src/rust/api/announcements.dart create mode 100644 rust/src/api/announcements.rs create mode 100644 test/features/settings/providers/announcements_provider_test.dart diff --git a/lib/features/settings/providers/announcements_provider.dart b/lib/features/settings/providers/announcements_provider.dart new file mode 100644 index 000000000..58622a467 --- /dev/null +++ b/lib/features/settings/providers/announcements_provider.dart @@ -0,0 +1,75 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:mostro/src/rust/api/announcements.dart' as announcements_api; + +/// The Announcements toggle (specs/006-announcement-channel §7). +/// +/// Unlike its four neighbours, which are `shared_preferences` keys, this one +/// lives in the Rust settings table: the value decides whether Rust opens a +/// relay subscription, and the authority for that is on the side that opens +/// it. Off means the subscription is closed at the tap, not that arriving +/// notices are hidden. + +/// The Rust side of the toggle. Injected so screen tests never reach the +/// bridge. +class AnnouncementsBridge { + const AnnouncementsBridge(); + + Future enabled() => announcements_api.getAnnouncementsEnabled(); + + Future setEnabled(bool enabled) => + announcements_api.setAnnouncementsEnabled(enabled: enabled); +} + +final announcementsBridgeProvider = Provider( + (ref) => const AnnouncementsBridge(), +); + +class AnnouncementsEnabledNotifier extends StateNotifier { + AnnouncementsEnabledNotifier({required AnnouncementsBridge bridge}) + : _bridge = bridge, + // On until Rust says otherwise: the persisted default (§7). + super(true) { + _load(); + } + + final AnnouncementsBridge _bridge; + + /// The user flipped the toggle before [_load] answered: the load read the + /// setting before that write, so its value is older than the screen's. + bool _touched = false; + + Future _load() async { + try { + final enabled = await _bridge.enabled(); + if (mounted && !_touched) state = enabled; + } catch (e) { + debugPrint('[announcements] reading the toggle failed: $e'); + } + } + + /// Applies the change to the UI first and persists after, so the toggle + /// answers the tap; a failed write is reported by returning false and the + /// state rolling back. + Future set(bool value) async { + final before = state; + _touched = true; + state = value; + try { + await _bridge.setEnabled(value); + return true; + } catch (e) { + debugPrint('[announcements] saving the toggle failed: $e'); + if (mounted) state = before; + return false; + } + } +} + +final announcementsEnabledProvider = + StateNotifierProvider( + (ref) => AnnouncementsEnabledNotifier( + bridge: ref.watch(announcementsBridgeProvider), + ), + ); diff --git a/lib/features/settings/providers/log_provider.dart b/lib/features/settings/providers/log_provider.dart index 45a096ff4..b120cda37 100644 --- a/lib/features/settings/providers/log_provider.dart +++ b/lib/features/settings/providers/log_provider.dart @@ -13,8 +13,9 @@ typedef LogEntryReader = Future Function(); /// The two bridge calls behind function seams, so the merge below can be /// driven in tests without a live bridge. -final logHistoryProvider = - Provider> Function()>((ref) => logging_api.recentLogs); +final logHistoryProvider = Provider> Function()>( + (ref) => logging_api.recentLogs, +); final logStreamProvider = Provider Function()>( (ref) => () async => (await logging_api.onLogEntry()).next, @@ -25,8 +26,9 @@ final logStreamProvider = Provider Function()>( /// Seeded from the Rust ring buffer so the screen opens on the history that led /// to whatever the user is reporting, then followed live. Cancelled when the /// provider is disposed (e.g. when LogReportScreen is popped). -final logEntriesProvider = - StreamProvider.autoDispose>((ref) async* { +final logEntriesProvider = StreamProvider.autoDispose>(( + ref, +) async* { var cancelled = false; ref.onDispose(() => cancelled = true); diff --git a/lib/features/settings/providers/nwc_provider.dart b/lib/features/settings/providers/nwc_provider.dart index f3796e765..10feb0fa4 100644 --- a/lib/features/settings/providers/nwc_provider.dart +++ b/lib/features/settings/providers/nwc_provider.dart @@ -20,6 +20,7 @@ class NwcWalletState { }) : relayUrls = List.unmodifiable(relayUrls); final String walletPubkey; + /// Immutable list of NWC relay URLs. final List relayUrls; final String? walletName; @@ -30,15 +31,13 @@ class NwcWalletState { List? relayUrls, String? walletName, Object? balanceSats = _unset, - }) => - NwcWalletState( - walletPubkey: walletPubkey ?? this.walletPubkey, - relayUrls: relayUrls ?? this.relayUrls, - walletName: walletName ?? this.walletName, - balanceSats: identical(balanceSats, _unset) - ? this.balanceSats - : balanceSats as int?, - ); + }) => NwcWalletState( + walletPubkey: walletPubkey ?? this.walletPubkey, + relayUrls: relayUrls ?? this.relayUrls, + walletName: walletName ?? this.walletName, + balanceSats: + identical(balanceSats, _unset) ? this.balanceSats : balanceSats as int?, + ); } // ── Notifier ─────────────────────────────────────────────────────────────────── @@ -75,8 +74,9 @@ class NwcNotifier extends StateNotifier { /// Wallet connection state. `null` when no wallet is connected. /// Override in `main()` via [ProviderScope] to inject [SharedPreferences]. -final nwcProvider = - StateNotifierProvider((ref) => NwcNotifier()); +final nwcProvider = StateNotifierProvider( + (ref) => NwcNotifier(), +); /// Convenience: `true` when a wallet is connected. final isWalletConnectedProvider = Provider( diff --git a/lib/features/settings/providers/settings_provider.dart b/lib/features/settings/providers/settings_provider.dart index 90512f3bd..c347cdd6b 100644 --- a/lib/features/settings/providers/settings_provider.dart +++ b/lib/features/settings/providers/settings_provider.dart @@ -41,12 +41,14 @@ class AppSettingsState { }) { return AppSettingsState( language: language ?? this.language, - defaultFiatCode: identical(defaultFiatCode, _unset) - ? this.defaultFiatCode - : defaultFiatCode as String?, - defaultLightningAddress: identical(defaultLightningAddress, _unset) - ? this.defaultLightningAddress - : defaultLightningAddress as String?, + defaultFiatCode: + identical(defaultFiatCode, _unset) + ? this.defaultFiatCode + : defaultFiatCode as String?, + defaultLightningAddress: + identical(defaultLightningAddress, _unset) + ? this.defaultLightningAddress + : defaultLightningAddress as String?, loggingEnabled: loggingEnabled ?? this.loggingEnabled, themeMode: themeMode ?? this.themeMode, ); @@ -111,9 +113,9 @@ class SettingsNotifier extends StateNotifier { SharedPreferences? prefs, AppSettingsState? initial, LightningAddressSink? syncLightningAddress, - }) : _prefs = prefs, - _syncLightningAddress = syncLightningAddress, - super(initial ?? const AppSettingsState()); + }) : _prefs = prefs, + _syncLightningAddress = syncLightningAddress, + super(initial ?? const AppSettingsState()); final SharedPreferences? _prefs; final LightningAddressSink? _syncLightningAddress; @@ -187,8 +189,9 @@ class SettingsNotifier extends StateNotifier { /// synchronously before the first frame. final settingsProvider = StateNotifierProvider( - (ref) => SettingsNotifier(), // no-persistence fallback; replaced in main() -); + (ref) => + SettingsNotifier(), // no-persistence fallback; replaced in main() + ); /// Language codes the app ships translations for, derived from the generated /// [AppLocalizations]. Used to validate stored and device languages. diff --git a/lib/features/settings/screens/notification_settings_screen.dart b/lib/features/settings/screens/notification_settings_screen.dart index 3458cabef..abf6cfcdd 100644 --- a/lib/features/settings/screens/notification_settings_screen.dart +++ b/lib/features/settings/screens/notification_settings_screen.dart @@ -7,6 +7,7 @@ import 'package:mostro/core/app_routes.dart'; import 'package:mostro/core/order_book_palette.dart'; import 'package:mostro/core/settings_palette.dart'; import 'package:mostro/features/settings/models/push_status_line.dart'; +import 'package:mostro/features/settings/providers/announcements_provider.dart'; import 'package:mostro/features/settings/providers/notification_permission_provider.dart'; import 'package:mostro/features/settings/providers/notification_prefs_provider.dart'; import 'package:mostro/features/settings/providers/push_settings_provider.dart'; @@ -28,6 +29,12 @@ import 'package:mostro/shared/widgets/redesign_app_bar.dart'; /// /// The event rows gate the in-app cards, not the push: a push carries no /// type to filter on (docs/PUSH_NOTIFICATIONS.md §9.1). +/// +/// A third card holds the Announcements toggle (specs/006 §7): the project's +/// signed notices, read from the relays. Off closes that subscription at the +/// tap, which is why its value lives in Rust rather than in `shared_preferences` +/// like the four rows above it — and why the OS permission does not gate it: +/// an announcement posts no system notification. class NotificationSettingsScreen extends ConsumerWidget { const NotificationSettingsScreen({super.key}); @@ -125,6 +132,19 @@ class NotificationSettingsScreen extends ConsumerWidget { ), ), const SizedBox(height: settingsGroupGap), + Padding( + padding: const EdgeInsets.fromLTRB(2, 0, 2, 14), + child: Text( + l10n.announcementsGroupSubtitle, + style: TextStyle( + fontSize: 12, + height: 1.5, + color: book.textSecondary, + ), + ), + ), + const SettingsGroup(rows: [_AnnouncementsRow()]), + const SizedBox(height: settingsGroupGap), SettingsFootnote( icon: Icons.lock_outline, // Relevant in a privacy app: pushes travel through Google/Apple. @@ -355,12 +375,99 @@ class _EventRow extends ConsumerWidget { final bool value; final bool enabled; + @override + Widget build(BuildContext context, WidgetRef ref) { + final (title, description) = _copy(AppLocalizations.of(context), event); + return _ToggleRow( + icon: icon, + title: title, + description: description, + value: value, + onChanged: enabled ? (next) => _set(context, ref, next) : null, + ); + } + + Future _set(BuildContext context, WidgetRef ref, bool next) async { + final ok = await ref + .read(notificationPrefsProvider.notifier) + .setEvent(event, next); + if (!ok && context.mounted) _saveFailed(context); + } + + static (String, String) _copy( + AppLocalizations l10n, + NotificationEvent event, + ) => switch (event) { + NotificationEvent.tradeUpdates => ( + l10n.notifTradeUpdatesTitle, + l10n.notifTradeUpdatesSubtitle, + ), + NotificationEvent.newMessages => ( + l10n.notifNewMessagesTitle, + l10n.notifNewMessagesSubtitle, + ), + NotificationEvent.paymentAlerts => ( + l10n.notifPaymentAlertsTitle, + l10n.notifPaymentAlertsSubtitle, + ), + NotificationEvent.disputeUpdates => ( + l10n.notifDisputeUpdatesTitle, + l10n.notifDisputeUpdatesSubtitle, + ), + }; +} + +/// The Announcements toggle (specs/006 §7), persisted by Rust: off closes +/// the relay subscription at the tap. Never gated by the OS permission. +class _AnnouncementsRow extends ConsumerWidget { + const _AnnouncementsRow(); + @override Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context); - final book = OrderBookPalette.of(context); - final (title, description) = _copy(l10n, event); + return _ToggleRow( + icon: Icons.campaign_outlined, + title: l10n.notifAnnouncementsTitle, + description: l10n.notifAnnouncementsSubtitle, + value: ref.watch(announcementsEnabledProvider), + onChanged: (next) => _set(context, ref, next), + ); + } + Future _set(BuildContext context, WidgetRef ref, bool next) async { + final ok = await ref.read(announcementsEnabledProvider.notifier).set(next); + if (!ok && context.mounted) _saveFailed(context); + } +} + +void _saveFailed(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context).notificationPrefSaveFailed), + ), + ); +} + +/// One row of a settings group: a glyph, a 13/600 title over an 11/400 +/// description, and a toggle. [onChanged] null disables the toggle. +class _ToggleRow extends StatelessWidget { + const _ToggleRow({ + required this.icon, + required this.title, + required this.description, + required this.value, + required this.onChanged, + }); + + final IconData icon; + final String title; + final String description; + final bool value; + final ValueChanged? onChanged; + + @override + Widget build(BuildContext context) { + final book = OrderBookPalette.of(context); return Padding( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14), child: Row( @@ -402,49 +509,12 @@ class _EventRow extends ConsumerWidget { MostroToggle( value: value, semanticLabel: title, - onChanged: enabled ? (next) => _set(context, ref, next) : null, + onChanged: onChanged, ), ], ), ); } - - Future _set(BuildContext context, WidgetRef ref, bool next) async { - final ok = await ref - .read(notificationPrefsProvider.notifier) - .setEvent(event, next); - if (!ok && context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - AppLocalizations.of(context).notificationPrefSaveFailed, - ), - ), - ); - } - } - - static (String, String) _copy( - AppLocalizations l10n, - NotificationEvent event, - ) => switch (event) { - NotificationEvent.tradeUpdates => ( - l10n.notifTradeUpdatesTitle, - l10n.notifTradeUpdatesSubtitle, - ), - NotificationEvent.newMessages => ( - l10n.notifNewMessagesTitle, - l10n.notifNewMessagesSubtitle, - ), - NotificationEvent.paymentAlerts => ( - l10n.notifPaymentAlertsTitle, - l10n.notifPaymentAlertsSubtitle, - ), - NotificationEvent.disputeUpdates => ( - l10n.notifDisputeUpdatesTitle, - l10n.notifDisputeUpdatesSubtitle, - ), - }; } // ── Permission banners ──────────────────────────────────────────────────────── diff --git a/lib/features/settings/widgets/currency_selector_dialog.dart b/lib/features/settings/widgets/currency_selector_dialog.dart index 66e4a590d..6dbdec3c0 100644 --- a/lib/features/settings/widgets/currency_selector_dialog.dart +++ b/lib/features/settings/widgets/currency_selector_dialog.dart @@ -22,10 +22,10 @@ class _FiatEntry { final String flag; factory _FiatEntry.fromJson(Map json) => _FiatEntry( - code: (json['code'] as String?) ?? '', - name: (json['name'] as String?) ?? '', - flag: (json['flag'] as String?) ?? '', - ); + code: (json['code'] as String?) ?? '', + name: (json['name'] as String?) ?? '', + flag: (json['flag'] as String?) ?? '', + ); } // ── Widget ──────────────────────────────────────────────────────────────────── @@ -63,11 +63,12 @@ class _CurrencySelectorDialogState try { final raw = await rootBundle.loadString('assets/data/fiat.json'); final List parsed = json.decode(raw) as List; - final entries = parsed - .cast>() - .map(_FiatEntry.fromJson) - .where((e) => e.code.isNotEmpty) - .toList(); + final entries = + parsed + .cast>() + .map(_FiatEntry.fromJson) + .where((e) => e.code.isNotEmpty) + .toList(); if (mounted) { setState(() { _allEntries = entries; @@ -84,10 +85,11 @@ class _CurrencySelectorDialogState void _onSearch() { final query = _searchController.text.toLowerCase(); setState(() { - _filtered = _allEntries.where((e) { - return e.code.toLowerCase().contains(query) || - e.name.toLowerCase().contains(query); - }).toList(); + _filtered = + _allEntries.where((e) { + return e.code.toLowerCase().contains(query) || + e.name.toLowerCase().contains(query); + }).toList(); }); } @@ -99,7 +101,8 @@ class _CurrencySelectorDialogState @override Widget build(BuildContext context) { final colors = Theme.of(context).extension(); - if (colors == null) throw StateError('AppColors theme extension must be registered'); + if (colors == null) + throw StateError('AppColors theme extension must be registered'); final l10n = AppLocalizations.of(context); return Scaffold( @@ -123,32 +126,33 @@ class _CurrencySelectorDialogState ), ), Expanded( - child: _loading - ? const Center(child: CircularProgressIndicator()) - : _filtered.isEmpty + child: + _loading + ? const Center(child: CircularProgressIndicator()) + : _filtered.isEmpty ? Center( - child: Text( - l10n.noCurrenciesFoundMessage, - style: Theme.of(context).textTheme.bodyMedium, - ), - ) - : ListView.builder( - itemCount: _filtered.length, - itemBuilder: (context, index) { - final entry = _filtered[index]; - return ListTile( - leading: Text( - entry.flag, - style: const TextStyle(fontSize: 24), - ), - title: Text( - '${entry.code} — ${entry.name}', - style: Theme.of(context).textTheme.bodyLarge, - ), - onTap: () => _select(entry), - ); - }, + child: Text( + l10n.noCurrenciesFoundMessage, + style: Theme.of(context).textTheme.bodyMedium, ), + ) + : ListView.builder( + itemCount: _filtered.length, + itemBuilder: (context, index) { + final entry = _filtered[index]; + return ListTile( + leading: Text( + entry.flag, + style: const TextStyle(fontSize: 24), + ), + title: Text( + '${entry.code} — ${entry.name}', + style: Theme.of(context).textTheme.bodyLarge, + ), + onTap: () => _select(entry), + ); + }, + ), ), ], ), diff --git a/lib/features/settings/widgets/language_selector.dart b/lib/features/settings/widgets/language_selector.dart index 1ce492965..f72f37bad 100644 --- a/lib/features/settings/widgets/language_selector.dart +++ b/lib/features/settings/widgets/language_selector.dart @@ -55,7 +55,8 @@ class LanguageSelector extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final currentCode = ref.watch(settingsProvider).language; final colorsRaw = Theme.of(context).extension(); - if (colorsRaw == null) throw StateError('AppColors theme extension must be registered'); + if (colorsRaw == null) + throw StateError('AppColors theme extension must be registered'); final colors = colorsRaw; return MostroSheet( @@ -70,18 +71,18 @@ class LanguageSelector extends ConsumerWidget { title: Text( lang.native, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - color: - lang.code == currentCode ? colors.mostroGreen : null, - ), + fontWeight: FontWeight.bold, + color: lang.code == currentCode ? colors.mostroGreen : null, + ), ), subtitle: Text( lang.name, style: Theme.of(context).textTheme.bodyMedium, ), - trailing: lang.code == currentCode - ? Icon(Icons.check_circle, color: colors.mostroGreen) - : null, + trailing: + lang.code == currentCode + ? Icon(Icons.check_circle, color: colors.mostroGreen) + : null, onTap: () { Navigator.of(context).pop(); if (lang.code == currentCode) return; diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 8a9144236..d272d0d52 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Bestätigungen und Fehler von Lightning-Zahlungen", "notifDisputeUpdatesTitle": "Streitfall-Updates", "notifDisputeUpdatesSubtitle": "Schlichter-Aktionen und Streitbeilegungen", + "notifAnnouncementsTitle": "Ankündigungen", + "notifAnnouncementsSubtitle": "Versionen, Ausfälle und Relay-Änderungen, signiert vom Mostro-Projekt", + "announcementsGroupSubtitle": "Ankündigungen werden von den Relays gelesen und nie beantwortet: Nichts über dich wird gesendet.", "searchCurrenciesHint": "Währungen suchen…", "noCurrenciesFoundMessage": "Keine Währungen gefunden", "shareLogsTooltip": "Protokolle teilen", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 44a688a11..be48dc4e7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1714,6 +1714,18 @@ "@notifDisputeUpdatesSubtitle": { "description": "Subtitle of the dispute updates notification toggle" }, + "notifAnnouncementsTitle": "Announcements", + "@notifAnnouncementsTitle": { + "description": "Title of the Announcements toggle in notification settings (specs/006)" + }, + "notifAnnouncementsSubtitle": "Releases, outages and relay changes, signed by the Mostro project", + "@notifAnnouncementsSubtitle": { + "description": "Subtitle of the Announcements toggle" + }, + "announcementsGroupSubtitle": "Announcements are read from the relays and never answered: nothing about you is sent.", + "@announcementsGroupSubtitle": { + "description": "Line above the Announcements toggle: the channel is one-way, nothing is reported back" + }, "searchCurrenciesHint": "Search currencies…", "@searchCurrenciesHint": { "description": "Hint text of the currency search field" diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b94e44295..9e07ab136 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Confirmaciones y fallos de pagos Lightning", "notifDisputeUpdatesTitle": "Actualizaciones de disputas", "notifDisputeUpdatesSubtitle": "Acciones de los resolutores y resoluciones de disputas", + "notifAnnouncementsTitle": "Anuncios", + "notifAnnouncementsSubtitle": "Versiones, caídas y cambios de relays, firmados por el proyecto Mostro", + "announcementsGroupSubtitle": "Los anuncios se leen de los relays y nunca se responden: no se envía nada sobre ti.", "searchCurrenciesHint": "Buscar monedas…", "noCurrenciesFoundMessage": "No se encontraron monedas", "shareLogsTooltip": "Compartir registros", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index c1563bfcc..42d7acb02 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Confirmations et échecs de paiements Lightning", "notifDisputeUpdatesTitle": "Mises à jour des litiges", "notifDisputeUpdatesSubtitle": "Actions des médiateurs et résolutions de litiges", + "notifAnnouncementsTitle": "Annonces", + "notifAnnouncementsSubtitle": "Versions, pannes et changements de relais, signés par le projet Mostro", + "announcementsGroupSubtitle": "Les annonces sont lues depuis les relais et jamais répondues : rien vous concernant n'est envoyé.", "searchCurrenciesHint": "Rechercher des devises…", "noCurrenciesFoundMessage": "Aucune devise trouvée", "shareLogsTooltip": "Partager les journaux", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 07a4c712d..4fa08cdc8 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Conferme ed errori dei pagamenti Lightning", "notifDisputeUpdatesTitle": "Aggiornamenti dispute", "notifDisputeUpdatesSubtitle": "Azioni dei mediatori e risoluzioni delle dispute", + "notifAnnouncementsTitle": "Annunci", + "notifAnnouncementsSubtitle": "Versioni, interruzioni e cambi di relay, firmati dal progetto Mostro", + "announcementsGroupSubtitle": "Gli annunci vengono letti dai relay e mai risposti: non viene inviato nulla su di te.", "searchCurrenciesHint": "Cerca valute…", "noCurrenciesFoundMessage": "Nessuna valuta trovata", "shareLogsTooltip": "Condividi i log", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 8a3ef2312..c78089e8c 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -2466,6 +2466,24 @@ abstract class AppLocalizations { /// **'Resolver actions and dispute resolutions'** String get notifDisputeUpdatesSubtitle; + /// Title of the Announcements toggle in notification settings (specs/006) + /// + /// In en, this message translates to: + /// **'Announcements'** + String get notifAnnouncementsTitle; + + /// Subtitle of the Announcements toggle + /// + /// In en, this message translates to: + /// **'Releases, outages and relay changes, signed by the Mostro project'** + String get notifAnnouncementsSubtitle; + + /// Line above the Announcements toggle: the channel is one-way, nothing is reported back + /// + /// In en, this message translates to: + /// **'Announcements are read from the relays and never answered: nothing about you is sent.'** + String get announcementsGroupSubtitle; + /// Hint text of the currency search field /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 2d6276849..b4477185b 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1379,6 +1379,17 @@ class AppLocalizationsDe extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Schlichter-Aktionen und Streitbeilegungen'; + @override + String get notifAnnouncementsTitle => 'Ankündigungen'; + + @override + String get notifAnnouncementsSubtitle => + 'Versionen, Ausfälle und Relay-Änderungen, signiert vom Mostro-Projekt'; + + @override + String get announcementsGroupSubtitle => + 'Ankündigungen werden von den Relays gelesen und nie beantwortet: Nichts über dich wird gesendet.'; + @override String get searchCurrenciesHint => 'Währungen suchen…'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 600195c21..720374a41 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1361,6 +1361,17 @@ class AppLocalizationsEn extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Resolver actions and dispute resolutions'; + @override + String get notifAnnouncementsTitle => 'Announcements'; + + @override + String get notifAnnouncementsSubtitle => + 'Releases, outages and relay changes, signed by the Mostro project'; + + @override + String get announcementsGroupSubtitle => + 'Announcements are read from the relays and never answered: nothing about you is sent.'; + @override String get searchCurrenciesHint => 'Search currencies…'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index e5cc998f9..54acfa240 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1374,6 +1374,17 @@ class AppLocalizationsEs extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Acciones de los resolutores y resoluciones de disputas'; + @override + String get notifAnnouncementsTitle => 'Anuncios'; + + @override + String get notifAnnouncementsSubtitle => + 'Versiones, caídas y cambios de relays, firmados por el proyecto Mostro'; + + @override + String get announcementsGroupSubtitle => + 'Los anuncios se leen de los relays y nunca se responden: no se envía nada sobre ti.'; + @override String get searchCurrenciesHint => 'Buscar monedas…'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 22415b963..5dcf08d0c 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1376,6 +1376,17 @@ class AppLocalizationsFr extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Actions des médiateurs et résolutions de litiges'; + @override + String get notifAnnouncementsTitle => 'Annonces'; + + @override + String get notifAnnouncementsSubtitle => + 'Versions, pannes et changements de relais, signés par le projet Mostro'; + + @override + String get announcementsGroupSubtitle => + 'Les annonces sont lues depuis les relais et jamais répondues : rien vous concernant n\'est envoyé.'; + @override String get searchCurrenciesHint => 'Rechercher des devises…'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 45043ea71..3f2a1f8ca 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -1373,6 +1373,17 @@ class AppLocalizationsIt extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Azioni dei mediatori e risoluzioni delle dispute'; + @override + String get notifAnnouncementsTitle => 'Annunci'; + + @override + String get notifAnnouncementsSubtitle => + 'Versioni, interruzioni e cambi di relay, firmati dal progetto Mostro'; + + @override + String get announcementsGroupSubtitle => + 'Gli annunci vengono letti dai relay e mai risposti: non viene inviato nulla su di te.'; + @override String get searchCurrenciesHint => 'Cerca valute…'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index c9934f4a1..072b0e156 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1378,6 +1378,17 @@ class AppLocalizationsNl extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Acties van de solver en uitkomsten van disputen'; + @override + String get notifAnnouncementsTitle => 'Aankondigingen'; + + @override + String get notifAnnouncementsSubtitle => + 'Versies, storingen en relaywijzigingen, ondertekend door het Mostro-project'; + + @override + String get announcementsGroupSubtitle => + 'Aankondigingen worden van de relays gelezen en nooit beantwoord: er wordt niets over jou verstuurd.'; + @override String get searchCurrenciesHint => 'Valuta zoeken…'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 37f5c92e9..f33c275f5 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -1377,6 +1377,17 @@ class AppLocalizationsPt extends AppLocalizations { String get notifDisputeUpdatesSubtitle => 'Ações do mediador e resoluções de disputas'; + @override + String get notifAnnouncementsTitle => 'Anúncios'; + + @override + String get notifAnnouncementsSubtitle => + 'Versões, quedas e mudanças de relays, assinados pelo projeto Mostro'; + + @override + String get announcementsGroupSubtitle => + 'Os anúncios são lidos dos relays e nunca respondidos: nada sobre você é enviado.'; + @override String get searchCurrenciesHint => 'Buscar moedas…'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 5446fba16..d48b2fabb 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Bevestigde en mislukte Lightning-betalingen", "notifDisputeUpdatesTitle": "Wijzigingen in disputen", "notifDisputeUpdatesSubtitle": "Acties van de solver en uitkomsten van disputen", + "notifAnnouncementsTitle": "Aankondigingen", + "notifAnnouncementsSubtitle": "Versies, storingen en relaywijzigingen, ondertekend door het Mostro-project", + "announcementsGroupSubtitle": "Aankondigingen worden van de relays gelezen en nooit beantwoord: er wordt niets over jou verstuurd.", "searchCurrenciesHint": "Valuta zoeken…", "noCurrenciesFoundMessage": "Geen valuta gevonden", "shareLogsTooltip": "Logboek delen", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 95d2d57ac..3d9c494ab 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -394,6 +394,9 @@ "notifPaymentAlertsSubtitle": "Confirmações e falhas de pagamentos Lightning", "notifDisputeUpdatesTitle": "Atualizações de disputas", "notifDisputeUpdatesSubtitle": "Ações do mediador e resoluções de disputas", + "notifAnnouncementsTitle": "Anúncios", + "notifAnnouncementsSubtitle": "Versões, quedas e mudanças de relays, assinados pelo projeto Mostro", + "announcementsGroupSubtitle": "Os anúncios são lidos dos relays e nunca respondidos: nada sobre você é enviado.", "searchCurrenciesHint": "Buscar moedas…", "noCurrenciesFoundMessage": "Nenhuma moeda encontrada", "shareLogsTooltip": "Compartilhar logs", diff --git a/lib/src/rust/api/announcements.dart b/lib/src/rust/api/announcements.dart new file mode 100644 index 000000000..2acd34816 --- /dev/null +++ b/lib/src/rust/api/announcements.dart @@ -0,0 +1,56 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'types.dart'; + +// These functions are ignored because they are not marked as `pub`: `emit`, `publish_current`, `set_flags`, `to_info`, `tx` + +/// Every announcement the cache holds right now: `critical` first, then +/// newest first (§3.4), dismissed ones included — a dismissed `critical` +/// stays listed and Dart is the one that knows (§3.4). Empty before the +/// database is up. +Future> getAnnouncements() => + RustLib.instance.api.crateApiAnnouncementsGetAnnouncements(); + +/// The Announcements toggle (§7): on unless the user turned it off. +Future getAnnouncementsEnabled() => + RustLib.instance.api.crateApiAnnouncementsGetAnnouncementsEnabled(); + +/// Flip the toggle. Off closes the relay subscription at the tap and +/// discards anything queued behind it; on reopens it, with the same 30-day +/// window a fresh install gets (§7). Persisted first: the subscription +/// follows the setting, never the other way round. +Future setAnnouncementsEnabled({required bool enabled}) => RustLib + .instance + .api + .crateApiAnnouncementsSetAnnouncementsEnabled(enabled: enabled); + +/// The user saw the announcement at `address`. Rust holds the flag because +/// it is Rust that decides whether a later revision re-announces (§5.3). +Future markAnnouncementRead({required String address}) => RustLib + .instance + .api + .crateApiAnnouncementsMarkAnnouncementRead(address: address); + +/// The user swiped the announcement at `address` away. Read as well: a +/// dismissed notice never counts as unread, whichever level keeps it listed. +Future dismissAnnouncement({required String address}) => RustLib + .instance + .api + .crateApiAnnouncementsDismissAnnouncement(address: address); + +/// Subscribe before the first [`get_announcements`], so a snapshot landing +/// in between is not missed. +Future onAnnouncementsChanged() => + RustLib.instance.api.crateApiAnnouncementsOnAnnouncementsChanged(); + +// Rust type: RustOpaqueMoi> +abstract class AnnouncementsStream implements RustOpaqueInterface { + /// The next snapshot; a lag skips to the newest rather than ending the + /// stream, since every snapshot is the whole list. + Future> next(); +} diff --git a/lib/src/rust/api/types.dart b/lib/src/rust/api/types.dart index 14cea2fcd..6a1bc2523 100644 --- a/lib/src/rust/api/types.dart +++ b/lib/src/rust/api/types.dart @@ -10,7 +10,7 @@ part 'types.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `default_expiration_hours`, `default_expiration_seconds` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `AppState`, `MostroNodeInfo`, `QueuedMessageStatus`, `TradeHistoryEntry` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt` /// The `bond_claims` key for a node / order pair. Future bondClaimKey({ @@ -21,6 +21,116 @@ Future bondClaimKey({ orderId: orderId, ); +/// A project announcement the reader admitted (§5.2), with every locale: Rust +/// does not translate, Dart picks the copy for the locale on screen. +class AnnouncementInfo { + /// `38387::` — the announcement's identity across + /// revisions, and the id of its notification card. + final String address; + + /// `:`: changes with every correction published + /// under the same address, which is what makes it unread again (§5.3). + final String revision; + + /// Unix seconds, the event's `created_at`. + final PlatformInt64 createdAt; + + /// Unix seconds, the NIP-40 `expiration`: the announcement is gone once + /// it passes, online or not (§5.5). + final PlatformInt64 expiration; + final AnnouncementSeverity severity; + + /// Every supported locale, in the app's order. + final List texts; + + /// The one action link, `https` only, as parsed. + final String? url; + final bool read; + + /// Swiped away. A `Critical` stays listed, read, until it expires; the + /// other levels leave the list (§3.4). + final bool dismissed; + + const AnnouncementInfo({ + required this.address, + required this.revision, + required this.createdAt, + required this.expiration, + required this.severity, + required this.texts, + this.url, + required this.read, + required this.dismissed, + }); + + @override + int get hashCode => + address.hashCode ^ + revision.hashCode ^ + createdAt.hashCode ^ + expiration.hashCode ^ + severity.hashCode ^ + texts.hashCode ^ + url.hashCode ^ + read.hashCode ^ + dismissed.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AnnouncementInfo && + runtimeType == other.runtimeType && + address == other.address && + revision == other.revision && + createdAt == other.createdAt && + expiration == other.expiration && + severity == other.severity && + texts == other.texts && + url == other.url && + read == other.read && + dismissed == other.dismissed; +} + +/// How loudly an announcement is painted (specs/006-announcement-channel +/// §3.4). The publisher declares a level, never a colour; Dart maps it onto +/// the palette. A level this build does not know arrives as `Warning`. +enum AnnouncementSeverity { + /// Releases, new features, events. + info, + + /// Outages, a relay being retired, anything with a deadline. + warning, + + /// A security issue the user must act on now. + critical, +} + +/// One locale's copy of an announcement, plain text (§3.2). +class AnnouncementText { + /// `en`, `es`, … — one of the app's locales. + final String locale; + final String title; + final String body; + + const AnnouncementText({ + required this.locale, + required this.title, + required this.body, + }); + + @override + int get hashCode => locale.hashCode ^ title.hashCode ^ body.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AnnouncementText && + runtimeType == other.runtimeType && + locale == other.locale && + title == other.title && + body == other.body; +} + /// Aggregated user-facing application settings. /// /// `privacy_mode` is a read-only mirror of `IdentityInfo.privacy_mode` — diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 84ec517d6..2f5dc49d0 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -4,6 +4,7 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field import 'api.dart'; +import 'api/announcements.dart'; import 'api/bond.dart'; import 'api/cashu.dart'; import 'api/disputes.dart'; @@ -89,7 +90,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.11.1'; @override - int get rustContentHash => -1544659396; + int get rustContentHash => -703973155; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -100,6 +101,10 @@ class RustLib extends BaseEntrypoint { } abstract class RustLibApi extends BaseApi { + Future> crateApiAnnouncementsAnnouncementsStreamNext({ + required AnnouncementsStream that, + }); + Future crateApiMessagesAnyMessageStreamNext({ required AnyMessageStream that, }); @@ -333,6 +338,10 @@ abstract class RustLibApi extends BaseApi { Future crateApiNwcDisconnectWallet(); + Future crateApiAnnouncementsDismissAnnouncement({ + required String address, + }); + Future crateApiMessagesDownloadAttachment({ required String messageId, }); @@ -373,6 +382,10 @@ abstract class RustLibApi extends BaseApi { Future> crateApiIdentityFundsAtRisk(); + Future> crateApiAnnouncementsGetAnnouncements(); + + Future crateApiAnnouncementsGetAnnouncementsEnabled(); + Future crateApiGetAppVersion(); Future crateApiMessagesGetAttachmentStatus({ @@ -500,10 +513,16 @@ abstract class RustLibApi extends BaseApi { BigInt? expirySecs, }); + Future crateApiAnnouncementsMarkAnnouncementRead({ + required String address, + }); + Future crateApiMessagesMarkAsRead({required String tradeId}); Future crateApiNodesNodeMetadataDefault(); + Future crateApiAnnouncementsOnAnnouncementsChanged(); + Future crateApiMessagesOnAnyNewMessage(); Future crateApiMessagesOnAttachmentProgress({ @@ -661,6 +680,10 @@ abstract class RustLibApi extends BaseApi { Future crateApiSettingsSetActiveMostroNode({required String pubkey}); + Future crateApiAnnouncementsSetAnnouncementsEnabled({ + required bool enabled, + }); + Future crateApiEscrowSetCashuMintUrlOverride({String? mintUrl}); Future crateApiSettingsSetDefaultFiatCode({String? code}); @@ -738,6 +761,15 @@ abstract class RustLibApi extends BaseApi { Future crateApiIdentityValidateMnemonic({required List words}); + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_AnnouncementsStream; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_AnnouncementsStream; + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_AnnouncementsStreamPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_AnyMessageStream; @@ -978,6 +1010,42 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required super.portManager, }); + @override + Future> crateApiAnnouncementsAnnouncementsStreamNext({ + required AnnouncementsStream that, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 1, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_announcement_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAnnouncementsAnnouncementsStreamNextConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAnnouncementsAnnouncementsStreamNextConstMeta => + const TaskConstMeta( + debugName: "AnnouncementsStream_next", + argNames: ["that"], + ); + @override Future crateApiMessagesAnyMessageStreamNext({ required AnyMessageStream that, @@ -993,7 +1061,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 1, + funcId: 2, port: port_, ); }, @@ -1029,7 +1097,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 2, + funcId: 3, port: port_, ); }, @@ -1065,7 +1133,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 3, + funcId: 4, port: port_, ); }, @@ -1101,7 +1169,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 4, + funcId: 5, port: port_, ); }, @@ -1137,7 +1205,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 5, + funcId: 6, port: port_, ); }, @@ -1173,7 +1241,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 6, + funcId: 7, port: port_, ); }, @@ -1209,7 +1277,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 7, + funcId: 8, port: port_, ); }, @@ -1242,7 +1310,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 8, + funcId: 9, port: port_, ); }, @@ -1278,7 +1346,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 9, + funcId: 10, port: port_, ); }, @@ -1311,7 +1379,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 10, + funcId: 11, port: port_, ); }, @@ -1344,7 +1412,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 11, + funcId: 12, port: port_, ); }, @@ -1380,7 +1448,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 12, + funcId: 13, port: port_, ); }, @@ -1414,7 +1482,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 13, + funcId: 14, port: port_, ); }, @@ -1441,7 +1509,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 14, + funcId: 15, port: port_, ); }, @@ -1477,7 +1545,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 15, + funcId: 16, port: port_, ); }, @@ -1515,7 +1583,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 16, + funcId: 17, port: port_, ); }, @@ -1545,7 +1613,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 17, + funcId: 18, port: port_, ); }, @@ -1581,7 +1649,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 18, + funcId: 19, port: port_, ); }, @@ -1619,7 +1687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 19, + funcId: 20, port: port_, ); }, @@ -1659,7 +1727,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 20, + funcId: 21, port: port_, ); }, @@ -1697,7 +1765,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 21, + funcId: 22, port: port_, ); }, @@ -1733,7 +1801,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 22, + funcId: 23, port: port_, ); }, @@ -1769,7 +1837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 23, + funcId: 24, port: port_, ); }, @@ -1802,7 +1870,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 24, + funcId: 25, port: port_, ); }, @@ -1838,7 +1906,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 25, + funcId: 26, port: port_, ); }, @@ -1871,7 +1939,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 26, + funcId: 27, port: port_, ); }, @@ -1907,7 +1975,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 27, + funcId: 28, port: port_, ); }, @@ -1943,7 +2011,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 28, + funcId: 29, port: port_, ); }, @@ -1980,7 +2048,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 29, + funcId: 30, port: port_, ); }, @@ -2013,7 +2081,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 30, + funcId: 31, port: port_, ); }, @@ -2049,7 +2117,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 31, + funcId: 32, port: port_, ); }, @@ -2085,7 +2153,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 32, + funcId: 33, port: port_, ); }, @@ -2121,7 +2189,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 33, + funcId: 34, port: port_, ); }, @@ -2157,7 +2225,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 34, + funcId: 35, port: port_, ); }, @@ -2188,7 +2256,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 35, + funcId: 36, port: port_, ); }, @@ -2223,7 +2291,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 36, + funcId: 37, port: port_, ); }, @@ -2254,7 +2322,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 37, + funcId: 38, port: port_, ); }, @@ -2282,7 +2350,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 38, + funcId: 39, port: port_, ); }, @@ -2317,7 +2385,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 39, + funcId: 40, port: port_, ); }, @@ -2349,7 +2417,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 40, + funcId: 41, port: port_, ); }, @@ -2380,7 +2448,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 41, + funcId: 42, port: port_, ); }, @@ -2410,7 +2478,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 42, + funcId: 43, port: port_, ); }, @@ -2437,7 +2505,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 43, + funcId: 44, port: port_, ); }, @@ -2467,7 +2535,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 44, + funcId: 45, port: port_, ); }, @@ -2497,7 +2565,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 45, + funcId: 46, port: port_, ); }, @@ -2525,7 +2593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 46, + funcId: 47, port: port_, ); }, @@ -2553,7 +2621,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 47, + funcId: 48, port: port_, ); }, @@ -2581,7 +2649,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 48, + funcId: 49, port: port_, ); }, @@ -2611,7 +2679,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 49, + funcId: 50, port: port_, ); }, @@ -2641,7 +2709,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 50, + funcId: 51, port: port_, ); }, @@ -2671,7 +2739,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 51, + funcId: 52, port: port_, ); }, @@ -2703,7 +2771,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 52, + funcId: 53, port: port_, ); }, @@ -2735,7 +2803,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 53, + funcId: 54, port: port_, ); }, @@ -2763,7 +2831,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 54, + funcId: 55, port: port_, ); }, @@ -2793,7 +2861,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 55, + funcId: 56, port: port_, ); }, @@ -2820,7 +2888,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 56, + funcId: 57, port: port_, ); }, @@ -2858,7 +2926,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 57, + funcId: 58, port: port_, ); }, @@ -2898,7 +2966,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 58, + funcId: 59, port: port_, ); }, @@ -2931,7 +2999,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 59, + funcId: 60, port: port_, ); }, @@ -2961,7 +3029,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 60, + funcId: 61, port: port_, ); }, @@ -2988,7 +3056,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 61, + funcId: 62, port: port_, ); }, @@ -3016,7 +3084,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 62, + funcId: 63, port: port_, ); }, @@ -3047,7 +3115,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 63, + funcId: 64, port: port_, ); }, @@ -3074,7 +3142,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 64, + funcId: 65, port: port_, ); }, @@ -3104,7 +3172,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 65, + funcId: 66, port: port_, ); }, @@ -3134,7 +3202,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 66, + funcId: 67, port: port_, ); }, @@ -3161,7 +3229,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 67, + funcId: 68, port: port_, ); }, @@ -3188,7 +3256,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 68, + funcId: 69, port: port_, ); }, @@ -3215,7 +3283,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 69, + funcId: 70, port: port_, ); }, @@ -3233,6 +3301,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiNwcDisconnectWalletConstMeta => const TaskConstMeta(debugName: "disconnect_wallet", argNames: []); + @override + Future crateApiAnnouncementsDismissAnnouncement({ + required String address, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 71, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAnnouncementsDismissAnnouncementConstMeta, + argValues: [address], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAnnouncementsDismissAnnouncementConstMeta => + const TaskConstMeta( + debugName: "dismiss_announcement", + argNames: ["address"], + ); + @override Future crateApiMessagesDownloadAttachment({ required String messageId, @@ -3245,7 +3346,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 70, + funcId: 72, port: port_, ); }, @@ -3278,7 +3379,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 71, + funcId: 73, port: port_, ); }, @@ -3311,7 +3412,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 72, + funcId: 74, port: port_, ); }, @@ -3346,7 +3447,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 73, + funcId: 75, port: port_, ); }, @@ -3381,7 +3482,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 74, + funcId: 76, port: port_, ); }, @@ -3414,7 +3515,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 75, + funcId: 77, port: port_, ); }, @@ -3447,7 +3548,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 76, + funcId: 78, port: port_, ); }, @@ -3480,7 +3581,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 77, + funcId: 79, port: port_, ); }, @@ -3510,7 +3611,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 78, + funcId: 80, port: port_, ); }, @@ -3538,7 +3639,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 79, + funcId: 81, port: port_, ); }, @@ -3568,7 +3669,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 80, + funcId: 82, port: port_, ); }, @@ -3587,7 +3688,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { const TaskConstMeta(debugName: "funds_at_risk", argNames: []); @override - Future crateApiGetAppVersion() { + Future> crateApiAnnouncementsGetAnnouncements() { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3595,54 +3696,108 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 81, + funcId: 83, port: port_, ); }, codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: null, + decodeSuccessData: sse_decode_list_announcement_info, + decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiGetAppVersionConstMeta, + constMeta: kCrateApiAnnouncementsGetAnnouncementsConstMeta, argValues: [], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiGetAppVersionConstMeta => - const TaskConstMeta(debugName: "get_app_version", argNames: []); + TaskConstMeta get kCrateApiAnnouncementsGetAnnouncementsConstMeta => + const TaskConstMeta(debugName: "get_announcements", argNames: []); @override - Future crateApiMessagesGetAttachmentStatus({ - required String messageId, - }) { + Future crateApiAnnouncementsGetAnnouncementsEnabled() { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(messageId, serializer); pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 82, + funcId: 84, port: port_, ); }, codec: SseCodec( - decodeSuccessData: sse_decode_opt_box_autoadd_download_status, + decodeSuccessData: sse_decode_bool, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiMessagesGetAttachmentStatusConstMeta, - argValues: [messageId], + constMeta: kCrateApiAnnouncementsGetAnnouncementsEnabledConstMeta, + argValues: [], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiMessagesGetAttachmentStatusConstMeta => - const TaskConstMeta( - debugName: "get_attachment_status", + TaskConstMeta get kCrateApiAnnouncementsGetAnnouncementsEnabledConstMeta => + const TaskConstMeta(debugName: "get_announcements_enabled", argNames: []); + + @override + Future crateApiGetAppVersion() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 85, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kCrateApiGetAppVersionConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiGetAppVersionConstMeta => + const TaskConstMeta(debugName: "get_app_version", argNames: []); + + @override + Future crateApiMessagesGetAttachmentStatus({ + required String messageId, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(messageId, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 86, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_download_status, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMessagesGetAttachmentStatusConstMeta, + argValues: [messageId], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMessagesGetAttachmentStatusConstMeta => + const TaskConstMeta( + debugName: "get_attachment_status", argNames: ["messageId"], ); @@ -3655,7 +3810,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 83, + funcId: 87, port: port_, ); }, @@ -3683,7 +3838,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 84, + funcId: 88, port: port_, ); }, @@ -3715,7 +3870,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 85, + funcId: 89, port: port_, ); }, @@ -3745,7 +3900,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 86, + funcId: 90, port: port_, ); }, @@ -3772,7 +3927,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 87, + funcId: 91, port: port_, ); }, @@ -3800,7 +3955,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 88, + funcId: 92, port: port_, ); }, @@ -3827,7 +3982,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 89, + funcId: 93, port: port_, ); }, @@ -3854,7 +4009,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 90, + funcId: 94, port: port_, ); }, @@ -3884,7 +4039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 91, + funcId: 95, port: port_, ); }, @@ -3914,7 +4069,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 92, + funcId: 96, port: port_, ); }, @@ -3944,7 +4099,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 93, + funcId: 97, port: port_, ); }, @@ -3974,7 +4129,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 94, + funcId: 98, port: port_, ); }, @@ -4005,7 +4160,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 95, + funcId: 99, port: port_, ); }, @@ -4032,7 +4187,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 96, + funcId: 100, port: port_, ); }, @@ -4060,7 +4215,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 97, + funcId: 101, port: port_, ); }, @@ -4088,7 +4243,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 98, + funcId: 102, port: port_, ); }, @@ -4121,7 +4276,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 99, + funcId: 103, port: port_, ); }, @@ -4148,7 +4303,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 100, + funcId: 104, port: port_, ); }, @@ -4178,7 +4333,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 101, + funcId: 105, port: port_, ); }, @@ -4208,7 +4363,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 102, + funcId: 106, port: port_, ); }, @@ -4235,7 +4390,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 103, + funcId: 107, )!; }, codec: SseCodec( @@ -4261,7 +4416,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 104, + funcId: 108, port: port_, ); }, @@ -4289,7 +4444,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 105, + funcId: 109, port: port_, ); }, @@ -4317,7 +4472,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 106, + funcId: 110, port: port_, ); }, @@ -4344,7 +4499,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 107, + funcId: 111, port: port_, ); }, @@ -4371,7 +4526,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 108, + funcId: 112, port: port_, ); }, @@ -4399,7 +4554,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 109, + funcId: 113, port: port_, ); }, @@ -4430,7 +4585,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 110, + funcId: 114, port: port_, ); }, @@ -4465,7 +4620,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 111, + funcId: 115, port: port_, ); }, @@ -4502,7 +4657,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 112, + funcId: 116, port: port_, ); }, @@ -4532,7 +4687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 113, + funcId: 117, port: port_, ); }, @@ -4564,7 +4719,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 114, + funcId: 118, port: port_, ); }, @@ -4595,7 +4750,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 115, + funcId: 119, port: port_, ); }, @@ -4625,7 +4780,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 116, + funcId: 120, port: port_, ); }, @@ -4655,7 +4810,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 117, + funcId: 121, port: port_, ); }, @@ -4683,7 +4838,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 118, + funcId: 122, port: port_, ); }, @@ -4711,7 +4866,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 119, + funcId: 123, port: port_, ); }, @@ -4738,7 +4893,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 120, + funcId: 124, port: port_, ); }, @@ -4765,7 +4920,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 121, + funcId: 125, port: port_, ); }, @@ -4792,7 +4947,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 122, + funcId: 126, port: port_, ); }, @@ -4819,7 +4974,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 123, + funcId: 127, port: port_, ); }, @@ -4855,7 +5010,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 124, + funcId: 128, port: port_, ); }, @@ -4886,7 +5041,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 125, + funcId: 129, port: port_, ); }, @@ -4920,7 +5075,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 126, + funcId: 130, port: port_, ); }, @@ -4940,6 +5095,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["amountSats", "description", "expirySecs"], ); + @override + Future crateApiAnnouncementsMarkAnnouncementRead({ + required String address, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 131, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAnnouncementsMarkAnnouncementReadConstMeta, + argValues: [address], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAnnouncementsMarkAnnouncementReadConstMeta => + const TaskConstMeta( + debugName: "mark_announcement_read", + argNames: ["address"], + ); + @override Future crateApiMessagesMarkAsRead({required String tradeId}) { return handler.executeNormal( @@ -4950,7 +5138,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 127, + funcId: 132, port: port_, ); }, @@ -4977,7 +5165,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 128, + funcId: 133, port: port_, ); }, @@ -4995,6 +5183,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiNodesNodeMetadataDefaultConstMeta => const TaskConstMeta(debugName: "node_metadata_default", argNames: []); + @override + Future crateApiAnnouncementsOnAnnouncementsChanged() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 134, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream, + decodeErrorData: null, + ), + constMeta: kCrateApiAnnouncementsOnAnnouncementsChangedConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAnnouncementsOnAnnouncementsChangedConstMeta => + const TaskConstMeta(debugName: "on_announcements_changed", argNames: []); + @override Future crateApiMessagesOnAnyNewMessage() { return handler.executeNormal( @@ -5004,7 +5220,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 129, + funcId: 135, port: port_, ); }, @@ -5035,7 +5251,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 130, + funcId: 136, port: port_, ); }, @@ -5066,7 +5282,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 131, + funcId: 137, port: port_, ); }, @@ -5094,7 +5310,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 132, + funcId: 138, port: port_, ); }, @@ -5122,7 +5338,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 133, + funcId: 139, port: port_, ); }, @@ -5150,7 +5366,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 134, + funcId: 140, port: port_, ); }, @@ -5184,7 +5400,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 135, + funcId: 141, port: port_, ); }, @@ -5215,7 +5431,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 136, + funcId: 142, port: port_, ); }, @@ -5243,7 +5459,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 137, + funcId: 143, port: port_, ); }, @@ -5274,7 +5490,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 138, + funcId: 144, port: port_, ); }, @@ -5305,7 +5521,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 139, + funcId: 145, port: port_, ); }, @@ -5336,7 +5552,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 140, + funcId: 146, port: port_, ); }, @@ -5364,7 +5580,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 141, + funcId: 147, port: port_, ); }, @@ -5392,7 +5608,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 142, + funcId: 148, port: port_, ); }, @@ -5420,7 +5636,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 143, + funcId: 149, port: port_, ); }, @@ -5448,7 +5664,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 144, + funcId: 150, port: port_, ); }, @@ -5476,7 +5692,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 145, + funcId: 151, port: port_, ); }, @@ -5504,7 +5720,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 146, + funcId: 152, port: port_, ); }, @@ -5532,7 +5748,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 147, + funcId: 153, port: port_, ); }, @@ -5560,7 +5776,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 148, + funcId: 154, port: port_, ); }, @@ -5588,7 +5804,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 149, + funcId: 155, port: port_, ); }, @@ -5619,7 +5835,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 150, + funcId: 156, port: port_, ); }, @@ -5647,7 +5863,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 151, + funcId: 157, port: port_, ); }, @@ -5675,7 +5891,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 152, + funcId: 158, port: port_, ); }, @@ -5703,7 +5919,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 153, + funcId: 159, port: port_, ); }, @@ -5736,7 +5952,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 154, + funcId: 160, port: port_, ); }, @@ -5766,7 +5982,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 155, + funcId: 161, port: port_, ); }, @@ -5795,7 +6011,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 156, + funcId: 162, )!; }, codec: SseCodec( @@ -5827,7 +6043,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 157, + funcId: 163, port: port_, ); }, @@ -5855,7 +6071,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 158, + funcId: 164, port: port_, ); }, @@ -5885,7 +6101,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 159, + funcId: 165, port: port_, ); }, @@ -5916,7 +6132,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 160, + funcId: 166, port: port_, ); }, @@ -5949,7 +6165,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 161, + funcId: 167, port: port_, ); }, @@ -5979,7 +6195,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 162, + funcId: 168, port: port_, ); }, @@ -6006,7 +6222,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 163, + funcId: 169, port: port_, ); }, @@ -6033,7 +6249,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 164, + funcId: 170, port: port_, ); }, @@ -6060,7 +6276,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 165, + funcId: 171, port: port_, ); }, @@ -6090,7 +6306,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 166, + funcId: 172, port: port_, ); }, @@ -6120,7 +6336,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 167, + funcId: 173, port: port_, ); }, @@ -6147,7 +6363,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 168, + funcId: 174, port: port_, ); }, @@ -6177,7 +6393,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 169, + funcId: 175, port: port_, ); }, @@ -6208,7 +6424,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 170, + funcId: 176, port: port_, ); }, @@ -6236,7 +6452,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 171, + funcId: 177, port: port_, ); }, @@ -6267,7 +6483,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 172, + funcId: 178, port: port_, ); }, @@ -6297,7 +6513,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 173, + funcId: 179, )!; }, codec: SseCodec( @@ -6330,7 +6546,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 174, + funcId: 180, port: port_, ); }, @@ -6363,7 +6579,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 175, + funcId: 181, port: port_, ); }, @@ -6390,7 +6606,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 176, + funcId: 182, port: port_, ); }, @@ -6420,7 +6636,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 177, + funcId: 183, port: port_, ); }, @@ -6447,7 +6663,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 178, + funcId: 184, port: port_, ); }, @@ -6483,7 +6699,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 179, + funcId: 185, port: port_, ); }, @@ -6514,7 +6730,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 180, + funcId: 186, port: port_, ); }, @@ -6550,7 +6766,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 181, + funcId: 187, port: port_, ); }, @@ -6590,7 +6806,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 182, + funcId: 188, port: port_, ); }, @@ -6630,7 +6846,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 183, + funcId: 189, port: port_, ); }, @@ -6667,7 +6883,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 184, + funcId: 190, port: port_, ); }, @@ -6698,7 +6914,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 185, + funcId: 191, port: port_, ); }, @@ -6719,6 +6935,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["pubkey"], ); + @override + Future crateApiAnnouncementsSetAnnouncementsEnabled({ + required bool enabled, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_bool(enabled, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 192, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAnnouncementsSetAnnouncementsEnabledConstMeta, + argValues: [enabled], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAnnouncementsSetAnnouncementsEnabledConstMeta => + const TaskConstMeta( + debugName: "set_announcements_enabled", + argNames: ["enabled"], + ); + @override Future crateApiEscrowSetCashuMintUrlOverride({String? mintUrl}) { return handler.executeNormal( @@ -6729,7 +6978,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 186, + funcId: 193, port: port_, ); }, @@ -6760,7 +7009,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 187, + funcId: 194, port: port_, ); }, @@ -6791,7 +7040,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 188, + funcId: 195, port: port_, ); }, @@ -6822,7 +7071,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 189, + funcId: 196, port: port_, ); }, @@ -6853,7 +7102,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 190, + funcId: 197, port: port_, ); }, @@ -6881,7 +7130,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 191, + funcId: 198, port: port_, ); }, @@ -6912,7 +7161,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 192, + funcId: 199, port: port_, ); }, @@ -6940,7 +7189,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 193, + funcId: 200, port: port_, ); }, @@ -6972,7 +7221,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 194, + funcId: 201, port: port_, ); }, @@ -7002,7 +7251,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 195, + funcId: 202, port: port_, ); }, @@ -7033,7 +7282,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 196, + funcId: 203, port: port_, ); }, @@ -7063,7 +7312,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 197, + funcId: 204, port: port_, ); }, @@ -7098,7 +7347,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 198, + funcId: 205, port: port_, ); }, @@ -7133,7 +7382,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 199, + funcId: 206, port: port_, ); }, @@ -7167,7 +7416,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 200, + funcId: 207, port: port_, ); }, @@ -7202,7 +7451,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 201, + funcId: 208, port: port_, ); }, @@ -7237,7 +7486,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 202, + funcId: 209, port: port_, ); }, @@ -7267,7 +7516,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 203, + funcId: 210, port: port_, ); }, @@ -7294,7 +7543,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 204, + funcId: 211, port: port_, ); }, @@ -7330,7 +7579,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 205, + funcId: 212, port: port_, ); }, @@ -7362,7 +7611,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 206, + funcId: 213, port: port_, ); }, @@ -7393,7 +7642,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 207, + funcId: 214, port: port_, ); }, @@ -7423,7 +7672,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 208, + funcId: 215, port: port_, ); }, @@ -7454,7 +7703,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 209, + funcId: 216, port: port_, ); }, @@ -7472,6 +7721,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiIdentityValidateMnemonicConstMeta => const TaskConstMeta(debugName: "validate_mnemonic", argNames: ["words"]); + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_AnnouncementsStream => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_AnnouncementsStream => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_AnyMessageStream => wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream; @@ -7686,6 +7943,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(raw as String); } + @protected + AnnouncementsStream + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalDcoDecode(raw as List); + } + @protected AnyMessageStream dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -7922,6 +8188,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return WalletStatusStreamImpl.frbInternalDcoDecode(raw as List); } + @protected + AnnouncementsStream + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalDcoDecode(raw as List); + } + @protected AnyMessageStream dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -8158,6 +8433,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return OrderBookImpl.frbInternalDcoDecode(raw as List); } + @protected + AnnouncementsStream + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalDcoDecode(raw as List); + } + @protected AnyMessageStream dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -8400,6 +8684,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as String; } + @protected + AnnouncementInfo dco_decode_announcement_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 9) + throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + return AnnouncementInfo( + address: dco_decode_String(arr[0]), + revision: dco_decode_String(arr[1]), + createdAt: dco_decode_i_64(arr[2]), + expiration: dco_decode_i_64(arr[3]), + severity: dco_decode_announcement_severity(arr[4]), + texts: dco_decode_list_announcement_text(arr[5]), + url: dco_decode_opt_String(arr[6]), + read: dco_decode_bool(arr[7]), + dismissed: dco_decode_bool(arr[8]), + ); + } + + @protected + AnnouncementSeverity dco_decode_announcement_severity(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return AnnouncementSeverity.values[raw as int]; + } + + @protected + AnnouncementText dco_decode_announcement_text(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return AnnouncementText( + locale: dco_decode_String(arr[0]), + title: dco_decode_String(arr[1]), + body: dco_decode_String(arr[2]), + ); + } + @protected AppSettings dco_decode_app_settings(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -9115,6 +9437,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_String).toList(); } + @protected + List dco_decode_list_announcement_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_announcement_info).toList(); + } + + @protected + List dco_decode_list_announcement_text(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_announcement_text).toList(); + } + @protected List dco_decode_list_bond_claim(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -10133,6 +10467,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return AnyhowException(inner); } + @protected + AnnouncementsStream + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + @protected AnyMessageStream sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -10445,6 +10791,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + AnnouncementsStream + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + @protected AnyMessageStream sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -10757,6 +11115,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + AnnouncementsStream + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return AnnouncementsStreamImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + @protected AnyMessageStream sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -11076,6 +11446,53 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return utf8.decoder.convert(inner); } + @protected + AnnouncementInfo sse_decode_announcement_info(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_address = sse_decode_String(deserializer); + var var_revision = sse_decode_String(deserializer); + var var_createdAt = sse_decode_i_64(deserializer); + var var_expiration = sse_decode_i_64(deserializer); + var var_severity = sse_decode_announcement_severity(deserializer); + var var_texts = sse_decode_list_announcement_text(deserializer); + var var_url = sse_decode_opt_String(deserializer); + var var_read = sse_decode_bool(deserializer); + var var_dismissed = sse_decode_bool(deserializer); + return AnnouncementInfo( + address: var_address, + revision: var_revision, + createdAt: var_createdAt, + expiration: var_expiration, + severity: var_severity, + texts: var_texts, + url: var_url, + read: var_read, + dismissed: var_dismissed, + ); + } + + @protected + AnnouncementSeverity sse_decode_announcement_severity( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_i_32(deserializer); + return AnnouncementSeverity.values[inner]; + } + + @protected + AnnouncementText sse_decode_announcement_text(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_locale = sse_decode_String(deserializer); + var var_title = sse_decode_String(deserializer); + var var_body = sse_decode_String(deserializer); + return AnnouncementText( + locale: var_locale, + title: var_title, + body: var_body, + ); + } + @protected AppSettings sse_decode_app_settings(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -11943,6 +12360,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_announcement_info( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_announcement_info(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_announcement_text( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_announcement_text(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_bond_claim(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -13435,6 +13880,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.message, serializer); } + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as AnnouncementsStreamImpl).frbInternalSseEncode(move: true), + serializer, + ); + } + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -13773,6 +14231,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as AnnouncementsStreamImpl).frbInternalSseEncode(move: false), + serializer, + ); + } + @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -14111,6 +14582,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as AnnouncementsStreamImpl).frbInternalSseEncode(move: null), + serializer, + ); + } + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -14455,6 +14939,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); } + @protected + void sse_encode_announcement_info( + AnnouncementInfo self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.address, serializer); + sse_encode_String(self.revision, serializer); + sse_encode_i_64(self.createdAt, serializer); + sse_encode_i_64(self.expiration, serializer); + sse_encode_announcement_severity(self.severity, serializer); + sse_encode_list_announcement_text(self.texts, serializer); + sse_encode_opt_String(self.url, serializer); + sse_encode_bool(self.read, serializer); + sse_encode_bool(self.dismissed, serializer); + } + + @protected + void sse_encode_announcement_severity( + AnnouncementSeverity self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.index, serializer); + } + + @protected + void sse_encode_announcement_text( + AnnouncementText self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.locale, serializer); + sse_encode_String(self.title, serializer); + sse_encode_String(self.body, serializer); + } + @protected void sse_encode_app_settings(AppSettings self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -15234,6 +15755,30 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_announcement_info( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_announcement_info(item, serializer); + } + } + + @protected + void sse_encode_list_announcement_text( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_announcement_text(item, serializer); + } + } + @protected void sse_encode_list_bond_claim( List self, @@ -16495,6 +17040,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } +@sealed +class AnnouncementsStreamImpl extends RustOpaque + implements AnnouncementsStream { + // Not to be used by end users + AnnouncementsStreamImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + AnnouncementsStreamImpl.frbInternalSseDecode( + BigInt ptr, + int externalSizeOnNative, + ) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: + RustLib + .instance + .api + .rust_arc_increment_strong_count_AnnouncementsStream, + rustArcDecrementStrongCount: + RustLib + .instance + .api + .rust_arc_decrement_strong_count_AnnouncementsStream, + rustArcDecrementStrongCountPtr: + RustLib + .instance + .api + .rust_arc_decrement_strong_count_AnnouncementsStreamPtr, + ); + + /// The next snapshot; a lag skips to the newest rather than ending the + /// stream, since every snapshot is the whole list. + Future> next() => RustLib.instance.api + .crateApiAnnouncementsAnnouncementsStreamNext(that: this); +} + @sealed class AnyMessageStreamImpl extends RustOpaque implements AnyMessageStream { // Not to be used by end users diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index cc4089f89..9f4d5814d 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -4,6 +4,7 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field import 'api.dart'; +import 'api/announcements.dart'; import 'api/bond.dart'; import 'api/cashu.dart'; import 'api/disputes.dart'; @@ -41,6 +42,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_AnnouncementsStreamPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStreamPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_AnyMessageStreamPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStreamPtr; @@ -147,6 +152,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + AnnouncementsStream + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -303,6 +314,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + AnnouncementsStream + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -459,6 +476,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + AnnouncementsStream + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -618,6 +641,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected String dco_decode_String(dynamic raw); + @protected + AnnouncementInfo dco_decode_announcement_info(dynamic raw); + + @protected + AnnouncementSeverity dco_decode_announcement_severity(dynamic raw); + + @protected + AnnouncementText dco_decode_announcement_text(dynamic raw); + @protected AppSettings dco_decode_app_settings(dynamic raw); @@ -859,6 +891,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_String(dynamic raw); + @protected + List dco_decode_list_announcement_info(dynamic raw); + + @protected + List dco_decode_list_announcement_text(dynamic raw); + @protected List dco_decode_list_bond_claim(dynamic raw); @@ -1199,6 +1237,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + AnnouncementsStream + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1355,6 +1399,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + AnnouncementsStream + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1511,6 +1561,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + AnnouncementsStream + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1670,6 +1726,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected String sse_decode_String(SseDeserializer deserializer); + @protected + AnnouncementInfo sse_decode_announcement_info(SseDeserializer deserializer); + + @protected + AnnouncementSeverity sse_decode_announcement_severity( + SseDeserializer deserializer, + ); + + @protected + AnnouncementText sse_decode_announcement_text(SseDeserializer deserializer); + @protected AppSettings sse_decode_app_settings(SseDeserializer deserializer); @@ -1953,6 +2020,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_String(SseDeserializer deserializer); + @protected + List sse_decode_list_announcement_info( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_announcement_text( + SseDeserializer deserializer, + ); + @protected List sse_decode_list_bond_claim(SseDeserializer deserializer); @@ -2374,6 +2451,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2556,6 +2640,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2738,6 +2829,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2923,6 +3021,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_String(String self, SseSerializer serializer); + @protected + void sse_encode_announcement_info( + AnnouncementInfo self, + SseSerializer serializer, + ); + + @protected + void sse_encode_announcement_severity( + AnnouncementSeverity self, + SseSerializer serializer, + ); + + @protected + void sse_encode_announcement_text( + AnnouncementText self, + SseSerializer serializer, + ); + @protected void sse_encode_app_settings(AppSettings self, SseSerializer serializer); @@ -3319,6 +3435,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_String(List self, SseSerializer serializer); + @protected + void sse_encode_list_announcement_info( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_announcement_text( + List self, + SseSerializer serializer, + ); + @protected void sse_encode_list_bond_claim( List self, @@ -3847,6 +3975,40 @@ class RustLibWire implements BaseWire { RustLibWire(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStreamPtr = + _lookup)>>( + 'frbgen_mostro_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream', + ); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStreamPtr + .asFunction)>(); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStreamPtr = + _lookup)>>( + 'frbgen_mostro_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream', + ); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStreamPtr + .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( ffi.Pointer ptr, diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index a0e93e13e..93c25847c 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -7,6 +7,7 @@ // ignore_for_file: argument_type_not_assignable import 'api.dart'; +import 'api/announcements.dart'; import 'api/bond.dart'; import 'api/cashu.dart'; import 'api/disputes.dart'; @@ -43,6 +44,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_AnnouncementsStreamPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_AnyMessageStreamPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream; @@ -149,6 +154,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException dco_decode_AnyhowException(dynamic raw); + @protected + AnnouncementsStream + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -305,6 +316,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + AnnouncementsStream + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -461,6 +478,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + AnnouncementsStream + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + dynamic raw, + ); + @protected AnyMessageStream dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -620,6 +643,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected String dco_decode_String(dynamic raw); + @protected + AnnouncementInfo dco_decode_announcement_info(dynamic raw); + + @protected + AnnouncementSeverity dco_decode_announcement_severity(dynamic raw); + + @protected + AnnouncementText dco_decode_announcement_text(dynamic raw); + @protected AppSettings dco_decode_app_settings(dynamic raw); @@ -861,6 +893,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_String(dynamic raw); + @protected + List dco_decode_list_announcement_info(dynamic raw); + + @protected + List dco_decode_list_announcement_text(dynamic raw); + @protected List dco_decode_list_bond_claim(dynamic raw); @@ -1201,6 +1239,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + @protected + AnnouncementsStream + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1357,6 +1401,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + AnnouncementsStream + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1513,6 +1563,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + AnnouncementsStream + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + SseDeserializer deserializer, + ); + @protected AnyMessageStream sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -1672,6 +1728,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected String sse_decode_String(SseDeserializer deserializer); + @protected + AnnouncementInfo sse_decode_announcement_info(SseDeserializer deserializer); + + @protected + AnnouncementSeverity sse_decode_announcement_severity( + SseDeserializer deserializer, + ); + + @protected + AnnouncementText sse_decode_announcement_text(SseDeserializer deserializer); + @protected AppSettings sse_decode_app_settings(SseDeserializer deserializer); @@ -1955,6 +2022,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_String(SseDeserializer deserializer); + @protected + List sse_decode_list_announcement_info( + SseDeserializer deserializer, + ); + + @protected + List sse_decode_list_announcement_text( + SseDeserializer deserializer, + ); + @protected List sse_decode_list_bond_claim(SseDeserializer deserializer); @@ -2376,6 +2453,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2558,6 +2642,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2740,6 +2831,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + AnnouncementsStream self, + SseSerializer serializer, + ); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( @@ -2925,6 +3023,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_String(String self, SseSerializer serializer); + @protected + void sse_encode_announcement_info( + AnnouncementInfo self, + SseSerializer serializer, + ); + + @protected + void sse_encode_announcement_severity( + AnnouncementSeverity self, + SseSerializer serializer, + ); + + @protected + void sse_encode_announcement_text( + AnnouncementText self, + SseSerializer serializer, + ); + @protected void sse_encode_app_settings(AppSettings self, SseSerializer serializer); @@ -3321,6 +3437,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_String(List self, SseSerializer serializer); + @protected + void sse_encode_list_announcement_info( + List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_list_announcement_text( + List self, + SseSerializer serializer, + ); + @protected void sse_encode_list_bond_claim( List self, @@ -3840,6 +3968,22 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { class RustLibWire implements BaseWire { RustLibWire.fromExternalLibrary(ExternalLibrary lib); + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr, + ); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( int ptr, @@ -4263,6 +4407,16 @@ external RustLibWasmModule get wasmModule; @JS() @anonymous extension type RustLibWasmModule._(JSObject _) implements JSObject { + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + int ptr, + ); + + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + int ptr, + ); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( int ptr, diff --git a/rust/src/api/announcements.rs b/rust/src/api/announcements.rs new file mode 100644 index 000000000..2eff496e1 --- /dev/null +++ b/rust/src/api/announcements.rs @@ -0,0 +1,275 @@ +//! The announcement channel's bridge surface +//! (`specs/006-announcement-channel/spec.md` §6.1, §7): what Dart reads, the +//! stream it follows, the Announcements toggle, and the read / dismissed +//! flags it reports back. +//! +//! Dart renders what this hands it and decides nothing: every announcement +//! here already passed the reader's door (`nostr::announcement_reader`), and +//! it carries all seven locales because Rust does not translate. + +use anyhow::{anyhow, bail, Result}; +use nostr_sdk::prelude::*; +use tokio::sync::broadcast; +use tokio::sync::broadcast::error::RecvError; + +use crate::api::types::{AnnouncementInfo, AnnouncementSeverity, AnnouncementText}; +use crate::db::{settings_keys, Storage}; +use crate::nostr::announcement_reader::{self, CurrentAnnouncement}; +use crate::nostr::announcements::{self, Severity}; + +/// Every announcement the cache holds right now: `critical` first, then +/// newest first (§3.4), dismissed ones included — a dismissed `critical` +/// stays listed and Dart is the one that knows (§3.4). Empty before the +/// database is up. +pub async fn get_announcements() -> Result> { + let Some(db) = crate::db::app_db::db() else { + return Ok(Vec::new()); + }; + let current = announcement_reader::restore( + db, + &announcements::allowed_authors(), + Timestamp::now(), + &announcements::app_version(), + ) + .await?; + Ok(current.iter().map(to_info).collect()) +} + +/// The Announcements toggle (§7): on unless the user turned it off. +pub async fn get_announcements_enabled() -> Result { + let db = crate::db::app_db::db().ok_or_else(|| anyhow!("StorageUnavailable"))?; + Ok(announcement_reader::enabled_from_setting( + db.get_setting(settings_keys::ANNOUNCEMENTS_ENABLED) + .await? + .as_deref(), + )) +} + +/// Flip the toggle. Off closes the relay subscription at the tap and +/// discards anything queued behind it; on reopens it, with the same 30-day +/// window a fresh install gets (§7). Persisted first: the subscription +/// follows the setting, never the other way round. +pub async fn set_announcements_enabled(enabled: bool) -> Result<()> { + let db = crate::db::app_db::db().ok_or_else(|| anyhow!("StorageUnavailable"))?; + db.set_setting( + settings_keys::ANNOUNCEMENTS_ENABLED, + if enabled { "true" } else { "false" }, + ) + .await?; + announcement_reader::set_enabled(enabled).await; + Ok(()) +} + +/// The user saw the announcement at `address`. Rust holds the flag because +/// it is Rust that decides whether a later revision re-announces (§5.3). +pub async fn mark_announcement_read(address: String) -> Result<()> { + set_flags(&address, Some(true), None).await +} + +/// The user swiped the announcement at `address` away. Read as well: a +/// dismissed notice never counts as unread, whichever level keeps it listed. +pub async fn dismiss_announcement(address: String) -> Result<()> { + set_flags(&address, Some(true), Some(true)).await +} + +async fn set_flags(address: &str, read: Option, dismissed: Option) -> Result<()> { + let db = crate::db::app_db::db().ok_or_else(|| anyhow!("StorageUnavailable"))?; + if !announcement_reader::set_flags(db, address, read, dismissed).await? { + // Expired or swept since the card was drawn: nothing to record, and + // the next emit takes the card with it. + log::debug!("[announcements] {address} is no longer cached; flag dropped"); + } + publish_current().await; + Ok(()) +} + +/// The bridge's view of a cached announcement. +pub(crate) fn to_info(current: &CurrentAnnouncement) -> AnnouncementInfo { + let announcement = ¤t.announcement; + let body = &announcement.body; + AnnouncementInfo { + address: current.address.clone(), + revision: announcement_reader::revision_of(announcement), + created_at: announcement.created_at.as_secs() as i64, + expiration: body.expiration.as_secs() as i64, + severity: match body.severity { + Severity::Info => AnnouncementSeverity::Info, + Severity::Warning => AnnouncementSeverity::Warning, + Severity::Critical => AnnouncementSeverity::Critical, + }, + texts: body + .texts + .iter() + .map(|text| AnnouncementText { + locale: text.locale.clone(), + title: text.title.clone(), + body: text.body.clone(), + }) + .collect(), + url: body.url.clone(), + read: current.read, + dismissed: current.dismissed, + } +} + +// ── Stream ──────────────────────────────────────────────────────────────────── + +/// A few snapshots at most sit unread: each is the whole list, so a lagging +/// subscriber loses nothing by skipping to the newest. +const CHANNEL_CAPACITY: usize = 8; + +fn tx() -> &'static broadcast::Sender> { + static TX: std::sync::OnceLock>> = + std::sync::OnceLock::new(); + TX.get_or_init(|| broadcast::channel(CHANNEL_CAPACITY).0) +} + +/// Hand Dart the cache as it stands. Called with the result of every pass +/// that may have changed it: a sweep, an arrival, a flag. +pub(crate) fn emit(current: &[CurrentAnnouncement]) { + // An error only means nobody is listening yet. + let _ = tx().send(current.iter().map(to_info).collect()); +} + +/// Re-read the cache and [`emit`] it. For the paths that changed one row +/// and do not hold the whole list. +pub(crate) async fn publish_current() { + match get_announcements().await { + Ok(list) => { + let _ = tx().send(list); + } + Err(e) => log::warn!("[announcements] re-reading the cache failed: {e}"), + } +} + +/// The cache, whole, every time it changes (§6.1). +pub struct AnnouncementsStream { + rx: broadcast::Receiver>, +} + +impl AnnouncementsStream { + /// The next snapshot; a lag skips to the newest rather than ending the + /// stream, since every snapshot is the whole list. + pub async fn next(&mut self) -> Result> { + loop { + match self.rx.recv().await { + Ok(list) => return Ok(list), + Err(RecvError::Lagged(_)) => continue, + Err(RecvError::Closed) => bail!("AnnouncementsStream closed: sender dropped"), + } + } + } +} + +/// Subscribe before the first [`get_announcements`], so a snapshot landing +/// in between is not missed. +pub fn on_announcements_changed() -> AnnouncementsStream { + AnnouncementsStream { + rx: tx().subscribe(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::nostr::announcements::{parse_body, Announcement}; + use serde_json::json; + + fn current(severity: &str, read: bool, dismissed: bool) -> CurrentAnnouncement { + let keys = Keys::generate(); + let locale = |l: &str| json!({ "title": format!("T {l}"), "body": "B" }); + let content = json!({ + "v": 1, + "severity": severity, + "locales": { + "en": locale("en"), "es": locale("es"), "fr": locale("fr"), + "de": locale("de"), "it": locale("it"), "nl": locale("nl"), + "pt": locale("pt"), + }, + "url": "https://mostro.network/blog", + }) + .to_string(); + let tags = vec![ + Tag::identifier("release-2.1"), + Tag::expiration(Timestamp::from_secs(1_900_000_000)), + ]; + let event = EventBuilder::new(Kind::from(38387u16), &content) + .tags(tags.clone()) + .custom_created_at(Timestamp::from_secs(1_800_000_000)) + .finalize(&keys) + .unwrap(); + CurrentAnnouncement { + address: announcement_reader::address_of(&keys.public_key(), "release-2.1"), + announcement: Announcement { + author: keys.public_key(), + event_id: event.id, + created_at: event.created_at, + body: parse_body(&Tags::from_list(tags), &content).unwrap(), + }, + read, + dismissed, + } + } + + #[test] + fn the_bridge_view_carries_every_locale_and_the_flags() { + // Arrange + let current = current("critical", true, false); + + // Act + let info = to_info(¤t); + + // Assert + assert_eq!(info.address, current.address); + assert_eq!( + info.revision, + format!("1800000000:{}", current.announcement.event_id.to_hex()) + ); + assert_eq!(info.created_at, 1_800_000_000); + assert_eq!(info.expiration, 1_900_000_000); + assert_eq!(info.severity, AnnouncementSeverity::Critical); + assert_eq!(info.url.as_deref(), Some("https://mostro.network/blog")); + assert!(info.read); + assert!(!info.dismissed); + let locales: Vec<&str> = info.texts.iter().map(|t| t.locale.as_str()).collect(); + assert_eq!(locales, announcements::SUPPORTED_LOCALES); + assert_eq!(info.texts[1].title, "T es"); + } + + #[test] + fn each_severity_maps_to_its_own_level() { + for (token, level) in [ + ("info", AnnouncementSeverity::Info), + ("warning", AnnouncementSeverity::Warning), + ("critical", AnnouncementSeverity::Critical), + ] { + assert_eq!(to_info(¤t(token, false, false)).severity, level); + } + } + + #[tokio::test] + async fn an_emit_reaches_a_subscriber_whole() { + // Arrange: subscribed before the emit, as Dart must be. + let mut stream = on_announcements_changed(); + let list = vec![current("info", false, true)]; + + // Act + emit(&list); + + // Assert: other tests emit too, so read until this list arrives. + loop { + let got = stream.next().await.unwrap(); + if got.len() == 1 && got[0].address == list[0].address { + assert!(got[0].dismissed); + break; + } + } + } + + #[test] + fn the_toggle_defaults_to_on() { + assert!(announcement_reader::enabled_from_setting(None)); + assert!(announcement_reader::enabled_from_setting(Some("true"))); + assert!(!announcement_reader::enabled_from_setting(Some("false"))); + } +} diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index 3b2dc5324..f7beb7ae1 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -1,3 +1,4 @@ +pub mod announcements; pub mod bond; pub mod bridge_handler; pub mod cashu; diff --git a/rust/src/api/types.rs b/rust/src/api/types.rs index e55f88ee6..2e26c1d45 100644 --- a/rust/src/api/types.rs +++ b/rust/src/api/types.rs @@ -172,6 +172,54 @@ impl PushPlatform { } } +/// How loudly an announcement is painted (specs/006-announcement-channel +/// §3.4). The publisher declares a level, never a colour; Dart maps it onto +/// the palette. A level this build does not know arrives as `Warning`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum AnnouncementSeverity { + /// Releases, new features, events. + Info, + /// Outages, a relay being retired, anything with a deadline. + Warning, + /// A security issue the user must act on now. + Critical, +} + +/// One locale's copy of an announcement, plain text (§3.2). +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct AnnouncementText { + /// `en`, `es`, … — one of the app's locales. + pub locale: String, + pub title: String, + pub body: String, +} + +/// A project announcement the reader admitted (§5.2), with every locale: Rust +/// does not translate, Dart picks the copy for the locale on screen. +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct AnnouncementInfo { + /// `38387::` — the announcement's identity across + /// revisions, and the id of its notification card. + pub address: String, + /// `:`: changes with every correction published + /// under the same address, which is what makes it unread again (§5.3). + pub revision: String, + /// Unix seconds, the event's `created_at`. + pub created_at: i64, + /// Unix seconds, the NIP-40 `expiration`: the announcement is gone once + /// it passes, online or not (§5.5). + pub expiration: i64, + pub severity: AnnouncementSeverity, + /// Every supported locale, in the app's order. + pub texts: Vec, + /// The one action link, `https` only, as parsed. + pub url: Option, + pub read: bool, + /// Swiped away. A `Critical` stays listed, read, until it expires; the + /// other levels leave the list (§3.4). + pub dismissed: bool, +} + /// What the notification settings screen shows about push registration /// (docs/PUSH_NOTIFICATIONS.md §8.1, §9.1). Capability (can this platform /// push at all) and permission are Dart's to know; this is the token and diff --git a/rust/src/db/mod.rs b/rust/src/db/mod.rs index 441242a98..a309fc7ab 100644 --- a/rust/src/db/mod.rs +++ b/rust/src/db/mod.rs @@ -85,6 +85,13 @@ pub mod settings_keys { /// unix seconds of the `403`; each entry clears per §7.1. pub const PUSH_NODE_REFUSALS: &str = "push_node_refusals"; + // ── Announcements (specs/006-announcement-channel §7) ──────────────────── + + /// The Announcements toggle, `"true"` / `"false"`; absent reads as + /// enabled. Device-scoped, like the push toggle: it says whether this + /// install opens the announcement subscription, not anything about a user. + pub const ANNOUNCEMENTS_ENABLED: &str = "announcements_enabled"; + /// User-added Mostro nodes, JSON array of `crate::api::nodes::CustomNode`. /// The trusted registry is compiled in (`crate::config::TRUSTED_MOSTRO_NODES`); /// only user additions are persisted. diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index f5fdc382a..f9fc3c2be 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -25,6 +25,7 @@ // Section: imports +use crate::api::announcements::*; use crate::api::bond::*; use crate::api::cashu::*; use crate::api::disputes::*; @@ -53,7 +54,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1544659396; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -703973155; // Section: executor @@ -61,6 +62,64 @@ pub use crate::api::bridge_handler::FLUTTER_RUST_BRIDGE_HANDLER; // Section: wire_funcs +fn wire__crate__api__announcements__AnnouncementsStream_next_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "AnnouncementsStream_next", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, true, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref_mut().await) + } + _ => unreachable!(), + } + } + let mut api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::announcements::AnnouncementsStream::next( + &mut *api_that_guard, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__messages__AnyMessageStream_next_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -3243,6 +3302,43 @@ fn wire__crate__api__nwc__disconnect_wallet_impl( }, ) } +fn wire__crate__api__announcements__dismiss_announcement_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "dismiss_announcement", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_address = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::announcements::dismiss_announcement(api_address).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__messages__download_attachment_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -3653,6 +3749,77 @@ fn wire__crate__api__identity__funds_at_risk_impl( }, ) } +fn wire__crate__api__announcements__get_announcements_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "get_announcements", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::announcements::get_announcements().await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__announcements__get_announcements_enabled_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "get_announcements_enabled", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::announcements::get_announcements_enabled().await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__get_app_version_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5312,6 +5479,43 @@ fn wire__crate__api__nwc__make_invoice_impl( }, ) } +fn wire__crate__api__announcements__mark_announcement_read_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "mark_announcement_read", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_address = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::announcements::mark_announcement_read(api_address).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__messages__mark_as_read_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5381,6 +5585,39 @@ fn wire__crate__api__nodes__node_metadata_default_impl( }, ) } +fn wire__crate__api__announcements__on_announcements_changed_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "on_announcements_changed", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let output_ok = + Result::<_, ()>::Ok(crate::api::announcements::on_announcements_changed())?; + Ok(output_ok) + })()) + } + }, + ) +} fn wire__crate__api__messages__on_any_new_message_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -7416,6 +7653,44 @@ fn wire__crate__api__settings__set_active_mostro_node_impl( }, ) } +fn wire__crate__api__announcements__set_announcements_enabled_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "set_announcements_enabled", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_enabled = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::announcements::set_announcements_enabled(api_enabled) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__escrow__set_cashu_mint_url_override_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -8318,6 +8593,9 @@ fn wire__crate__api__identity__validate_mnemonic_impl( // Section: related_funcs +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); @@ -8407,6 +8685,16 @@ impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseDecode for AnnouncementsStream { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + impl SseDecode for AnyMessageStream { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8667,6 +8955,16 @@ impl SseDecode for WalletStatusStream { } } +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + impl SseDecode for RustOpaqueMoi> { @@ -8941,6 +9239,59 @@ impl SseDecode for String { } } +impl SseDecode for crate::api::types::AnnouncementInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_address = ::sse_decode(deserializer); + let mut var_revision = ::sse_decode(deserializer); + let mut var_createdAt = ::sse_decode(deserializer); + let mut var_expiration = ::sse_decode(deserializer); + let mut var_severity = ::sse_decode(deserializer); + let mut var_texts = >::sse_decode(deserializer); + let mut var_url = >::sse_decode(deserializer); + let mut var_read = ::sse_decode(deserializer); + let mut var_dismissed = ::sse_decode(deserializer); + return crate::api::types::AnnouncementInfo { + address: var_address, + revision: var_revision, + created_at: var_createdAt, + expiration: var_expiration, + severity: var_severity, + texts: var_texts, + url: var_url, + read: var_read, + dismissed: var_dismissed, + }; + } +} + +impl SseDecode for crate::api::types::AnnouncementSeverity { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return match inner { + 0 => crate::api::types::AnnouncementSeverity::Info, + 1 => crate::api::types::AnnouncementSeverity::Warning, + 2 => crate::api::types::AnnouncementSeverity::Critical, + _ => unreachable!("Invalid variant for AnnouncementSeverity: {}", inner), + }; + } +} + +impl SseDecode for crate::api::types::AnnouncementText { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_locale = ::sse_decode(deserializer); + let mut var_title = ::sse_decode(deserializer); + let mut var_body = ::sse_decode(deserializer); + return crate::api::types::AnnouncementText { + locale: var_locale, + title: var_title, + body: var_body, + }; + } +} + impl SseDecode for crate::api::types::AppSettings { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9653,6 +10004,34 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -11292,607 +11671,651 @@ fn pde_ffi_dispatcher_primary_impl( ) { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 1 => wire__crate__api__messages__AnyMessageStream_next_impl( + 1 => wire__crate__api__announcements__AnnouncementsStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 2 => wire__crate__api__messages__AttachmentProgressStream_next_impl( + 2 => wire__crate__api__messages__AnyMessageStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 3 => wire__crate__api__bond__BondClaimStream_next_impl(port, ptr, rust_vec_len, data_len), - 4 => wire__crate__api__bond__BondSlashedStream_next_impl(port, ptr, rust_vec_len, data_len), - 5 => { + 3 => wire__crate__api__messages__AttachmentProgressStream_next_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 4 => wire__crate__api__bond__BondClaimStream_next_impl(port, ptr, rust_vec_len, data_len), + 5 => wire__crate__api__bond__BondSlashedStream_next_impl(port, ptr, rust_vec_len, data_len), + 6 => { wire__crate__api__cashu__CashuWalletStream_next_impl(port, ptr, rust_vec_len, data_len) } - 6 => wire__crate__api__nostr__ConnectionStateStream_next_impl( + 7 => wire__crate__api__nostr__ConnectionStateStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 7 => wire__crate__api__disputes__DisputeStream_next_impl(port, ptr, rust_vec_len, data_len), - 8 => { + 8 => wire__crate__api__disputes__DisputeStream_next_impl(port, ptr, rust_vec_len, data_len), + 9 => { wire__crate__api__escrow__EscrowModeStream_next_impl(port, ptr, rust_vec_len, data_len) } - 9 => wire__crate__api__logging__LogEntryStream_next_impl(port, ptr, rust_vec_len, data_len), 10 => { + wire__crate__api__logging__LogEntryStream_next_impl(port, ptr, rust_vec_len, data_len) + } + 11 => { wire__crate__api__messages__MessageStream_next_impl(port, ptr, rust_vec_len, data_len) } - 11 => wire__crate__api__messages__MessageUpdateStream_next_impl( + 12 => wire__crate__api__messages__MessageUpdateStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 12 => wire__crate__api__my_reputation__MyReputationStream_next_impl( + 13 => wire__crate__api__my_reputation__MyReputationStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 13 => wire__crate__api__orders__OrderBook_clear_impl(port, ptr, rust_vec_len, data_len), - 14 => wire__crate__api__orders__OrderBook_default_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__orders__OrderBook_get_order_impl(port, ptr, rust_vec_len, data_len), - 16 => { + 14 => wire__crate__api__orders__OrderBook_clear_impl(port, ptr, rust_vec_len, data_len), + 15 => wire__crate__api__orders__OrderBook_default_impl(port, ptr, rust_vec_len, data_len), + 16 => wire__crate__api__orders__OrderBook_get_order_impl(port, ptr, rust_vec_len, data_len), + 17 => { wire__crate__api__orders__OrderBook_get_orders_impl(port, ptr, rust_vec_len, data_len) } - 17 => wire__crate__api__orders__OrderBook_new_impl(port, ptr, rust_vec_len, data_len), - 18 => { + 18 => wire__crate__api__orders__OrderBook_new_impl(port, ptr, rust_vec_len, data_len), + 19 => { wire__crate__api__orders__OrderBook_remove_order_impl(port, ptr, rust_vec_len, data_len) } - 19 => { + 20 => { wire__crate__api__orders__OrderBook_set_orders_impl(port, ptr, rust_vec_len, data_len) } - 20 => wire__crate__api__orders__OrderBook_update_order_status_impl( + 21 => wire__crate__api__orders__OrderBook_update_order_status_impl( port, ptr, rust_vec_len, data_len, ), - 21 => { + 22 => { wire__crate__api__orders__OrderBook_upsert_order_impl(port, ptr, rust_vec_len, data_len) } - 22 => { + 23 => { wire__crate__api__orders__OrderDeltaStream_next_impl(port, ptr, rust_vec_len, data_len) } - 23 => wire__crate__api__orders__OrdersStream_next_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__push__PushStatusStream_next_impl(port, ptr, rust_vec_len, data_len), - 25 => { + 24 => wire__crate__api__orders__OrdersStream_next_impl(port, ptr, rust_vec_len, data_len), + 25 => wire__crate__api__push__PushStatusStream_next_impl(port, ptr, rust_vec_len, data_len), + 26 => { wire__crate__api__reputation__RatingStream_next_impl(port, ptr, rust_vec_len, data_len) } - 26 => wire__crate__api__nostr__RelayAutoSyncStream_next_impl( + 27 => wire__crate__api__nostr__RelayAutoSyncStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 27 => { + 28 => { wire__crate__api__nostr__RelayStatusStream_next_impl(port, ptr, rust_vec_len, data_len) } - 28 => wire__crate__api__restore_progress__RestoreProgressStream_next_impl( + 29 => wire__crate__api__restore_progress__RestoreProgressStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 29 => { + 30 => { wire__crate__api__settings__SettingsStream_next_impl(port, ptr, rust_vec_len, data_len) } - 30 => wire__crate__api__identity__TradeKeyIndexStream_next_impl( + 31 => wire__crate__api__identity__TradeKeyIndexStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 31 => wire__crate__api__trade_touch__TradeTouchStream_next_impl( + 32 => wire__crate__api__trade_touch__TradeTouchStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 32 => wire__crate__api__orders__TradeUpdatesStream_next_impl( + 33 => wire__crate__api__orders__TradeUpdatesStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 33 => wire__crate__api__messages__UnreadCountStream_next_impl( + 34 => wire__crate__api__messages__UnreadCountStream_next_impl( port, ptr, rust_vec_len, data_len, ), - 34 => { + 35 => { wire__crate__api__nwc__WalletStatusStream_next_impl(port, ptr, rust_vec_len, data_len) } - 35 => wire__crate__api__bond__abandon_bonded_order_impl(port, ptr, rust_vec_len, data_len), - 36 => { + 36 => wire__crate__api__bond__abandon_bonded_order_impl(port, ptr, rust_vec_len, data_len), + 37 => { wire__crate__api__nodes__add_custom_mostro_node_impl(port, ptr, rust_vec_len, data_len) } - 37 => wire__crate__api__nostr__add_relay_impl(port, ptr, rust_vec_len, data_len), - 38 => { + 38 => wire__crate__api__nostr__add_relay_impl(port, ptr, rust_vec_len, data_len), + 39 => { wire__crate__api__messages__attachment_web_probe_impl(port, ptr, rust_vec_len, data_len) } - 39 => wire__crate__api__types__bond_claim_key_impl(port, ptr, rust_vec_len, data_len), - 40 => wire__crate__api__types__bond_claim_phase_is_terminal_impl( + 40 => wire__crate__api__types__bond_claim_key_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__types__bond_claim_phase_is_terminal_impl( port, ptr, rust_vec_len, data_len, ), - 41 => { + 42 => { wire__crate__api__types__bond_claim_storage_id_impl(port, ptr, rust_vec_len, data_len) } - 42 => wire__crate__api__types__bond_policy_default_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__crate__api__types__bond_policy_info_default_impl( + 43 => wire__crate__api__types__bond_policy_default_impl(port, ptr, rust_vec_len, data_len), + 44 => wire__crate__api__types__bond_policy_info_default_impl( port, ptr, rust_vec_len, data_len, ), - 44 => wire__crate__api__node_stats__cached_mostro_node_stats_impl( + 45 => wire__crate__api__node_stats__cached_mostro_node_stats_impl( port, ptr, rust_vec_len, data_len, ), - 45 => wire__crate__api__my_reputation__cached_my_reputation_impl( + 46 => wire__crate__api__my_reputation__cached_my_reputation_impl( port, ptr, rust_vec_len, data_len, ), - 46 => wire__crate__api__orders__cancel_order_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__cashu__cashu_connect_impl(port, ptr, rust_vec_len, data_len), - 48 => wire__crate__api__cashu__cashu_create_token_impl(port, ptr, rust_vec_len, data_len), - 49 => wire__crate__api__cashu__cashu_disconnect_impl(port, ptr, rust_vec_len, data_len), - 50 => wire__crate__api__cashu__cashu_escrow_quote_impl(port, ptr, rust_vec_len, data_len), - 51 => wire__crate__api__cashu__cashu_get_balance_impl(port, ptr, rust_vec_len, data_len), - 52 => wire__crate__api__cashu__cashu_melt_impl(port, ptr, rust_vec_len, data_len), - 53 => wire__crate__api__cashu__cashu_melt_quote_impl(port, ptr, rust_vec_len, data_len), - 54 => wire__crate__api__cashu__cashu_receive_token_impl(port, ptr, rust_vec_len, data_len), - 55 => wire__crate__api__cashu__cashu_status_impl(port, ptr, rust_vec_len, data_len), - 56 => wire__crate__api__cashu__cashu_sweep_spent_proofs_impl( + 47 => wire__crate__api__orders__cancel_order_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__cashu__cashu_connect_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__crate__api__cashu__cashu_create_token_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__cashu__cashu_disconnect_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__cashu__cashu_escrow_quote_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__cashu__cashu_get_balance_impl(port, ptr, rust_vec_len, data_len), + 53 => wire__crate__api__cashu__cashu_melt_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__cashu__cashu_melt_quote_impl(port, ptr, rust_vec_len, data_len), + 55 => wire__crate__api__cashu__cashu_receive_token_impl(port, ptr, rust_vec_len, data_len), + 56 => wire__crate__api__cashu__cashu_status_impl(port, ptr, rust_vec_len, data_len), + 57 => wire__crate__api__cashu__cashu_sweep_spent_proofs_impl( port, ptr, rust_vec_len, data_len, ), - 57 => { + 58 => { wire__crate__api__invoice__check_buyer_invoice_impl(port, ptr, rust_vec_len, data_len) } - 58 => wire__crate__api__reputation_transfer__check_reputation_import_impl( + 59 => wire__crate__api__reputation_transfer__check_reputation_import_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 60 => wire__crate__api__invoice__classify_payment_destination_impl( port, ptr, rust_vec_len, data_len, ), - 59 => wire__crate__api__invoice__classify_payment_destination_impl( + 61 => wire__crate__api__logging__clear_logs_impl(port, ptr, rust_vec_len, data_len), + 62 => wire__crate__api__push__clear_push_token_impl(port, ptr, rust_vec_len, data_len), + 63 => wire__crate__api__bond__close_expired_bond_window_impl( port, ptr, rust_vec_len, data_len, ), - 60 => wire__crate__api__logging__clear_logs_impl(port, ptr, rust_vec_len, data_len), - 61 => wire__crate__api__push__clear_push_token_impl(port, ptr, rust_vec_len, data_len), - 62 => wire__crate__api__bond__close_expired_bond_window_impl( + 64 => wire__crate__api__nwc__connect_wallet_impl(port, ptr, rust_vec_len, data_len), + 65 => wire__crate__api__identity__create_identity_impl(port, ptr, rust_vec_len, data_len), + 66 => wire__crate__api__orders__create_order_impl(port, ptr, rust_vec_len, data_len), + 67 => wire__crate__api__invoice__decode_bolt11_impl(port, ptr, rust_vec_len, data_len), + 68 => wire__crate__api__identity__delete_identity_impl(port, ptr, rust_vec_len, data_len), + 69 => wire__crate__api__identity__derive_trade_key_impl(port, ptr, rust_vec_len, data_len), + 70 => wire__crate__api__nwc__disconnect_wallet_impl(port, ptr, rust_vec_len, data_len), + 71 => wire__crate__api__announcements__dismiss_announcement_impl( port, ptr, rust_vec_len, data_len, ), - 63 => wire__crate__api__nwc__connect_wallet_impl(port, ptr, rust_vec_len, data_len), - 64 => wire__crate__api__identity__create_identity_impl(port, ptr, rust_vec_len, data_len), - 65 => wire__crate__api__orders__create_order_impl(port, ptr, rust_vec_len, data_len), - 66 => wire__crate__api__invoice__decode_bolt11_impl(port, ptr, rust_vec_len, data_len), - 67 => wire__crate__api__identity__delete_identity_impl(port, ptr, rust_vec_len, data_len), - 68 => wire__crate__api__identity__derive_trade_key_impl(port, ptr, rust_vec_len, data_len), - 69 => wire__crate__api__nwc__disconnect_wallet_impl(port, ptr, rust_vec_len, data_len), - 70 => { + 72 => { wire__crate__api__messages__download_attachment_impl(port, ptr, rust_vec_len, data_len) } - 71 => wire__crate__api__bond__estimate_bond_sats_impl(port, ptr, rust_vec_len, data_len), - 72 => wire__crate__api__identity__export_encrypted_backup_impl( + 73 => wire__crate__api__bond__estimate_bond_sats_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__identity__export_encrypted_backup_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 75 => wire__crate__api__reputation_transfer__export_reputation_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 76 => wire__crate__api__nostr__fetch_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 77 => wire__crate__api__nostr__fetch_mostro_instance_tags_impl( port, ptr, rust_vec_len, data_len, ), - 73 => wire__crate__api__reputation_transfer__export_reputation_impl( + 78 => wire__crate__api__node_stats__fetch_mostro_node_stats_impl( port, ptr, rust_vec_len, data_len, ), - 74 => wire__crate__api__nostr__fetch_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 75 => wire__crate__api__nostr__fetch_mostro_instance_tags_impl( + 79 => wire__crate__api__nostr__fetch_price_sources_impl(port, ptr, rust_vec_len, data_len), + 80 => wire__crate__api__nostr__flush_message_queue_impl(port, ptr, rust_vec_len, data_len), + 81 => wire__crate__api__nodes__forget_mostro_node_picture_impl( port, ptr, rust_vec_len, data_len, ), - 76 => wire__crate__api__node_stats__fetch_mostro_node_stats_impl( + 82 => wire__crate__api__identity__funds_at_risk_impl(port, ptr, rust_vec_len, data_len), + 83 => wire__crate__api__announcements__get_announcements_impl( port, ptr, rust_vec_len, data_len, ), - 77 => wire__crate__api__nostr__fetch_price_sources_impl(port, ptr, rust_vec_len, data_len), - 78 => wire__crate__api__nostr__flush_message_queue_impl(port, ptr, rust_vec_len, data_len), - 79 => wire__crate__api__nodes__forget_mostro_node_picture_impl( + 84 => wire__crate__api__announcements__get_announcements_enabled_impl( port, ptr, rust_vec_len, data_len, ), - 80 => wire__crate__api__identity__funds_at_risk_impl(port, ptr, rust_vec_len, data_len), - 81 => wire__crate__api__get_app_version_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__crate__api__messages__get_attachment_status_impl( + 85 => wire__crate__api__get_app_version_impl(port, ptr, rust_vec_len, data_len), + 86 => wire__crate__api__messages__get_attachment_status_impl( port, ptr, rust_vec_len, data_len, ), - 83 => wire__crate__api__nwc__get_balance_impl(port, ptr, rust_vec_len, data_len), - 84 => wire__crate__api__bond__get_bond_claim_impl(port, ptr, rust_vec_len, data_len), - 85 => wire__crate__api__bond__get_bond_claim_from_impl(port, ptr, rust_vec_len, data_len), - 86 => wire__crate__api__bond__get_bond_policy_impl(port, ptr, rust_vec_len, data_len), - 87 => wire__crate__api__nostr__get_connection_state_impl(port, ptr, rust_vec_len, data_len), - 88 => wire__crate__api__disputes__get_dispute_impl(port, ptr, rust_vec_len, data_len), - 89 => wire__crate__api__escrow__get_escrow_mode_impl(port, ptr, rust_vec_len, data_len), - 90 => wire__crate__api__identity__get_identity_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__messages__get_messages_impl(port, ptr, rust_vec_len, data_len), - 92 => { + 87 => wire__crate__api__nwc__get_balance_impl(port, ptr, rust_vec_len, data_len), + 88 => wire__crate__api__bond__get_bond_claim_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__bond__get_bond_claim_from_impl(port, ptr, rust_vec_len, data_len), + 90 => wire__crate__api__bond__get_bond_policy_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__nostr__get_connection_state_impl(port, ptr, rust_vec_len, data_len), + 92 => wire__crate__api__disputes__get_dispute_impl(port, ptr, rust_vec_len, data_len), + 93 => wire__crate__api__escrow__get_escrow_mode_impl(port, ptr, rust_vec_len, data_len), + 94 => wire__crate__api__identity__get_identity_impl(port, ptr, rust_vec_len, data_len), + 95 => wire__crate__api__messages__get_messages_impl(port, ptr, rust_vec_len, data_len), + 96 => { wire__crate__api__nodes__get_mostro_node_picture_impl(port, ptr, rust_vec_len, data_len) } - 93 => wire__crate__api__settings__get_mostro_pubkey_impl(port, ptr, rust_vec_len, data_len), - 94 => wire__crate__api__identity__get_nym_identity_impl(port, ptr, rust_vec_len, data_len), - 95 => wire__crate__api__orders__get_order_impl(port, ptr, rust_vec_len, data_len), - 96 => wire__crate__api__orders__get_order_book_snapshot_impl( + 97 => wire__crate__api__settings__get_mostro_pubkey_impl(port, ptr, rust_vec_len, data_len), + 98 => wire__crate__api__identity__get_nym_identity_impl(port, ptr, rust_vec_len, data_len), + 99 => wire__crate__api__orders__get_order_impl(port, ptr, rust_vec_len, data_len), + 100 => wire__crate__api__orders__get_order_book_snapshot_impl( port, ptr, rust_vec_len, data_len, ), - 97 => wire__crate__api__orders__get_orders_impl(port, ptr, rust_vec_len, data_len), - 98 => wire__crate__api__reputation_transfer__get_pending_reputation_attestation_impl( + 101 => wire__crate__api__orders__get_orders_impl(port, ptr, rust_vec_len, data_len), + 102 => wire__crate__api__reputation_transfer__get_pending_reputation_attestation_impl( port, ptr, rust_vec_len, data_len, ), - 99 => { + 103 => { wire__crate__api__reputation__get_privacy_mode_impl(port, ptr, rust_vec_len, data_len) } - 100 => wire__crate__api__push__get_push_status_impl(port, ptr, rust_vec_len, data_len), - 101 => wire__crate__api__reputation__get_rating_for_trade_impl( + 104 => wire__crate__api__push__get_push_status_impl(port, ptr, rust_vec_len, data_len), + 105 => wire__crate__api__reputation__get_rating_for_trade_impl( port, ptr, rust_vec_len, data_len, ), - 102 => wire__crate__api__nostr__get_relays_impl(port, ptr, rust_vec_len, data_len), - 104 => wire__crate__api__settings__get_settings_impl(port, ptr, rust_vec_len, data_len), - 105 => wire__crate__api__identity__get_trade_key_impl(port, ptr, rust_vec_len, data_len), - 106 => wire__crate__api__orders__get_trade_role_impl(port, ptr, rust_vec_len, data_len), - 107 => wire__crate__api__messages__get_unread_count_impl(port, ptr, rust_vec_len, data_len), - 108 => wire__crate__api__nwc__get_wallet_impl(port, ptr, rust_vec_len, data_len), - 109 => wire__crate__api__disputes__handle_admin_canceled_impl( + 106 => wire__crate__api__nostr__get_relays_impl(port, ptr, rust_vec_len, data_len), + 108 => wire__crate__api__settings__get_settings_impl(port, ptr, rust_vec_len, data_len), + 109 => wire__crate__api__identity__get_trade_key_impl(port, ptr, rust_vec_len, data_len), + 110 => wire__crate__api__orders__get_trade_role_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__messages__get_unread_count_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__nwc__get_wallet_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__disputes__handle_admin_canceled_impl( port, ptr, rust_vec_len, data_len, ), - 110 => { + 114 => { wire__crate__api__disputes__handle_admin_settled_impl(port, ptr, rust_vec_len, data_len) } - 111 => wire__crate__api__disputes__handle_admin_took_dispute_impl( + 115 => wire__crate__api__disputes__handle_admin_took_dispute_impl( port, ptr, rust_vec_len, data_len, ), - 112 => wire__crate__api__reputation__handle_rating_received_impl( + 116 => wire__crate__api__reputation__handle_rating_received_impl( port, ptr, rust_vec_len, data_len, ), - 113 => wire__crate__api__identity__has_pending_identity_wipe_impl( + 117 => wire__crate__api__identity__has_pending_identity_wipe_impl( port, ptr, rust_vec_len, data_len, ), - 114 => { + 118 => { wire__crate__api__identity__import_from_mnemonic_impl(port, ptr, rust_vec_len, data_len) } - 115 => wire__crate__api__identity__import_from_nsec_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__reputation_transfer__import_reputation_impl( + 119 => wire__crate__api__identity__import_from_nsec_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__reputation_transfer__import_reputation_impl( port, ptr, rust_vec_len, data_len, ), - 117 => wire__crate__api__logging__init_app_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__init_db_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__nostr__initialize_impl(port, ptr, rust_vec_len, data_len), - 120 => { + 121 => wire__crate__api__logging__init_app_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__init_db_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__nostr__initialize_impl(port, ptr, rust_vec_len, data_len), + 124 => { wire__crate__api__logging__install_log_bridge_impl(port, ptr, rust_vec_len, data_len) } - 121 => wire__crate__api__bond__list_bond_claims_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__nodes__list_mostro_nodes_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__orders__list_trades_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__identity__load_identity_from_mnemonic_impl( + 125 => wire__crate__api__bond__list_bond_claims_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__nodes__list_mostro_nodes_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__orders__list_trades_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__identity__load_identity_from_mnemonic_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 129 => wire__crate__api__cashu__lock_escrow_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__nwc__make_invoice_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__announcements__mark_announcement_read_impl( port, ptr, rust_vec_len, data_len, ), - 125 => wire__crate__api__cashu__lock_escrow_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__nwc__make_invoice_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__messages__mark_as_read_impl(port, ptr, rust_vec_len, data_len), - 128 => { + 132 => wire__crate__api__messages__mark_as_read_impl(port, ptr, rust_vec_len, data_len), + 133 => { wire__crate__api__nodes__node_metadata_default_impl(port, ptr, rust_vec_len, data_len) } - 129 => { + 134 => wire__crate__api__announcements__on_announcements_changed_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 135 => { wire__crate__api__messages__on_any_new_message_impl(port, ptr, rust_vec_len, data_len) } - 130 => wire__crate__api__messages__on_attachment_progress_impl( + 136 => wire__crate__api__messages__on_attachment_progress_impl( port, ptr, rust_vec_len, data_len, ), - 131 => { + 137 => { wire__crate__api__bond__on_bond_claim_updated_impl(port, ptr, rust_vec_len, data_len) } - 132 => wire__crate__api__bond__on_bond_slashed_impl(port, ptr, rust_vec_len, data_len), - 133 => { + 138 => wire__crate__api__bond__on_bond_slashed_impl(port, ptr, rust_vec_len, data_len), + 139 => { wire__crate__api__cashu__on_cashu_wallet_changed_impl(port, ptr, rust_vec_len, data_len) } - 134 => wire__crate__api__nostr__on_connection_state_changed_impl( + 140 => wire__crate__api__nostr__on_connection_state_changed_impl( port, ptr, rust_vec_len, data_len, ), - 135 => { + 141 => { wire__crate__api__disputes__on_dispute_updated_impl(port, ptr, rust_vec_len, data_len) } - 136 => { + 142 => { wire__crate__api__escrow__on_escrow_mode_changed_impl(port, ptr, rust_vec_len, data_len) } - 137 => wire__crate__api__logging__on_log_entry_impl(port, ptr, rust_vec_len, data_len), - 138 => { + 143 => wire__crate__api__logging__on_log_entry_impl(port, ptr, rust_vec_len, data_len), + 144 => { wire__crate__api__messages__on_message_updated_impl(port, ptr, rust_vec_len, data_len) } - 139 => wire__crate__api__my_reputation__on_my_reputation_changed_impl( + 145 => wire__crate__api__my_reputation__on_my_reputation_changed_impl( port, ptr, rust_vec_len, data_len, ), - 140 => wire__crate__api__messages__on_new_message_impl(port, ptr, rust_vec_len, data_len), - 141 => wire__crate__api__orders__on_order_deltas_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__orders__on_orders_updated_impl(port, ptr, rust_vec_len, data_len), - 143 => { + 146 => wire__crate__api__messages__on_new_message_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__orders__on_order_deltas_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__orders__on_orders_updated_impl(port, ptr, rust_vec_len, data_len), + 149 => { wire__crate__api__push__on_push_status_changed_impl(port, ptr, rust_vec_len, data_len) } - 144 => { + 150 => { wire__crate__api__reputation__on_rating_received_impl(port, ptr, rust_vec_len, data_len) } - 145 => { + 151 => { wire__crate__api__nostr__on_relay_auto_synced_impl(port, ptr, rust_vec_len, data_len) } - 146 => { + 152 => { wire__crate__api__nostr__on_relay_status_changed_impl(port, ptr, rust_vec_len, data_len) } - 147 => wire__crate__api__restore_progress__on_restore_progress_impl( + 153 => wire__crate__api__restore_progress__on_restore_progress_impl( port, ptr, rust_vec_len, data_len, ), - 148 => { + 154 => { wire__crate__api__settings__on_settings_changed_impl(port, ptr, rust_vec_len, data_len) } - 149 => wire__crate__api__identity__on_trade_key_index_changed_impl( + 155 => wire__crate__api__identity__on_trade_key_index_changed_impl( port, ptr, rust_vec_len, data_len, ), - 150 => { + 156 => { wire__crate__api__trade_touch__on_trade_touched_impl(port, ptr, rust_vec_len, data_len) } - 151 => wire__crate__api__orders__on_trade_updated_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__messages__on_unread_count_changed_impl( + 157 => wire__crate__api__orders__on_trade_updated_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__messages__on_unread_count_changed_impl( port, ptr, rust_vec_len, data_len, ), - 153 => { + 159 => { wire__crate__api__nwc__on_wallet_status_changed_impl(port, ptr, rust_vec_len, data_len) } - 154 => wire__crate__api__disputes__open_dispute_impl(port, ptr, rust_vec_len, data_len), - 155 => { + 160 => wire__crate__api__disputes__open_dispute_impl(port, ptr, rust_vec_len, data_len), + 161 => { wire__crate__api__orders__order_filters_default_impl(port, ptr, rust_vec_len, data_len) } - 157 => wire__crate__api__nwc__pay_invoice_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__orders__payout_amount_impl(port, ptr, rust_vec_len, data_len), - 159 => { + 163 => wire__crate__api__nwc__pay_invoice_impl(port, ptr, rust_vec_len, data_len), + 164 => wire__crate__api__orders__payout_amount_impl(port, ptr, rust_vec_len, data_len), + 165 => { wire__crate__api__orders__payout_destinations_impl(port, ptr, rust_vec_len, data_len) } - 160 => { + 166 => { wire__crate__api__types__push_platform_as_wire_impl(port, ptr, rust_vec_len, data_len) } - 161 => { + 167 => { wire__crate__api__types__push_platform_from_wire_impl(port, ptr, rust_vec_len, data_len) } - 162 => wire__crate__api__logging__recent_logs_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__push__reconcile_push_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__orders__recover_trades_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__node_stats__refresh_mostro_node_info_cache_impl( + 168 => wire__crate__api__logging__recent_logs_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__push__reconcile_push_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__orders__recover_trades_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__node_stats__refresh_mostro_node_info_cache_impl( port, ptr, rust_vec_len, data_len, ), - 166 => wire__crate__api__nodes__refresh_mostro_node_metadata_impl( + 172 => wire__crate__api__nodes__refresh_mostro_node_metadata_impl( port, ptr, rust_vec_len, data_len, ), - 167 => wire__crate__api__my_reputation__refresh_my_reputation_impl( + 173 => wire__crate__api__my_reputation__refresh_my_reputation_impl( port, ptr, rust_vec_len, data_len, ), - 168 => wire__crate__api__settings__rehydrate_active_mostro_node_impl( + 174 => wire__crate__api__settings__rehydrate_active_mostro_node_impl( port, ptr, rust_vec_len, data_len, ), - 169 => wire__crate__api__escrow__rehydrate_escrow_overrides_impl( + 175 => wire__crate__api__escrow__rehydrate_escrow_overrides_impl( port, ptr, rust_vec_len, data_len, ), - 170 => wire__crate__api__orders__release_order_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__nodes__remove_custom_mostro_node_impl( + 176 => wire__crate__api__orders__release_order_impl(port, ptr, rust_vec_len, data_len), + 177 => wire__crate__api__nodes__remove_custom_mostro_node_impl( port, ptr, rust_vec_len, data_len, ), - 172 => wire__crate__api__nostr__remove_relay_impl(port, ptr, rust_vec_len, data_len), - 174 => wire__crate__api__orders__request_bond_invoice_again_impl( + 178 => wire__crate__api__nostr__remove_relay_impl(port, ptr, rust_vec_len, data_len), + 180 => wire__crate__api__orders__request_bond_invoice_again_impl( port, ptr, rust_vec_len, data_len, ), - 175 => { + 181 => { wire__crate__api__order_link__resolve_order_link_impl(port, ptr, rust_vec_len, data_len) } - 176 => wire__crate__api__orders__restart_orders_subscription_impl( + 182 => wire__crate__api__orders__restart_orders_subscription_impl( port, ptr, rust_vec_len, data_len, ), - 177 => wire__crate__api__identity__restore_identity_session_impl( + 183 => wire__crate__api__identity__restore_identity_session_impl( port, ptr, rust_vec_len, data_len, ), - 178 => wire__crate__api__nostr__resync_impl(port, ptr, rust_vec_len, data_len), - 179 => { + 184 => wire__crate__api__nostr__resync_impl(port, ptr, rust_vec_len, data_len), + 185 => { wire__crate__api__disputes__send_dispute_file_impl(port, ptr, rust_vec_len, data_len) } - 180 => wire__crate__api__orders__send_fiat_sent_impl(port, ptr, rust_vec_len, data_len), - 181 => wire__crate__api__messages__send_file_impl(port, ptr, rust_vec_len, data_len), - 182 => wire__crate__api__orders__send_invoice_impl(port, ptr, rust_vec_len, data_len), - 183 => wire__crate__api__messages__send_message_impl(port, ptr, rust_vec_len, data_len), - 184 => wire__crate__api__messages__send_reaction_impl(port, ptr, rust_vec_len, data_len), - 185 => wire__crate__api__settings__set_active_mostro_node_impl( + 186 => wire__crate__api__orders__send_fiat_sent_impl(port, ptr, rust_vec_len, data_len), + 187 => wire__crate__api__messages__send_file_impl(port, ptr, rust_vec_len, data_len), + 188 => wire__crate__api__orders__send_invoice_impl(port, ptr, rust_vec_len, data_len), + 189 => wire__crate__api__messages__send_message_impl(port, ptr, rust_vec_len, data_len), + 190 => wire__crate__api__messages__send_reaction_impl(port, ptr, rust_vec_len, data_len), + 191 => wire__crate__api__settings__set_active_mostro_node_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 192 => wire__crate__api__announcements__set_announcements_enabled_impl( port, ptr, rust_vec_len, data_len, ), - 186 => wire__crate__api__escrow__set_cashu_mint_url_override_impl( + 193 => wire__crate__api__escrow__set_cashu_mint_url_override_impl( port, ptr, rust_vec_len, data_len, ), - 187 => wire__crate__api__settings__set_default_fiat_code_impl( + 194 => wire__crate__api__settings__set_default_fiat_code_impl( port, ptr, rust_vec_len, data_len, ), - 188 => wire__crate__api__settings__set_default_lightning_address_impl( + 195 => wire__crate__api__settings__set_default_lightning_address_impl( port, ptr, rust_vec_len, data_len, ), - 189 => wire__crate__api__escrow__set_escrow_mode_override_impl( + 196 => wire__crate__api__escrow__set_escrow_mode_override_impl( port, ptr, rust_vec_len, data_len, ), - 190 => wire__crate__api__settings__set_language_impl(port, ptr, rust_vec_len, data_len), - 191 => { + 197 => wire__crate__api__settings__set_language_impl(port, ptr, rust_vec_len, data_len), + 198 => { wire__crate__api__settings__set_logging_enabled_impl(port, ptr, rust_vec_len, data_len) } - 192 => { + 199 => { wire__crate__api__reputation__set_privacy_mode_impl(port, ptr, rust_vec_len, data_len) } - 193 => wire__crate__api__push__set_push_enabled_impl(port, ptr, rust_vec_len, data_len), - 194 => wire__crate__api__push__set_push_token_impl(port, ptr, rust_vec_len, data_len), - 195 => wire__crate__api__settings__set_test_order_expiry_impl( + 200 => wire__crate__api__push__set_push_enabled_impl(port, ptr, rust_vec_len, data_len), + 201 => wire__crate__api__push__set_push_token_impl(port, ptr, rust_vec_len, data_len), + 202 => wire__crate__api__settings__set_test_order_expiry_impl( port, ptr, rust_vec_len, data_len, ), - 196 => wire__crate__api__settings__set_theme_impl(port, ptr, rust_vec_len, data_len), - 197 => wire__crate__api__disputes__share_chat_key_with_solver_impl( + 203 => wire__crate__api__settings__set_theme_impl(port, ptr, rust_vec_len, data_len), + 204 => wire__crate__api__disputes__share_chat_key_with_solver_impl( port, ptr, rust_vec_len, data_len, ), - 198 => wire__crate__api__reputation_transfer__sign_reputation_rebind_impl( + 205 => wire__crate__api__reputation_transfer__sign_reputation_rebind_impl( port, ptr, rust_vec_len, data_len, ), - 199 => wire__crate__api__disputes__solver_role_impl(port, ptr, rust_vec_len, data_len), - 200 => wire__crate__api__bond__submit_bond_payout_invoice_impl( + 206 => wire__crate__api__disputes__solver_role_impl(port, ptr, rust_vec_len, data_len), + 207 => wire__crate__api__bond__submit_bond_payout_invoice_impl( port, ptr, rust_vec_len, data_len, ), - 201 => wire__crate__api__disputes__submit_evidence_impl(port, ptr, rust_vec_len, data_len), - 202 => wire__crate__api__reputation__submit_rating_impl(port, ptr, rust_vec_len, data_len), - 203 => wire__crate__api__orders__subscribe_orders_impl(port, ptr, rust_vec_len, data_len), - 204 => wire__crate__api__nodes__sync_mostro_node_pictures_impl( + 208 => wire__crate__api__disputes__submit_evidence_impl(port, ptr, rust_vec_len, data_len), + 209 => wire__crate__api__reputation__submit_rating_impl(port, ptr, rust_vec_len, data_len), + 210 => wire__crate__api__orders__subscribe_orders_impl(port, ptr, rust_vec_len, data_len), + 211 => wire__crate__api__nodes__sync_mostro_node_pictures_impl( port, ptr, rust_vec_len, data_len, ), - 205 => wire__crate__api__orders__take_order_impl(port, ptr, rust_vec_len, data_len), - 206 => wire__crate__api__escrow_deadline__trade_escrow_deadline_impl( + 212 => wire__crate__api__orders__take_order_impl(port, ptr, rust_vec_len, data_len), + 213 => wire__crate__api__escrow_deadline__trade_escrow_deadline_impl( port, ptr, rust_vec_len, data_len, ), - 207 => wire__crate__api__orders__trade_node_of_impl(port, ptr, rust_vec_len, data_len), - 208 => { + 214 => wire__crate__api__orders__trade_node_of_impl(port, ptr, rust_vec_len, data_len), + 215 => { wire__crate__api__invoice__trade_step_started_at_impl(port, ptr, rust_vec_len, data_len) } - 209 => { + 216 => { wire__crate__api__identity__validate_mnemonic_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -11907,17 +12330,17 @@ fn pde_ffi_dispatcher_sync_impl( ) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 103 => wire__crate__api__reputation_transfer__get_reputation_support_impl( + 107 => wire__crate__api__reputation_transfer__get_reputation_support_impl( ptr, rust_vec_len, data_len, ), - 156 => wire__crate__api__reputation_transfer__parse_reputation_attestation_impl( + 162 => wire__crate__api__reputation_transfer__parse_reputation_attestation_impl( ptr, rust_vec_len, data_len, ), - 173 => wire__crate__api__reputation_transfer__reputation_identity_npub_impl( + 179 => wire__crate__api__reputation_transfer__reputation_identity_npub_impl( ptr, rust_vec_len, data_len, @@ -11928,6 +12351,24 @@ fn pde_ffi_dispatcher_sync_impl( // Section: rust2dart +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} + +impl flutter_rust_bridge::IntoIntoDart> for AnnouncementsStream { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -12351,6 +12792,78 @@ impl flutter_rust_bridge::IntoIntoDart> for Walle } } +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::types::AnnouncementInfo { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.address.into_into_dart().into_dart(), + self.revision.into_into_dart().into_dart(), + self.created_at.into_into_dart().into_dart(), + self.expiration.into_into_dart().into_dart(), + self.severity.into_into_dart().into_dart(), + self.texts.into_into_dart().into_dart(), + self.url.into_into_dart().into_dart(), + self.read.into_into_dart().into_dart(), + self.dismissed.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::types::AnnouncementInfo +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::types::AnnouncementInfo +{ + fn into_into_dart(self) -> crate::api::types::AnnouncementInfo { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::types::AnnouncementSeverity { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + Self::Info => 0.into_dart(), + Self::Warning => 1.into_dart(), + Self::Critical => 2.into_dart(), + _ => unreachable!(), + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::types::AnnouncementSeverity +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::types::AnnouncementSeverity +{ + fn into_into_dart(self) -> crate::api::types::AnnouncementSeverity { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::types::AnnouncementText { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.locale.into_into_dart().into_dart(), + self.title.into_into_dart().into_dart(), + self.body.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::types::AnnouncementText +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::types::AnnouncementText +{ + fn into_into_dart(self) -> crate::api::types::AnnouncementText { + self + } +} // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::types::AppSettings { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -14400,6 +14913,13 @@ impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { } } +impl SseEncode for AnnouncementsStream { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + impl SseEncode for AnyMessageStream { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -14597,6 +15117,17 @@ impl SseEncode for WalletStatusStream { } } +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + impl SseEncode for RustOpaqueMoi> { @@ -14896,6 +15427,47 @@ impl SseEncode for String { } } +impl SseEncode for crate::api::types::AnnouncementInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.address, serializer); + ::sse_encode(self.revision, serializer); + ::sse_encode(self.created_at, serializer); + ::sse_encode(self.expiration, serializer); + ::sse_encode(self.severity, serializer); + >::sse_encode(self.texts, serializer); + >::sse_encode(self.url, serializer); + ::sse_encode(self.read, serializer); + ::sse_encode(self.dismissed, serializer); + } +} + +impl SseEncode for crate::api::types::AnnouncementSeverity { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode( + match self { + crate::api::types::AnnouncementSeverity::Info => 0, + crate::api::types::AnnouncementSeverity::Warning => 1, + crate::api::types::AnnouncementSeverity::Critical => 2, + _ => { + unimplemented!(""); + } + }, + serializer, + ); + } +} + +impl SseEncode for crate::api::types::AnnouncementText { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.locale, serializer); + ::sse_encode(self.title, serializer); + ::sse_encode(self.body, serializer); + } +} + impl SseEncode for crate::api::types::AppSettings { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -15491,6 +16063,26 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -16860,6 +17452,7 @@ mod io { // Section: imports use super::*; + use crate::api::announcements::*; use crate::api::bond::*; use crate::api::cashu::*; use crate::api::disputes::*; @@ -16886,6 +17479,20 @@ mod io { flutter_rust_bridge::frb_generated_boilerplate_io!(); + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_mostro_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_mostro_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[unsafe(no_mangle)] pub extern "C" fn frbgen_mostro_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( ptr: *const std::ffi::c_void, @@ -17262,6 +17869,7 @@ mod web { // Section: imports use super::*; + use crate::api::announcements::*; use crate::api::bond::*; use crate::api::cashu::*; use crate::api::disputes::*; @@ -17290,6 +17898,20 @@ mod web { flutter_rust_bridge::frb_generated_boilerplate_web!(); + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnouncementsStream( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnyMessageStream( ptr: *const std::ffi::c_void, diff --git a/rust/src/nostr/announcement_reader.rs b/rust/src/nostr/announcement_reader.rs index ed1665baa..fdba29a64 100644 --- a/rust/src/nostr/announcement_reader.rs +++ b/rust/src/nostr/announcement_reader.rs @@ -19,7 +19,7 @@ use nostr_sdk::prelude::*; use semver::Version; use serde::{Deserialize, Serialize}; -use crate::db::Storage; +use crate::db::{settings_keys, Storage}; use crate::nostr::announcements::{ self, admit, Announcement, AnnouncementError, Severity, KIND_ANNOUNCEMENT, }; @@ -101,6 +101,17 @@ pub fn address_of(author: &PublicKey, identifier: &str) -> String { format!("{KIND_ANNOUNCEMENT}:{}:{identifier}", author.to_hex()) } +/// The revision of an announcement as Dart sees it: `created_at` and the +/// event id, the pair [`replaceable_rank`] orders by. Two revisions at one +/// address are the same text only when this is equal. +pub fn revision_of(announcement: &Announcement) -> String { + format!( + "{}:{}", + announcement.created_at.as_secs(), + announcement.event_id.to_hex() + ) +} + /// §5.2 steps 1–6, at `now`, for an app at `version`. Step 7 — winning at /// its address — needs the cache, and is [`ingest`]'s. pub fn door( @@ -308,6 +319,38 @@ async fn sweep( Ok(kept) } +/// Record what the user did with the announcement at `address` (§6.1): a +/// `read` and a `dismissed` flag, each left alone when `None`. The flags +/// belong to the cached revision — a correction arriving later starts +/// unread again. Returns `false` when the address is not cached: nothing +/// may refer to an address the cache no longer holds, and a flag for one +/// that just expired is not an error. +pub async fn set_flags( + db: &S, + address: &str, + read: Option, + dismissed: Option, +) -> anyhow::Result { + let _section = exclusive().await; + let Some(row) = db + .list_announcements() + .await? + .into_iter() + .find(|row| row.address == address) + else { + return Ok(false); + }; + let updated = StoredAnnouncement { + read: read.unwrap_or(row.read), + dismissed: dismissed.unwrap_or(row.dismissed), + ..row.clone() + }; + if updated != row { + db.save_announcement(&updated).await?; + } + Ok(true) +} + /// A cached row through the door again, from its signed event. fn recheck( row: &StoredAnnouncement, @@ -335,20 +378,83 @@ impl Drop for LoopGuard { } } -/// Bring the channel up to date: re-check the cache against the clock, then -/// start the relay loop or, when it already runs, move its filter's window -/// to now. Called on every `Online` and every resume, like the order book; -/// with an empty allowlist it does nothing at all. +/// The Announcements toggle (§7), mirrored from the settings table by +/// [`subscribe_announcements`] and [`set_enabled`], so the relay pump can +/// check it per event without a database read. Off means the subscription +/// is closed and whatever still arrives behind it is discarded. +static ENABLED: AtomicBool = AtomicBool::new(true); + +/// What a stored toggle value means: absent reads as enabled (§7, default on). +pub fn enabled_from_setting(value: Option<&str>) -> bool { + value != Some("false") +} + +/// Whether the channel is on, as of the last subscribe or toggle. +pub fn is_enabled() -> bool { + ENABLED.load(Ordering::Acquire) +} + +async fn load_enabled(db: &S) -> bool { + enabled_from_setting( + db.get_setting(settings_keys::ANNOUNCEMENTS_ENABLED) + .await + .ok() + .flatten() + .as_deref(), + ) +} + +/// Apply the toggle, already persisted by the caller: on reopens the +/// subscription through [`subscribe_announcements`], off closes it at the +/// tap — nothing waits for the next background transition (§7). +pub async fn set_enabled(enabled: bool) { + ENABLED.store(enabled, Ordering::Release); + if enabled { + subscribe_announcements().await; + } else { + close_subscription().await; + } +} + +/// Close the relay subscription, if one was ever opened. The pump task +/// stays: it is gated by [`ENABLED`], and a later on re-issues the filter. +async fn close_subscription() { + if !LOOP_ACTIVE.load(Ordering::Acquire) { + return; + } + if let Ok(pool) = crate::api::nostr::get_pool() { + crate::nostr::live_subs::live_subs() + .close(&pool.client(), &SubscriptionId::new(SUBSCRIPTION_ID)) + .await; + log::info!("[announcements] subscription closed: toggle off"); + } +} + +/// Bring the channel up to date: re-check the cache against the clock, hand +/// Dart what is left, then start the relay loop or, when it already runs, +/// move its filter's window to now. Called on every `Online` and every +/// resume, like the order book; with an empty allowlist, or the toggle off, +/// nothing is subscribed — the cache is still swept, since what it holds is +/// the last thing the project said and the expiry rule holds offline (§5.4). pub async fn subscribe_announcements() { let authors = announcements::allowed_authors(); let version = announcements::app_version(); + let mut enabled = true; // Even with no key left to subscribe to: a release that retires the last // one must still sweep what that key left in the cache. if let Some(db) = crate::db::app_db::db() { - if let Err(e) = restore(db, &authors, Timestamp::now(), &version).await { - log::warn!("[announcements] re-checking the cache failed: {e}"); + enabled = load_enabled(db).await; + match restore(db, &authors, Timestamp::now(), &version).await { + Ok(current) => crate::api::announcements::emit(¤t), + Err(e) => log::warn!("[announcements] re-checking the cache failed: {e}"), } } + ENABLED.store(enabled, Ordering::Release); + if !enabled { + close_subscription().await; + log::debug!("[announcements] toggle off: no subscription"); + return; + } let Some(filter) = announcement_filter(&authors, Timestamp::now()) else { log::debug!("[announcements] allowlist empty: no subscription"); return; @@ -407,10 +513,20 @@ async fn run_subscription(authors: Vec, filter: Filter, version: Vers if subscription_id != id { continue; } + // Checked per event, after the subscription was closed: an event + // queued behind the close is discarded, as the toggle promises (§7). + if !is_enabled() { + log::debug!("[announcements] {} discarded: toggle off", event.id); + continue; + } let Some(db) = crate::db::app_db::db() else { continue; }; match ingest(db, &event, &authors, Timestamp::now(), &version).await { + Ok(outcome @ (Ingested::New | Ingested::Superseded)) => { + log::info!("[announcements] {}: {outcome:?}", event.id); + crate::api::announcements::publish_current().await; + } Ok(outcome) => log::debug!("[announcements] {}: {outcome:?}", event.id), Err(e) => log::warn!("[announcements] storing {} failed: {e}", event.id), } @@ -982,6 +1098,71 @@ mod tests { assert_eq!(current[0].announcement.body.severity, Severity::Critical); } + // ── Read and dismissed (§6.1) ─────────────────────────────────────── + + #[tokio::test] + async fn flags_are_recorded_on_the_cached_row() { + // Arrange + let db = store().await; + let keys = Keys::generate(); + let allow = [keys.public_key()]; + let event = draft("flags").sign(&keys); + ingest_now(&db, &event, &allow).await; + let address = address_of(&keys.public_key(), "flags"); + + // Act + let read = set_flags(&db, &address, Some(true), None).await.unwrap(); + let dismissed = set_flags(&db, &address, None, Some(true)).await.unwrap(); + + // Assert: both persisted, each leaving the other alone. + assert!(read && dismissed); + let current = restore(&db, &allow, now(), &app()).await.unwrap(); + assert!(current[0].read); + assert!(current[0].dismissed); + } + + #[tokio::test] + async fn a_flag_for_an_address_not_cached_is_dropped() { + let db = store().await; + + let recorded = set_flags(&db, "38387:aa:gone", Some(true), None) + .await + .unwrap(); + + assert!(!recorded); + assert!(db.list_announcements().await.unwrap().is_empty()); + } + + #[tokio::test] + async fn a_correction_clears_a_dismissal_too() { + // Arrange: dismissed, then a newer revision at the same address. + let db = store().await; + let keys = Keys::generate(); + let allow = [keys.public_key()]; + ingest_now(&db, &draft("c").sign(&keys), &allow).await; + let address = address_of(&keys.public_key(), "c"); + set_flags(&db, &address, Some(true), Some(true)).await.unwrap(); + + // Act + let outcome = ingest_now(&db, &draft("c").at(NOW + 60).sign(&keys), &allow).await; + + // Assert: the correction is a new notice, not a dismissed one. + assert_eq!(outcome, Ingested::Superseded); + let current = restore(&db, &allow, now(), &app()).await.unwrap(); + assert!(!current[0].read); + assert!(!current[0].dismissed); + } + + // ── The toggle (§7) ───────────────────────────────────────────────── + + #[test] + fn the_toggle_reads_absent_as_on() { + assert!(enabled_from_setting(None)); + assert!(enabled_from_setting(Some("true"))); + assert!(enabled_from_setting(Some("anything else"))); + assert!(!enabled_from_setting(Some("false"))); + } + /// Announcements are addressed to the install: a new identity keeps them /// (CLAUDE.md, "every new store must say which side it is on"). #[tokio::test] diff --git a/specs/006-announcement-channel/spec.md b/specs/006-announcement-channel/spec.md index 4d04302de..c5f7ad075 100644 --- a/specs/006-announcement-channel/spec.md +++ b/specs/006-announcement-channel/spec.md @@ -2,9 +2,10 @@ **Feature Branch**: `006-announcement-channel` **Created**: 2026-08-26 -**Status**: In progress — steps 1 and 2 of §10 are built: parsing and the allowlist in +**Status**: In progress — steps 1 to 3 of §10 are built: parsing and the allowlist in `rust/src/nostr/announcements.rs`, the reader and its cache in -`rust/src/nostr/announcement_reader.rs` +`rust/src/nostr/announcement_reader.rs`, the bridge and the Announcements toggle in +`rust/src/api/announcements.rs` and `lib/features/settings/providers/announcements_provider.dart` **Input**: Give the project one authenticated way to reach people already running the app — "update to 2.1", "the node is down for maintenance", "this relay is gone" — without a backend, an account, an email address, or a push token. @@ -556,6 +557,24 @@ translate." Adding `rust/src/api/announcements.rs` means `./scripts/frb-generate.sh` must run, and the generated `lib/src/rust/` is never hand-edited. +**What the bridge settled** (step 3 of §10): + +- The bridge type is `AnnouncementInfo` (`rust/src/api/types.rs`), to keep clear of the + reader's `Announcement`. Its `revision` is `:` — the pair §5.3 + orders by — so Dart tells a correction from a redelivery by string equality alone. +- `get_announcements()` returns the cache **whole**: `critical` first, then newest first, + dismissed rows included with their `read` and `dismissed` flags. Dart decides what a + dismissed row means by its level (§3.4), so Rust must not filter it out. +- `on_announcements_changed()` emits that same whole list after every pass that may have + changed it — a sweep (every `Online` and every resume), an arrival that won at its + address, a flag. A lagging subscriber skips to the newest snapshot, since each one is + complete. +- `dismiss_announcement` also marks the row read: a dismissed notice never counts as + unread, whichever level keeps it listed. A flag for an address the cache no longer + holds is dropped silently, not an error — the card was drawn before the row expired. +- Read and dismissed belong to the revision: a correction clears both (§5.3), and the + bridge test `a_correction_clears_a_dismissal_too` pins it. + ### 6.2 Rendering Each announcement becomes a `NotificationModel`: @@ -612,6 +631,16 @@ filter asks for on the next open — `since = now - 30 days` is the same window install gets, so an announcement published while the switch was off is picked up if it is still fresh, and is not if it is not. +**How it is built.** The value is the `settings` key `announcements_enabled` +(`"true"` / `"false"`, absent reads as on), device-scoped like the push toggle. The reader +mirrors it into a process flag at every subscribe and at every tap: off closes the +`announcements` subscription through `live_subs` and the relay pump discards, per event, +whatever still arrives behind the close — the pump task itself stays, gated, and the next +on re-issues the filter through the same pump. **Off leaves the cache alone**: what it holds +is the last thing the project said, it stays shown, and the clock still sweeps it (§5.4). +Hiding it would make the switch mean two things. The OS notification permission does not +gate the toggle either: an announcement posts no system notification. + **Default: on.** A judgement call, stated plainly: the channel is low-frequency and product-related, and nothing here posts a system notification, so nothing escapes the app the user just opened. The day it does post one, Android 13+ requires a runtime permission @@ -704,7 +733,7 @@ PR per step, per the workflow in CLAUDE.md. | 0 | ~~Fix the app-version source (§4.3)~~ — **done in this PR** | Version targeting is unusable while the version is not the shipped one, so it could not be left as a follow-up | | 1 | §3 parsing and validation + the §4.1 allowlist, as pure Rust functions — no relay, no DB, no UI | Everything rests on it, and it is the cheapest thing to get wrong quietly. Ships with the allowlist **empty**, which is inert by construction | | 2 | Fetch, verify, freshness, expiry, the `announcements` table and the schema bump (§4.2, §5) | Testable without a screen | -| 3 | The bridge surface + the Announcements toggle (§6.1, §7), then `./scripts/frb-generate.sh` | The off switch before the surface | +| 3 | ~~The bridge surface + the Announcements toggle (§6.1, §7), then `./scripts/frb-generate.sh`~~ — **done** | The off switch before the surface | | 4 | Rendering into the existing notification surface, seven locales of chrome (§6.2) | Last, when there is something to show | | 5 | `rust/src/bin/announce.rs` + the publishing doc (§8) | With or just after step 1, sharing its validator | | 6 | **Add the real npubs** — one line, its own PR, npubs checked against a source outside this repo | The only commit that makes the channel live | diff --git a/test/features/settings/providers/announcements_provider_test.dart b/test/features/settings/providers/announcements_provider_test.dart new file mode 100644 index 000000000..2aec8bd15 --- /dev/null +++ b/test/features/settings/providers/announcements_provider_test.dart @@ -0,0 +1,89 @@ +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:mostro/features/settings/providers/announcements_provider.dart'; + +/// The Announcements toggle (specs/006-announcement-channel §7): the UI +/// answers the tap, Rust is told, and a refused write rolls back. +class _FakeBridge extends AnnouncementsBridge { + _FakeBridge({this.stored = true, this.failSet = false, this.gate}); + + bool stored; + final bool failSet; + + /// When set, [enabled] waits on it: the load is in flight. + final Completer? gate; + final asked = []; + + @override + Future enabled() async { + if (gate != null) await gate!.future; + return stored; + } + + @override + Future setEnabled(bool enabled) async { + asked.add(enabled); + if (failSet) throw Exception('StorageUnavailable'); + stored = enabled; + } +} + +void main() { + test('starts on, then loads what Rust persisted', () async { + // Arrange + final bridge = _FakeBridge(stored: false); + + // Act + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + expect(notifier.state, isTrue); + await Future.delayed(Duration.zero); + + // Assert + expect(notifier.state, isFalse); + }); + + test('a tap is applied first and handed to Rust after', () async { + // Arrange + final bridge = _FakeBridge(); + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + await Future.delayed(Duration.zero); + + // Act + final ok = await notifier.set(false); + + // Assert + expect(ok, isTrue); + expect(notifier.state, isFalse); + expect(bridge.asked, [false]); + }); + + test('a write Rust refuses rolls the toggle back', () async { + // Arrange + final bridge = _FakeBridge(failSet: true); + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + await Future.delayed(Duration.zero); + + // Act + final ok = await notifier.set(false); + + // Assert + expect(ok, isFalse); + expect(notifier.state, isTrue); + }); + + test('a load that lands after a tap does not undo it', () async { + // Arrange: the load is still reading when the user taps. + final gate = Completer(); + final bridge = _FakeBridge(stored: true, gate: gate); + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + + // Act + await notifier.set(false); + gate.complete(); + await Future.delayed(Duration.zero); + + // Assert: the stale `true` the load read is not applied. + expect(notifier.state, isFalse); + }); +} diff --git a/test/features/settings/screens/settings_screens_test.dart b/test/features/settings/screens/settings_screens_test.dart index 0228dc692..287d4a1a5 100644 --- a/test/features/settings/screens/settings_screens_test.dart +++ b/test/features/settings/screens/settings_screens_test.dart @@ -9,6 +9,7 @@ import 'package:mostro/core/automation/automation_ids.dart'; import 'package:mostro/core/settings_palette.dart'; import 'package:mostro/features/about/screens/about_screen.dart' show appVersionProvider; +import 'package:mostro/features/settings/providers/announcements_provider.dart'; import 'package:mostro/features/settings/providers/mostro_nodes_provider.dart'; import 'package:mostro/features/settings/providers/notification_permission_provider.dart'; import 'package:mostro/features/settings/providers/notification_prefs_provider.dart'; @@ -65,6 +66,23 @@ PushStatus _push({ : nodeRefusedUntil.millisecondsSinceEpoch ~/ 1000, ); +/// The Announcements toggle's Rust side, recording what it was asked. +class _RecordingAnnouncements extends AnnouncementsBridge { + _RecordingAnnouncements({this.stored = true}); + + bool stored; + final asked = []; + + @override + Future enabled() async => stored; + + @override + Future setEnabled(bool enabled) async { + asked.add(enabled); + stored = enabled; + } +} + /// Records what the master toggle asked for, without a bridge or a device. class _RecordingToggle implements PushToggle { final asked = []; @@ -86,7 +104,11 @@ List _overrides({ bool pushExpiresWithTab = false, PushStatus? push, PushToggle? toggle, + AnnouncementsBridge? announcements, }) => [ + announcementsBridgeProvider.overrideWithValue( + announcements ?? _RecordingAnnouncements(), + ), pushSupportedProvider.overrideWithValue(pushSupported), pushExpiresWithTabProvider.overrideWithValue(pushExpiresWithTab), pushStatusProvider.overrideWith((ref) => Stream.value(push ?? _push())), @@ -449,8 +471,8 @@ void main() { ) async { await _pump(tester, const NotificationSettingsScreen()); - // The master push toggle, then the four events. - expect(find.byType(MostroToggle), findsNWidgets(5)); + // The master push toggle, the four events, then Announcements. + expect(find.byType(MostroToggle), findsNWidgets(6)); expect(find.text('Trade updates'), findsOneWidget); expect(find.text('Dispute updates'), findsOneWidget); }); @@ -619,8 +641,8 @@ void main() { findsOneWidget, ); expect(_masterToggle, findsNothing); - // The in-app event rows still apply. - expect(find.byType(MostroToggle), findsNWidgets(4)); + // The in-app event rows and Announcements still apply. + expect(find.byType(MostroToggle), findsNWidgets(5)); }); testWidgets('no banner while the system permission is granted', ( @@ -653,6 +675,9 @@ void main() { find.byType(MostroToggle), )) { if (toggle.semanticLabel == 'Push notifications') continue; + // Announcements post no system notification: the OS permission + // does not gate them. + if (toggle.semanticLabel == 'Announcements') continue; expect(toggle.onChanged, isNull); } // Turning push off still unregisters every trade from the server. @@ -721,5 +746,47 @@ void main() { final prefs = await SharedPreferences.getInstance(); expect(prefs.getBool(NotificationEvent.tradeUpdates.prefsKey), isFalse); }); + + // ── Announcements (specs/006 §7) ────────────────────────────────────── + + testWidgets('shows the Announcements toggle with what Rust persisted', ( + tester, + ) async { + await _pump( + tester, + const NotificationSettingsScreen(), + overrides: _overrides( + announcements: _RecordingAnnouncements(stored: false), + ), + ); + await tester.pump(); + + expect(find.text('Announcements'), findsOneWidget); + expect( + find.textContaining('signed by the Mostro project'), + findsOneWidget, + ); + expect(find.textContaining('nothing about you is sent'), findsOneWidget); + expect(tester.widget(_announcementsToggle).value, isFalse); + }); + + testWidgets('turning Announcements off goes through Rust', (tester) async { + final bridge = _RecordingAnnouncements(); + await _pump( + tester, + const NotificationSettingsScreen(), + overrides: _overrides(announcements: bridge), + ); + + await tester.tap(_announcementsToggle); + await tester.pumpAndSettle(); + + expect(bridge.asked, [false]); + expect(tester.widget(_announcementsToggle).value, isFalse); + }); }); } + +final _announcementsToggle = find.byWidgetPredicate( + (w) => w is MostroToggle && w.semanticLabel == 'Announcements', +); From ce9160b37a7ad16f5736b1e341b629550212a8c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Oct 2026 22:30:29 +0000 Subject: [PATCH 2/6] test: regenerate golden files --- ...ngs_10d_notifications_unsupported_dark.png | Bin 12516 -> 12298 bytes ...gs_10d_notifications_unsupported_light.png | Bin 12686 -> 12483 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_dark.png b/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_dark.png index 5a24475badeb093638e2fd2969e23c062a82f0aa..04e3c8c4aa932ac8807a82ff15c9ca1acec5ec21 100644 GIT binary patch literal 12298 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 literal 12516 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 Z34PRv)3q>r@ZS^w&1<@9rB`k5|39cHVY>hT diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_light.png b/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_light.png index f33a4b18f68909eb6433888d18d357f568c3b540..8ef18c781df8a01c8f36150b1f9e281c3da7f998 100644 GIT binary patch literal 12483 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 literal 12686 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 Date: Fri, 23 Oct 2026 21:31:44 -0300 Subject: [PATCH 3/6] fix(announcements): serialize the toggle with refreshes and keep a failed read off Review round 1 (#889). - Rust: a refresh (Online, resume) read the setting, awaited the cache sweep and then stored what it had read, so a tap in between was undone and the subscription reopened with the persisted switch off. Toggle changes and refreshes now take one mutex. - Rust: a failed read of the setting counted as consent; it now keeps the channel off until a later refresh reads it. - Dart: writes of the toggle go one after another, and a refused write re-reads Rust instead of restoring the pre-tap value, which can be the default the load had not yet replaced. - Five settings files that dart format reformatted by mistake are back to main. --- .../providers/announcements_provider.dart | 41 ++++++++-- .../settings/providers/log_provider.dart | 10 +-- .../settings/providers/nwc_provider.dart | 22 ++--- .../settings/providers/settings_provider.dart | 25 +++--- .../widgets/currency_selector_dialog.dart | 80 +++++++++---------- .../settings/widgets/language_selector.dart | 17 ++-- rust/src/nostr/announcement_reader.rs | 49 +++++++++--- .../announcements_provider_test.dart | 66 ++++++++++++++- 8 files changed, 208 insertions(+), 102 deletions(-) diff --git a/lib/features/settings/providers/announcements_provider.dart b/lib/features/settings/providers/announcements_provider.dart index 58622a467..b44f874f2 100644 --- a/lib/features/settings/providers/announcements_provider.dart +++ b/lib/features/settings/providers/announcements_provider.dart @@ -36,14 +36,19 @@ class AnnouncementsEnabledNotifier extends StateNotifier { final AnnouncementsBridge _bridge; - /// The user flipped the toggle before [_load] answered: the load read the - /// setting before that write, so its value is older than the screen's. - bool _touched = false; + /// Taps so far. A load that answers after one read the setting before its + /// write, so its value is older than the screen's; a failed write reloads + /// only when no newer tap has replaced it. + int _taps = 0; + + /// Writes go one after another: two quick taps otherwise race to the + /// store, and the older one can land last. + Future _writes = Future.value(); Future _load() async { try { final enabled = await _bridge.enabled(); - if (mounted && !_touched) state = enabled; + if (mounted && _taps == 0) state = enabled; } catch (e) { debugPrint('[announcements] reading the toggle failed: $e'); } @@ -51,20 +56,40 @@ class AnnouncementsEnabledNotifier extends StateNotifier { /// Applies the change to the UI first and persists after, so the toggle /// answers the tap; a failed write is reported by returning false and the - /// state rolling back. - Future set(bool value) async { + /// toggle going back to what Rust holds. + Future set(bool value) { + final tap = ++_taps; final before = state; - _touched = true; state = value; + final write = _writes.then((_) => _write(value, tap, before)); + _writes = write.then((_) {}); + return write; + } + + Future _write(bool value, int tap, bool before) async { try { await _bridge.setEnabled(value); return true; } catch (e) { debugPrint('[announcements] saving the toggle failed: $e'); - if (mounted) state = before; + if (mounted && tap == _taps) await _reload(tap, before); return false; } } + + /// After a refused write the screen shows a value Rust never took. What it + /// showed before the tap may be stale too — the load can still be in + /// flight — so Rust is asked again; a tap that lands meanwhile wins. + Future _reload(int tap, bool before) async { + bool enabled; + try { + enabled = await _bridge.enabled(); + } catch (e) { + debugPrint('[announcements] re-reading the toggle failed: $e'); + enabled = before; + } + if (mounted && tap == _taps) state = enabled; + } } final announcementsEnabledProvider = diff --git a/lib/features/settings/providers/log_provider.dart b/lib/features/settings/providers/log_provider.dart index b120cda37..45a096ff4 100644 --- a/lib/features/settings/providers/log_provider.dart +++ b/lib/features/settings/providers/log_provider.dart @@ -13,9 +13,8 @@ typedef LogEntryReader = Future Function(); /// The two bridge calls behind function seams, so the merge below can be /// driven in tests without a live bridge. -final logHistoryProvider = Provider> Function()>( - (ref) => logging_api.recentLogs, -); +final logHistoryProvider = + Provider> Function()>((ref) => logging_api.recentLogs); final logStreamProvider = Provider Function()>( (ref) => () async => (await logging_api.onLogEntry()).next, @@ -26,9 +25,8 @@ final logStreamProvider = Provider Function()>( /// Seeded from the Rust ring buffer so the screen opens on the history that led /// to whatever the user is reporting, then followed live. Cancelled when the /// provider is disposed (e.g. when LogReportScreen is popped). -final logEntriesProvider = StreamProvider.autoDispose>(( - ref, -) async* { +final logEntriesProvider = + StreamProvider.autoDispose>((ref) async* { var cancelled = false; ref.onDispose(() => cancelled = true); diff --git a/lib/features/settings/providers/nwc_provider.dart b/lib/features/settings/providers/nwc_provider.dart index 10feb0fa4..f3796e765 100644 --- a/lib/features/settings/providers/nwc_provider.dart +++ b/lib/features/settings/providers/nwc_provider.dart @@ -20,7 +20,6 @@ class NwcWalletState { }) : relayUrls = List.unmodifiable(relayUrls); final String walletPubkey; - /// Immutable list of NWC relay URLs. final List relayUrls; final String? walletName; @@ -31,13 +30,15 @@ class NwcWalletState { List? relayUrls, String? walletName, Object? balanceSats = _unset, - }) => NwcWalletState( - walletPubkey: walletPubkey ?? this.walletPubkey, - relayUrls: relayUrls ?? this.relayUrls, - walletName: walletName ?? this.walletName, - balanceSats: - identical(balanceSats, _unset) ? this.balanceSats : balanceSats as int?, - ); + }) => + NwcWalletState( + walletPubkey: walletPubkey ?? this.walletPubkey, + relayUrls: relayUrls ?? this.relayUrls, + walletName: walletName ?? this.walletName, + balanceSats: identical(balanceSats, _unset) + ? this.balanceSats + : balanceSats as int?, + ); } // ── Notifier ─────────────────────────────────────────────────────────────────── @@ -74,9 +75,8 @@ class NwcNotifier extends StateNotifier { /// Wallet connection state. `null` when no wallet is connected. /// Override in `main()` via [ProviderScope] to inject [SharedPreferences]. -final nwcProvider = StateNotifierProvider( - (ref) => NwcNotifier(), -); +final nwcProvider = + StateNotifierProvider((ref) => NwcNotifier()); /// Convenience: `true` when a wallet is connected. final isWalletConnectedProvider = Provider( diff --git a/lib/features/settings/providers/settings_provider.dart b/lib/features/settings/providers/settings_provider.dart index c347cdd6b..90512f3bd 100644 --- a/lib/features/settings/providers/settings_provider.dart +++ b/lib/features/settings/providers/settings_provider.dart @@ -41,14 +41,12 @@ class AppSettingsState { }) { return AppSettingsState( language: language ?? this.language, - defaultFiatCode: - identical(defaultFiatCode, _unset) - ? this.defaultFiatCode - : defaultFiatCode as String?, - defaultLightningAddress: - identical(defaultLightningAddress, _unset) - ? this.defaultLightningAddress - : defaultLightningAddress as String?, + defaultFiatCode: identical(defaultFiatCode, _unset) + ? this.defaultFiatCode + : defaultFiatCode as String?, + defaultLightningAddress: identical(defaultLightningAddress, _unset) + ? this.defaultLightningAddress + : defaultLightningAddress as String?, loggingEnabled: loggingEnabled ?? this.loggingEnabled, themeMode: themeMode ?? this.themeMode, ); @@ -113,9 +111,9 @@ class SettingsNotifier extends StateNotifier { SharedPreferences? prefs, AppSettingsState? initial, LightningAddressSink? syncLightningAddress, - }) : _prefs = prefs, - _syncLightningAddress = syncLightningAddress, - super(initial ?? const AppSettingsState()); + }) : _prefs = prefs, + _syncLightningAddress = syncLightningAddress, + super(initial ?? const AppSettingsState()); final SharedPreferences? _prefs; final LightningAddressSink? _syncLightningAddress; @@ -189,9 +187,8 @@ class SettingsNotifier extends StateNotifier { /// synchronously before the first frame. final settingsProvider = StateNotifierProvider( - (ref) => - SettingsNotifier(), // no-persistence fallback; replaced in main() - ); + (ref) => SettingsNotifier(), // no-persistence fallback; replaced in main() +); /// Language codes the app ships translations for, derived from the generated /// [AppLocalizations]. Used to validate stored and device languages. diff --git a/lib/features/settings/widgets/currency_selector_dialog.dart b/lib/features/settings/widgets/currency_selector_dialog.dart index 6dbdec3c0..66e4a590d 100644 --- a/lib/features/settings/widgets/currency_selector_dialog.dart +++ b/lib/features/settings/widgets/currency_selector_dialog.dart @@ -22,10 +22,10 @@ class _FiatEntry { final String flag; factory _FiatEntry.fromJson(Map json) => _FiatEntry( - code: (json['code'] as String?) ?? '', - name: (json['name'] as String?) ?? '', - flag: (json['flag'] as String?) ?? '', - ); + code: (json['code'] as String?) ?? '', + name: (json['name'] as String?) ?? '', + flag: (json['flag'] as String?) ?? '', + ); } // ── Widget ──────────────────────────────────────────────────────────────────── @@ -63,12 +63,11 @@ class _CurrencySelectorDialogState try { final raw = await rootBundle.loadString('assets/data/fiat.json'); final List parsed = json.decode(raw) as List; - final entries = - parsed - .cast>() - .map(_FiatEntry.fromJson) - .where((e) => e.code.isNotEmpty) - .toList(); + final entries = parsed + .cast>() + .map(_FiatEntry.fromJson) + .where((e) => e.code.isNotEmpty) + .toList(); if (mounted) { setState(() { _allEntries = entries; @@ -85,11 +84,10 @@ class _CurrencySelectorDialogState void _onSearch() { final query = _searchController.text.toLowerCase(); setState(() { - _filtered = - _allEntries.where((e) { - return e.code.toLowerCase().contains(query) || - e.name.toLowerCase().contains(query); - }).toList(); + _filtered = _allEntries.where((e) { + return e.code.toLowerCase().contains(query) || + e.name.toLowerCase().contains(query); + }).toList(); }); } @@ -101,8 +99,7 @@ class _CurrencySelectorDialogState @override Widget build(BuildContext context) { final colors = Theme.of(context).extension(); - if (colors == null) - throw StateError('AppColors theme extension must be registered'); + if (colors == null) throw StateError('AppColors theme extension must be registered'); final l10n = AppLocalizations.of(context); return Scaffold( @@ -126,33 +123,32 @@ class _CurrencySelectorDialogState ), ), Expanded( - child: - _loading - ? const Center(child: CircularProgressIndicator()) - : _filtered.isEmpty + child: _loading + ? const Center(child: CircularProgressIndicator()) + : _filtered.isEmpty ? Center( - child: Text( - l10n.noCurrenciesFoundMessage, - style: Theme.of(context).textTheme.bodyMedium, - ), - ) + child: Text( + l10n.noCurrenciesFoundMessage, + style: Theme.of(context).textTheme.bodyMedium, + ), + ) : ListView.builder( - itemCount: _filtered.length, - itemBuilder: (context, index) { - final entry = _filtered[index]; - return ListTile( - leading: Text( - entry.flag, - style: const TextStyle(fontSize: 24), - ), - title: Text( - '${entry.code} — ${entry.name}', - style: Theme.of(context).textTheme.bodyLarge, - ), - onTap: () => _select(entry), - ); - }, - ), + itemCount: _filtered.length, + itemBuilder: (context, index) { + final entry = _filtered[index]; + return ListTile( + leading: Text( + entry.flag, + style: const TextStyle(fontSize: 24), + ), + title: Text( + '${entry.code} — ${entry.name}', + style: Theme.of(context).textTheme.bodyLarge, + ), + onTap: () => _select(entry), + ); + }, + ), ), ], ), diff --git a/lib/features/settings/widgets/language_selector.dart b/lib/features/settings/widgets/language_selector.dart index f72f37bad..1ce492965 100644 --- a/lib/features/settings/widgets/language_selector.dart +++ b/lib/features/settings/widgets/language_selector.dart @@ -55,8 +55,7 @@ class LanguageSelector extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final currentCode = ref.watch(settingsProvider).language; final colorsRaw = Theme.of(context).extension(); - if (colorsRaw == null) - throw StateError('AppColors theme extension must be registered'); + if (colorsRaw == null) throw StateError('AppColors theme extension must be registered'); final colors = colorsRaw; return MostroSheet( @@ -71,18 +70,18 @@ class LanguageSelector extends ConsumerWidget { title: Text( lang.native, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - color: lang.code == currentCode ? colors.mostroGreen : null, - ), + fontWeight: FontWeight.bold, + color: + lang.code == currentCode ? colors.mostroGreen : null, + ), ), subtitle: Text( lang.name, style: Theme.of(context).textTheme.bodyMedium, ), - trailing: - lang.code == currentCode - ? Icon(Icons.check_circle, color: colors.mostroGreen) - : null, + trailing: lang.code == currentCode + ? Icon(Icons.check_circle, color: colors.mostroGreen) + : null, onTap: () { Navigator.of(context).pop(); if (lang.code == currentCode) return; diff --git a/rust/src/nostr/announcement_reader.rs b/rust/src/nostr/announcement_reader.rs index fdba29a64..c6684cd98 100644 --- a/rust/src/nostr/announcement_reader.rs +++ b/rust/src/nostr/announcement_reader.rs @@ -394,23 +394,37 @@ pub fn is_enabled() -> bool { ENABLED.load(Ordering::Acquire) } +/// What a read of the stored toggle means. A read that failed is not consent: +/// the value may well be `"false"`, so the channel stays off until a later +/// `Online` or resume reads it (every refresh reads it again). +fn enabled_from_read(read: anyhow::Result>) -> bool { + match read { + Ok(value) => enabled_from_setting(value.as_deref()), + Err(e) => { + log::warn!("[announcements] reading the toggle failed: {e}; staying off"); + false + } + } +} + async fn load_enabled(db: &S) -> bool { - enabled_from_setting( - db.get_setting(settings_keys::ANNOUNCEMENTS_ENABLED) - .await - .ok() - .flatten() - .as_deref(), - ) + enabled_from_read(db.get_setting(settings_keys::ANNOUNCEMENTS_ENABLED).await) } +/// One toggle change or refresh at a time. A refresh (`Online`, resume) reads +/// the setting, then awaits the cache sweep before it stores what it read; a +/// tap in between would be undone — the subscription reopened with the +/// persisted switch off — if the two could interleave. +static TRANSITION: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); + /// Apply the toggle, already persisted by the caller: on reopens the /// subscription through [`subscribe_announcements`], off closes it at the /// tap — nothing waits for the next background transition (§7). pub async fn set_enabled(enabled: bool) { + let _transition = TRANSITION.lock().await; ENABLED.store(enabled, Ordering::Release); if enabled { - subscribe_announcements().await; + refresh_subscription().await; } else { close_subscription().await; } @@ -437,6 +451,12 @@ async fn close_subscription() { /// nothing is subscribed — the cache is still swept, since what it holds is /// the last thing the project said and the expiry rule holds offline (§5.4). pub async fn subscribe_announcements() { + let _transition = TRANSITION.lock().await; + refresh_subscription().await; +} + +/// [`subscribe_announcements`] with [`TRANSITION`] already held. +async fn refresh_subscription() { let authors = announcements::allowed_authors(); let version = announcements::app_version(); let mut enabled = true; @@ -1141,7 +1161,9 @@ mod tests { let allow = [keys.public_key()]; ingest_now(&db, &draft("c").sign(&keys), &allow).await; let address = address_of(&keys.public_key(), "c"); - set_flags(&db, &address, Some(true), Some(true)).await.unwrap(); + set_flags(&db, &address, Some(true), Some(true)) + .await + .unwrap(); // Act let outcome = ingest_now(&db, &draft("c").at(NOW + 60).sign(&keys), &allow).await; @@ -1163,6 +1185,15 @@ mod tests { assert!(!enabled_from_setting(Some("false"))); } + /// A read that failed may be hiding a `"false"`: it is not consent. + #[test] + fn a_failed_toggle_read_keeps_the_channel_off() { + assert!(enabled_from_read(Ok(None))); + assert!(enabled_from_read(Ok(Some("true".into())))); + assert!(!enabled_from_read(Ok(Some("false".into())))); + assert!(!enabled_from_read(Err(anyhow::anyhow!("db locked")))); + } + /// Announcements are addressed to the install: a new identity keeps them /// (CLAUDE.md, "every new store must say which side it is on"). #[tokio::test] diff --git a/test/features/settings/providers/announcements_provider_test.dart b/test/features/settings/providers/announcements_provider_test.dart index 2aec8bd15..bf56044fe 100644 --- a/test/features/settings/providers/announcements_provider_test.dart +++ b/test/features/settings/providers/announcements_provider_test.dart @@ -6,24 +6,39 @@ import 'package:mostro/features/settings/providers/announcements_provider.dart'; /// The Announcements toggle (specs/006-announcement-channel §7): the UI /// answers the tap, Rust is told, and a refused write rolls back. class _FakeBridge extends AnnouncementsBridge { - _FakeBridge({this.stored = true, this.failSet = false, this.gate}); + _FakeBridge({ + this.stored = true, + this.failSet = false, + this.gate, + this.holdWrites = false, + }); bool stored; final bool failSet; - /// When set, [enabled] waits on it: the load is in flight. + /// When set, the first [enabled] waits on it: the load is in flight. final Completer? gate; + + /// When true, each [setEnabled] waits on its own entry in [writes]. + final bool holdWrites; + final writes = >[]; final asked = []; + int reads = 0; @override Future enabled() async { - if (gate != null) await gate!.future; + if (reads++ == 0 && gate != null) await gate!.future; return stored; } @override Future setEnabled(bool enabled) async { asked.add(enabled); + if (holdWrites) { + final gate = Completer(); + writes.add(gate); + await gate.future; + } if (failSet) throw Exception('StorageUnavailable'); stored = enabled; } @@ -86,4 +101,49 @@ void main() { // Assert: the stale `true` the load read is not applied. expect(notifier.state, isFalse); }); + + test( + 'two quick taps reach Rust one after the other, last one wins', + () async { + // Arrange: writes hang until the test lets each one through. + final bridge = _FakeBridge(holdWrites: true); + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + await Future.delayed(Duration.zero); + + // Act + final first = notifier.set(false); + final second = notifier.set(true); + await Future.delayed(Duration.zero); + expect(bridge.writes, hasLength(1), reason: 'second waits for first'); + bridge.writes[0].complete(); + await first; + await Future.delayed(Duration.zero); + expect(bridge.writes, hasLength(2)); + bridge.writes[1].complete(); + await second; + + // Assert + expect(bridge.asked, [false, true]); + expect(bridge.stored, isTrue); + expect(notifier.state, isTrue); + }, + ); + + test('a write refused while the load is in flight lands on what Rust ' + 'holds, not on the pre-tap default', () async { + // Arrange: persisted off, the load still reading, the write refused. + final gate = Completer(); + final bridge = _FakeBridge(stored: false, failSet: true, gate: gate); + final notifier = AnnouncementsEnabledNotifier(bridge: bridge); + expect(notifier.state, isTrue, reason: 'the default until the load lands'); + + // Act + final ok = await notifier.set(false); + gate.complete(); + await Future.delayed(Duration.zero); + + // Assert: re-read from Rust, not rolled back to the stale `true`. + expect(ok, isFalse); + expect(notifier.state, isFalse); + }); } From 92ace39f660b45a348e1873cf7646561a1781a5c Mon Sep 17 00:00:00 2001 From: grunch Date: Sat, 24 Oct 2026 11:57:46 -0300 Subject: [PATCH 4/6] fix(announcements): open the first subscription under the transition lock The pump task used to issue the first `live_subs().replace` on its own, after `refresh_subscription` had spawned it. A tap that turned the toggle off between the spawn and that call closed nothing yet and the task then opened the subscription behind it: relay traffic and a registered REQ with the switch off, until the next refresh. The open now happens in `refresh_subscription`, with `TRANSITION` held, so it orders with every toggle change; the task only pumps the stream it is handed. A failed open drops the loop guard, as the early returns did. --- rust/src/nostr/announcement_reader.rs | 57 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/rust/src/nostr/announcement_reader.rs b/rust/src/nostr/announcement_reader.rs index c6684cd98..0c439ea3b 100644 --- a/rust/src/nostr/announcement_reader.rs +++ b/rust/src/nostr/announcement_reader.rs @@ -479,39 +479,34 @@ async fn refresh_subscription() { log::debug!("[announcements] allowlist empty: no subscription"); return; }; + let Ok(pool) = crate::api::nostr::get_pool() else { + log::warn!("[announcements] no relay pool: not subscribing"); + return; + }; + let client = pool.client(); + let id = SubscriptionId::new(SUBSCRIPTION_ID); if LOOP_ACTIVE .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire) .is_err() { // `live_subs` re-issues the recorded filter on every reconnect; left // alone, its `since` would trail further behind each day it runs. - if let Ok(pool) = crate::api::nostr::get_pool() { - if let Err(e) = crate::nostr::live_subs::live_subs() - .replace(&pool.client(), SubscriptionId::new(SUBSCRIPTION_ID), filter) - .await - { - log::warn!("[announcements] refreshing the filter failed: {e}"); - } + if let Err(e) = crate::nostr::live_subs::live_subs() + .replace(&client, id, filter) + .await + { + log::warn!("[announcements] refreshing the filter failed: {e}"); } return; } - crate::rt::spawn(async move { - let _guard = LoopGuard; - run_subscription(authors, filter, version).await; - }); -} - -/// Subscribe on the shared pool — keyed with an ephemeral key, never a trade -/// key (§4.4) — and store whatever wins at its address. Publishes nothing. -async fn run_subscription(authors: Vec, filter: Filter, version: Version) { - let Ok(pool) = crate::api::nostr::get_pool() else { - log::warn!("[announcements] no relay pool: not subscribing"); - return; - }; - let client = pool.client(); - // Before subscribing, so nothing arrives between the two unheard. - let mut rx = client.notifications(); - let id = SubscriptionId::new(SUBSCRIPTION_ID); + let guard = LoopGuard; + // The first open happens here, under `TRANSITION`, not in the pump task: + // spawned, it could reach the relay after a tap closed the subscription + // and reopen it behind the user's back. A pump that never subscribed + // drops the guard, so the next refresh tries again. + // + // Taken before subscribing, so nothing arrives between the two unheard. + let rx = client.notifications(); if let Err(e) = crate::nostr::live_subs::live_subs() .replace(&client, id.clone(), filter) .await @@ -520,7 +515,21 @@ async fn run_subscription(authors: Vec, filter: Filter, version: Vers return; } log::info!("[announcements] subscribed to {} key(s)", authors.len()); + crate::rt::spawn(async move { + let _guard = guard; + run_subscription(rx, id, authors, version).await; + }); +} +/// Pump the subscription [`refresh_subscription`] opened on the shared pool — +/// keyed with an ephemeral key, never a trade key (§4.4) — and store whatever +/// wins at its address. Publishes nothing. +async fn run_subscription( + mut rx: std::pin::Pin + Send>>, + id: SubscriptionId, + authors: Vec, + version: Version, +) { while let Some(notification) = rx.next().await { let ClientNotification::Event { subscription_id, From a1d40f92c4f1ba597f7ae870d235b42f1fc368e5 Mon Sep 17 00:00:00 2001 From: grunch Date: Sat, 24 Oct 2026 12:15:32 -0300 Subject: [PATCH 5/6] fix(announcements): toggle icons on the icon scale (DS-ICO-3) The Design guide job reads a changed screen whole; the three 17 dp icons were debt from before the guide. 16 now, the row-icon size. --- .../settings/screens/notification_settings_screen.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/features/settings/screens/notification_settings_screen.dart b/lib/features/settings/screens/notification_settings_screen.dart index abf6cfcdd..b15d5b3ac 100644 --- a/lib/features/settings/screens/notification_settings_screen.dart +++ b/lib/features/settings/screens/notification_settings_screen.dart @@ -208,7 +208,7 @@ class _PushMasterRowState extends ConsumerState<_PushMasterRow> { value ? Icons.notifications_active_outlined : Icons.notifications_off_outlined, - size: 17, + size: 16, color: value ? book.limeIcon : book.textTertiary, ), const SizedBox(width: 12), @@ -340,7 +340,7 @@ class _UnsupportedPlatformRow extends StatelessWidget { children: [ Icon( Icons.notifications_off_outlined, - size: 17, + size: 16, color: book.textTertiary, ), const SizedBox(width: 12), @@ -477,7 +477,7 @@ class _ToggleRow extends StatelessWidget { children: [ Icon( icon, - size: 17, + size: 16, color: value ? book.limeIcon : book.textTertiary, ), const SizedBox(width: 12), From 05c97f66e988fc058ec7333d0c8defaa3d75510e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 24 Oct 2026 15:35:31 +0000 Subject: [PATCH 6/6] test: regenerate golden files --- .../settings_10d_notifications_dark.png | Bin 13139 -> 13035 bytes ...settings_10d_notifications_denied_dark.png | Bin 12225 -> 12126 bytes ...ettings_10d_notifications_denied_light.png | Bin 12636 -> 12541 bytes ...ttings_10d_notifications_disabled_dark.png | Bin 13105 -> 13004 bytes ...tings_10d_notifications_disabled_light.png | Bin 13414 -> 13307 bytes .../settings_10d_notifications_light.png | Bin 13480 -> 13367 bytes ...ettings_10d_notifications_refused_dark.png | Bin 13328 -> 13230 bytes ...ttings_10d_notifications_refused_light.png | Bin 13710 -> 13586 bytes ...ngs_10d_notifications_unsupported_dark.png | Bin 12298 -> 12190 bytes ...gs_10d_notifications_unsupported_light.png | Bin 12483 -> 12368 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_dark.png b/test/features/settings/screens/goldens/settings_10d_notifications_dark.png index 9ea0d67fcec3751f2b05f345b2df51c4aa4e32ac..34b94f803892ae371cb4d8029eb1ee89ce5ca5d8 100644 GIT binary patch literal 13035 zcmeI3XFyX~_wIwJj0JI|sMK))5fF6fy$FJI=}J`*0-;IoMICTJ5a~(@NQVFs>45~) z0Tcv62|Yw=0s%sY1VZk~6z6s3|CYJ$z4z1Q3x|`Ovd`IjJ?r_cMa)e@ZRX>g$3Y+v zv(61o6A*~O83a1C`^`~ckAKT_> z9kp`R(-Xh1vWmf~qOt4|OW#*`I3=bb`5#8=-Fql?nu?n@Q?A54go0H1_%H zH0qnMSpWJa7!0;(hLPXX?)cH|o56%)1Zp|BrQnjux>9dYr!9Fi8Lxy7Y3^G?#(+Tc zyGSSq^m&Irm!b92Ax==-_y5})B{f}dRkju)U=cfQEepDxb*;a zpSW1m`RT!M1TD30Zw1$4gzvQ!f1A>*L~wEa0+X=xp; zWB9-*Y!$Va)jNeGA@y<&Hu>Fm;1~#{m1zaLibB>P5M|e1p@}XvZq*0nGQ?)VErDE8 zBR-6WDvOOVJZQ$BcBBAX?tsG3Cb925&s6WrpVyt>VpT7}x23=i5pmcWE zyE?XZXSByxT5h{;nXm-UQ2Zg);T?8?uc&)^Mk-`hBxSL*j^Z&y8tLrRwWiWvr;fEU z1IV_Ge$wk|jFHBNrT(96q^@A1Oc&JdzA(MW+PP!89%_#w>8%G#3xdL~7;|^%PT%sH zxXEU2UXg|=84i}nWM(1QpmIaQZ$L>fJI@k3xM=Bc%Fi*=0;7ZlP^l3Axs|Apz@2e*>omtxJ}vNF?eKE_2!f}qYT9}3d{tX%G^tf-Ta9lv>xV? ziMag(g`(=nZE8xty4F@O7V{kR+GUXFSNJ$CRCUfxAIy+_%;!hRNR$P9IQ5uMPrDBX zTK)7HG>Bq_oVVRZj!>>%ZZ7}&UpFK-OGP@Yeur7iC5LstFXi~0v{sQb4px5=X=#T502{%Yb1KGc73rKy-Z}9d4JD(f zP{R`^DySx5LMzWkgPM;WQH#(^()7MH^(^4bp}#rJR~Dz;&m^d>QPcKr3cB;;lu{dO z$KhCre}hT`%&9)CKDN#LtOi4Ck+j?`^t*|a7u0CtE!qh5r2yrZ88=QmQUY-%#ipjgdH`yA1{TAK2^+fE{ zKb+>v`M%zutf;4I^HJ}0g?TsHSk4~;Mclw0*(_Gwde9Y?cWJTH2K1Tb?o-BJBXtRC ze7b=brxUm|vX-_7dYwRjA{x!fr$H1D12ahLTQukn+wU7@IG*Z|+3K9(Z63u;NXW{P z3s1vZ?na$Yx|82#6V9!y;$(N@sC>=Xfwt=Y!=7wqtl2oDEbpMu!Ty!3UiBp2y)ny7 zj}Y2pZD0IUQzm4uvnqXapg6}Z*zGf?#Xnx@%O$^TnBlS?*G=o$ALtIa}|>f*H@8WKl<(2#y+BgKA%3a$B@f%`u8(#VSi{MB7MQ48_u;SonYFGvg0{E z^_}rnFC}I8{>^p2+`umz#vW`S?!1XhpiPD^TGttWz+lmN$D_SJdw4G^V)H#8VPbT^ zpjP?8jC$B~FYO(fTeGo`$V(5+U%x5(q@d3Q&BoZ=lIuuBn=s z+FP!c4r09+sR-2k{Rxlnav5GoH1k(vuJq_Yi*&q%!lRPRaGJ9>*^v{2{E6|bslF0w=^Jdi8Kqw34a8;RoC@ij9= zai>tK@Z{c3>E&tj)p_h?;vo$^DE zy<6&b$xl?2>=D!(>ZU>>RvD$PUWlTP8nF_=sOBC z3y*Wg`hDf>XM*~f_(p*URT^0M>N}##IJEU+mV&w(BjII5(;;(9EKlZ0kWb0miqeZ# zDC`GKt0oU-L7i00t^B57KJ*sK8=hv(O-h(Oi2^4Jv=V}OGe>kldKsww zSBf6=_q*BBR_iUL)+%o*dVFwpi^xsPepqQ&MyqQkv{}MTzArpvYU8UzOk_j7?z;3sWIYkHjdQ&I}gD*LJ3<0nvW7>Tlniw(`BsIao%;(&zT zo3fXt=I$*Q27$?wpNx$uot}%fqd8vp0mEWLB4)`u^l&jyq9<8A^caz|WvdndD=0|q z&$gJ~9~nlC`Ht`LDdj1$;DEqxfuGQAG;ZaD3LO5Ey!|!E{jmqQ|Ig36yz_ra=D!Z1 zx&a>T-uancJ(*RSka|=voI6BEHH`AH2>)>9&XGTB(bsYLE16=O(_(17&>4S7jSmQ! zzoy@L69hhV_j;T?W!*BvLvNu+*1i2qY08Rb(=GMClj$}ZgC6_@3 zf03KOId+iT&!TY9pA^v}6+BVx*`l(I?#P6=7Wx(g5h&&D;c(S|qlk1R_GoMJkRRL} zodYaN4dR-a_6%sT&{$phVzHEXpLsx>Mm5>O z0pX~-B?2DKbBm7GjU6>AiRBZ{)!yVs>*Nb$6x<5=Di~QQ5R>|I%)KXmW(>LJ(0Wu< z)j>M^yKD=EY!mJdkyHya;ijaxLUg^62JLVv82Cs5aQZ)q}5@A(D9XNY;N13cltH-Upqqmi>3> zH9q$O29|rX6iPEaR0eCet0hgvx{I?_A|f`e6?_)&4=j5k$j?>CAMgm79Dj-pOU^@5 z(jK{H03W<7U!zc*)3RC)rF76H`m-|L9{;-}V_mCb=OPk%81#AhpG1_fHLX(nvwVNas4k%g=~#x#17JF%c?blC`|nwkecit>GSU%KUF9Bu}B4iirgV2 zCxlimY=aH62MuKTAPDNxC$mgR#>mNgU!t_983QQ)pFD@ZO%*WJ0cVQ(AHKU&81n`SX$Vrs}6rs?>JYW4P)>`$VJU@!04guyplWvboYl?iIW6~0XEy z@4L)tdyD{Fk{qtf{_cFMU%5#|r_mA4C6gP9ECk^8&drYufzW3G*6{9u+RLlNP&Yh- z?WL12n^KV}eaT3b=K?VznAqb{Vm%%HoaoVs$XRk0aDe6FR=zN zvB4WR1VEc6(y=LBXS1FyT+R(sE%beEjI;}o767?%ZUx&ee8-P7lII$@tp36yEbEt|5ARlZGd6Tle>>n!C= z25$CUsha?Md#4u_U#S}e@63uD)Q*7f-79u-a{Kout{gM3+Sz+0mB9;bVCxmu>wUqcZ^d^;Z-f?Y@3|Gk@9PJ&kTk@0-dYDi zi?68^M@0=qs2`~OUxEUj{IJotyaAY{I+8_I!{WV5pplxROed^fWO_?*Sabh_ul^;M z*}@7xiw_pM`#ba4YTTI&@!egu73(on_?-?cZdgW;&oiH5t{Z&9%Cg*Bfeq){!ag<# zJB!Xa7<@0bF(Hj@Ultj#HU5$+;A}IYnHhh7FH{A^0Yy z%)hdUzpnc-60cb!FV=6EM@;p?%dRr__zwqs3TRnc^+mSv@> z?Nf8xWQ$srgU@v-9@N#y`QGaa5zXZz-6RGfAX+J(y|0Yid;3Vhg)(d|4KcLaEYR;6 ze#NxTIeOmNS*h@0Vv4RFbHyjw8Y%06kKiG*<_YwecX<`^p@*Ug`XgAk%zVP8#nkB# z#kyCy-(;^B8&Fe0bQ@GW_EfYj4es*`F8Qg`v!xAeHQW;b9|lb76;QKnpQ$bMsX6&U z{vpmtF-6bgwWP}OqKG-Cxg~PHJD(V#E`eiK+RIQZrjT}!Y)ch&vgMZZEgI>Xg7vz?* zvWs;O*2>uq%)TlYM{?*WPcD4s2K?E1EbArqKr35cAC0ToYnyM4++7s1;A=_?j}zPy zbJoq8`)@wqs&O~^eBUq|NUS$M4cR^{gRML>SZbCZ{5)jFDu(m8|9ypReRNVmC#1a3 z7FhNwGJt0-oTYnK^ys)(`*!6M?=OxOaHW#!gwp8;N5aJJC@$OIj%WYT18TGMV`Juz z*zFHsRrs=^zYJy@z$pp)5 z1gyIp{^Vvt|2>VnlQehRI72bJau*!W=qU=EDfA)t+ zOx|FALqI25nZNqZzp}k_OuL26pH!+md8hjCIp*I9@7Jf7hcPJwhU1J-Wi(@?fyEGOJOQS47 zCkjhB_Vo3a20wjrds^)Zw^z(5Z7>KR zAU zC-e+sSH2dfowO2;dt$ZnxSosqvh!V!&X0d@l$d~8IglH#`p__-PwyD)UuFrx->;p~ zF_t&>leSpX)u`27axTIGgzzdD|Mn)UEI5T{(;R*=wlgMAx4hter#e)~@eN8M$Y>$1 zSoepaPq0L%UNc(*Y$@slp(AHEyeq6EsjjlY#Ldg8zsjM*dWC-`6<1En8mn*utKVAn zTZJ}zzejNtyJm!lSxgjOugpn$6P2<(!3!Zm)xdVQOl$AEUdIC231~#BP8H2e>UQxH z9_n{9h{-S4KLU-eFP2vNo%5#QxvZctn6ch0x&K3tTGY4pa2`?DscRMa#Kv+bu+x!0 zQ{MchL)gFoyYwEd6^kmUFX4azONKMe6;B?(XQF-gJFZg~N0T_N44EMoiS11rkij89 z*sGuWN11Yif<;u9i1RG7HFCB-96h7z_IzaGx5%BD7S*h+c8-oIqmzsL5z2W>xp0W^ z(6qh*lj?I*544uluL5Y%UQt=YFj5CFaP#3a>~N{9IDD~E*yf3R&X>;OlNUWsZS`G= zTWnGCzuwlx%p6xxgRd($q;6y+lYQT{!;gW&gjHua0JJ6~bzUSjOyZK3Y4cZetWPHqM23GX@d?m--9t!5#N z*?s)19ALOUxqJDJ^XE{T>qsM`X5)Y=5nJP#vg@;(q{cV7t=v5wdlJHyVFvX`+FO3a z#wymJ*4^({iNp6*klIB%?E2kRUKfBsXJY8R07gJvJM@q56=%= zh6-VQjSPVd1JfC!C3MJus^{6OO^^DLjTh__-xrgkI~1*bIJAaIm$c??HNKkca3Fy} zxt?TUqrQwL_D%G5&moFctM;5`c-a6`m!dYEV9TW`JrQP89P3IG60B;n=U%33qJBlv zrDUIaljTi@WLN6@tm2aXy-1ngVDK$#mrI}aMBojhPwcWvU8imDYEuP;XC4@417Rr_ zoCYR#&Q7$UN7FkYgX7lZ_IOROy-kFiVDgTiU)_qE-7=t5MRfqdneWxkP+}9wUNcKj zz?s~72`BzMAP6KeXm6bT{y>=p2j}r?Mt3I%_Q@qPWZzgiWiB;m?aqEGHNX1mIjd2+ zuOp%sNoad2ogG>vpu;(y-d8A@m~4M8n?8oY&5va!!bXqBCtsBrKjqxgG@@dYdU!-- zF$WV}j?`gVLxDhAbbJ50k_+X2+eaG(N2jNZY7u4HF?M070u2_nA$#q)+&tS_HX=E{ zOJT?RdVrD{dI~@%UXIVv9UFBYtej{1IN^>`lpY&AKV_Ran)7JC& zJda$~z`D)*Am#b*Hf!8He?!H<+A6Tx>Lzeu*_{JJbn)SKLrX7vwxRGYpt?mF2cWiV zSCz+snjLxS<_6w1w$tMo0#g>_WTc&;OdVQf-Z=2wX)#hV?_Y0DEZpD%@?odTy%@hG zZP775JqyKCPAR%UW#$e*(z6B0Go%IJHVS;5s8Lnw1emdrluudN)0Q&-{cB^tl$_4U z762)uL3WAr{qNDM4VjrwT0|3TByi~dxOhuzWHRc6b7wrN6eIECSGek0s0k6B)4JQ+ zuiqW|lRs<6(!XqhC_yPQ#mh3&Yk8ydje6C#IV_R&Ur2%(&fRO3a3!)Es382;%?NYl zyqm3Rb~;%NoTorCg%2M#b8yGcUCz}jl&(nA{YB&eHUM_0YGe3Q<@0M@{F*lZQ|(0F zR-zEjTCYgTH|h-xoV8x84gp-P)so~7Ri=`X)nYxBNWi_l6j&hI)3mz6WESyeHo}YJ zII>;WFyzS`2|Bhf|LWiCnENaku@}Y%Y3$XaX3fvfZ>_0P@6*q)MY2;=6>7$QzN3D^ z$JDU>-tR@mWDM5uKohA$-cP8`SKOrq{Nzp-f?)4`uxI&|d#VI=@#<0jQ zMQ9*HnpqP<;k^0EMk`$Fb*&VC9YbAcwnN9W`U&mfh2CRW3|(Y$GfSM9Kw*(z;U&rn z8&hQW-F>y(sWmmS80uX!{5vAx94&OrY@gQpO9Kwj0GQr}?aR@C>S?R&1-av@s!Qwe zJ>8+T7&4iRd3m-AkUGWlxI$oBgJj4k zU%<6F>`7QP-!fg(%@-Xmt!yi+)PY&?MLe+9tq%`W1G438RXdBN`JG5s!0s6!x2Fh;A?giL>weOKJ8ivNd(wu0VP^ z{)`RSkpy9v9VVr`j64|fNvIh-@Y&&69a1X8rk1{j; zel>&q5t5X;2M08+k)-~_mh%{QKG6>wg;6J@nd6IVXWHYE8+|)J9j9cd)=7By6*B+1 zYWg<#vrG_S#wync2oEkrm2C?d7g-$r7HV%St{E}`-sHcnmqr9y&t%8x7t|7mZYG)C zj+aI}1zcmtQ7x0Ql!+so&$txE6?w;-csnsB}#j z;Ly;$9o>T9luO@)fiKwJcDa=7t~z8f891THLn$+770j9jq2YOuJpDQ7pJ?CWbWq*p#9 zEsG$AmgwRL3ya2)Nq?QjbHsO|>(SkqiHi?M7FyAm?#5)j^r|vw7I;iF`5aXTAUL8vl-KjEX#Zr*jY} z6dRh?QloDImD+eif1#q-bgp1(I(v6^g~$pu5sw3=;T^+#aX{Qz7Q?mF98BeZYxl@2 zrT4=$sqp1y$}#;`wM>y!Kn;IuA08%;&kpqnY6(Ap(|AA-zCnEXPcT%c@(V1=e3E@?9D#<`cm~vQEp-Pib zfJ<4M3M;Fkw4~(t^wJoy18mg+4j%ZAZQk0;F;aD+%(^6&iejmqVDgmx=Z#r^g`a=j zQ${KqRX+H6$9hF0wZ;!1%lILWmiTffrVvVH1`o)Wm9BPw^d8ZN2vkg`M@jLZTo1qK?^gw$ukRFS0%NbalHOIjFEDQ#fb9d&>#*V>PJ=F|_sk(8 zr$Kc7%<(HQ;ONjoCcg%pBw3;38INaULY!sz3^hz`FHq3S_rfAVWtHtBb}l6rF+ANhiogxcFDadaOwY%?d5l`bXaaWEEGE^r z;Q}$pP{yoLkvF>m*jJ-{WASX|(C zp-{R0$rwTi{qpRPnb@e6F#w?S&yDjDqIc$N5NyP0I82w@(GlQF&B_&1Ybk&zh=@to zDB;lSHny%^%&AYAfp#Tdyv7lLf0YB8CVSSuRbMTF*r;s3j z_+nN<_)exl@B7Yx{8V}SD_Q|Z5Nj*VK%>$`#XaQ(G?fvtVb9WOgrwScFfZ&TJf&c& z1py*h>WdkU55QweDqPm`;-Ak0c@MOcWe-7SlovA`&WiH!M-OWs1Z$G0yCfDcvZ~E% zm-R8_gMGp!MFPw!wpPw`;4RB+3Rlgy@j#=@@P1XQ7fjS0RJR;tWPz#GY!hV`ngKi< zAN5^{*2Rpc^)ZfVFTC6+1~a8K&)-+ce!b>;NX@>Jg*+zlt@D&$ zfc0^}wm1W*_x#Hn#Ai>AClvtCD&FwuMTpW-kBP2ZK9TjQ^q2hSeD)1dk)~r{9fjS4=4P23CjcN9g?J|wSjqPh z4g(!C33Jh**H7ilbMcav>a6biQlH&3dzQ+z7^bvMchzY*>ueQ`*6MUtn+rb@YGycF ztPu9P*@vE7#W;NQd2y{OAL$lka;9motxudT_k$ua67m6}7(>3RjYF!Rf?`FGEY3do zTzNW~txW|K7``5x8AfP(iMTk)?muXsBykEqc+7_Z>rUN0SK$YAndneA7lcBTnNeKI zua&HaM-Jku*LqN9Lt=cLqNyHX=Df0JvctTnQz`nB!~3p@)j_pg`fByo){L$5(h(~C zv#)LfoF;gXoc69W)K&;8zOc<7m9}>sPN8LrA)E- zt}HDSb+jwO{=Rk1)Rp_}dLL{hbTD4Vx%I60vnK9{6et9+-iXzwZ%%RdxCB*BmGf?V zDy2&%`;XANWoD^2l4y*cpP0>0W-wG^)DH+z^y+pBy;Ex1QPzCRhTh3|HAJBwsJLXR zKDP{)8{8*nAQOj1l{fnK5CR*5ZX;K4Pa#sL6wybs#blK z)^EnVuI8I{npSYacm>NWS^a{?d;SX-%L>$9ZtF=(Z(JBN;I3x;pE{a;0g8sScz0aI zJugh#O`s{7`4mUZRoS`wm%n1PW;kV?8;yP2W83fl8bP|xls2HMzI3a8<%j-BJg4_e zod$ZE{y|lYJvLbgPUk-X9fMXced=`s4((F^o!o~7oEnS05=Is^_=P)R8bPmtp26Qt z^-5>_GXsd9yMfO1eL&QGm3jx%REoP!oXw8IyB)#)Lf6~Cq>DYWehPGGsvE?RSt@b zb;w>ZW`>Y`8D^eK=dS0R`<(ln`~E$z=krph1nC%A9|C@&4qg8l_?scf@}dr?3@<qsx z2zolb8NmpO)k=tE2IU{}1f7fjpC3GtVWG|x(GoQ2aV_(n5B;O3=|ioYdmbJ^jIrzS zJo2F9MA$*UKKja1OMl4JL_;X$^GJ}-WN1g?!cMF3nX$PsFM4-Yhy3~T4YR`w)iLGK zU<9Oms=^~D9IQoe%lF&#AHKM>{qy3BX(zwUB|@mLmzNR!<4rn-812MHE{a~4+%tEk zg__pvO|@*q%rz}VB3D%!R}pm-E2Qdp2pv*dxYbV&V03NYInV*506kA zo1=Qfg!FDlNzFsFTQ=cK16Jl*W2GM%uvVMnt3L>;Z{e?)yE~>h`Xy-( z(2YC$lN4+^bvlZ+ogYEYyEwYoa>Zxek~3mqC&arcx+5pNaF1%zvelL!K|yi(tvdnJ zgF>Ndcfv(n)uwBKM~RD<=J-E)ivRT@kQl+Ri9Na5Pr+KEtE04j?Aatzn@^Y9S~2!+ zUemWIP>$!;XODBSA$Z#-M3jnE*{{apXIVRm%*5^Hx%Inq>$p!5rUBfN@zXUq9H7R; zrSO#~^Bj_7Dqa#PY|X6?5tl|gUb!+*9|qjx@M#_^3YL{g_eoToOL0U~#j*5*v5BI| zhf$W|;)&Ibjm6I)SF+~I+Vq*3FQyoK*r2Tmp8t3U8cHY7M`a~5E_q(Pq305;--e1S zbFRZE9fnU0-%aW^X7)-omb`O5Hn{YPf3Y>hLhg-c>lZSC>OL`0)3>K**(&0|-I3Et zG_I3j0{N6VmYoIbw2EXA#c*{$^wq=)35*sSh*;J@7KTJYxgI5i621hx+qYYt8Vqb1 zBY+{Bk(c9cFyCOuSYuYWZZhMz`|(VwsdxzlzOs}dS2m@K2Q?6m>OVnpRpTVOG(Wju+>E@TSXdQnhN=SYwHaJKoNDZW zNFYh&-acun%|!NDkI=pF4`u!ydu_3!&3p-O2sc2_7xgT34^K@b$KefD_U?QNgJ(~^ zpwncl$33oH%fcgDdM%L)Tx0Sh*O1H0rJ0$T(14JI_387axMNyY0qA1?7*eD(o&ym- zZ5RD|La4ebFhAdwOF|~y@dzQfM}vC33;z0?qqNd{qNdONp228j%^-f)-Q9h?LaU|D zC+IbDHav&59y>b=p~mgFj|*0CHUj zQ3*{eYLHKza|7Y?b6P#dy)L{VzRitSm*FK&;oRlk@plEu74JWR{$-33S@VGEX@Aj^kOr$v~aYuH#-ZVi&=TwOa$#+f$z%FJGTW+Q*M^SYbdp$aI(-u z#Fvf2QQGXApdI3Li)VzdHWq+MnST$H#m(w0er@T^yQzg^ct_u+1LB{Lk3P?%AVZaU zpssM2gWtaAK`O(`A6Yk;w1rQ81KznV*O1`|3LZS$=Y8TG_z`niT?+}C%3mYrftB4K z_wV5OJA^+QKMPXUtG57=nGOI@tFO%zYmveaX9IU$E$iq<4DV$B>7DD<_xbQi{wX`| zF9pzZe_!+5ybA4l_U3*S=L_vYa?sMF7~D}WqH#f6My7kuQ1-(yc3?!SyS1l-TNmu# zu3C%hOYn+F;}yBf^vv4LNl^#w%`3W8$%v)x^l0VzYI@?} z_0|KtT05;}_`@$p56R_B((-PdrtB_Zya%%fZ&*pp`_Nf}_$K*0Z%F0s-q1nC-A!}n zhdeE#Y;j3ST=DjF`>CId*H)Uc>RlEyF0mPRY_W1@kCszOxATqI6VE7AXq9TPRP7Kpk10ed4z>;C)s8>zpA03zcJDu_3WvSERNrT7 z+p85hqrXSal5O;Ah}4SFzQ?iTdXU{wq;~T0P}!KAD*ahjY8A;uY09a$JCt`uA;3&J zu^=WIX5SL&Yaji3;FsoVyr%O|+rYwJW$yUdSf5)6?EyYW~n zVYOgWX!4}iM|4IYmcyUW;Vq~OblR!%)8eYI{ zX7wJBkDdGi-h9|v*$^u-8J;T+jX%G9uoe7pCCAQYUf+C^jXPhz60u+B# zfRx61FHaoN5ZD095csp_!|x7M+bq2x4i)x{D@G>rzO<=;ZFuTOF1?$3y`-z3fZv1{ zncr2V=^6Rcg;z{Bw-@refW;`0v?h;JLvfjpoK4dM<^dgt&Xn2v5#8r>)BQ?_Rrey< z{DCSp%06^bsUTr&YS(uS*fu@1FeA1BOk_`f1Cx^~?_6hf!lyl8j&syj=PNk`Bs{y; z#k-q672fE74RfMzZKf;GYO8A<)BDMb+N};uPW5(l*YG|zSsRp{@qrwJQ092=3cP^0 z+V&-xr{YSixhZslzrPRsF z7kfAX2m4&%<~M~L+A{S@xOAW-<&;f&K7k&3gUjNHT(~o(u^jfw_DoBJ?u`{YeUdX) z^~97YBVVj|at9_;)q*fP-_HlEr0dVrezIvC?3HXO^_+#-SS&qKryBwA6T}znHTR46 z<;|+*BV=f5O0^|!pfg)|Yt%Li8aaG#v9FZH-@n8U69h$#pS^n6{3v6r#dnvon?>>7U zr@y{ue~_O8^Fh5V-|N(~N;}7J_BqQY&NSlzKkuCSe~#GyM&X=QVg+$n zK)FFXpx<%kckMf^X#ls(z%9)ay<4 zf#W-(skd^ri^Q^WE=ppflxSU#ny0KCYLrPAV>ak>z?F&`iV+X?3;wSx^yf1`NGIj? zIcrk4slWsBg4SY!7$C1$ziE*x;Rit+%bk+HWixpAyD|sjiO|oZrH=%5?5zAsQx>Z& zp(%1tU-DPn`fHK5vmyYKoD3PD74|5$1TJ10CNbs4Jm0@4o4J}4E_075Hn?q7T|C6{ zBrI6nmS~^^<+H7~wBgp5xeL71u?ctUzd0-G3_G8bY;juQ88h$z;N7e0`V|fOB~`JB z`FD>VuB~QRE7yB%JLtJzWq31{hj~yV+AV6@_2YUCGSXp8X<_1qp2t?V~a>&R^<0a$yIfz zSni9Er!DUZJGxGAMYZ@-PWDf&q@^U0J>rLML9cLta1w_YiK{Av*Og^b??RfC$1}6< zNyd6-{)FO6nWQ_L`+P$Ktbff>vDN8)ly||PfDj~oQs=j**tdKv#PTGR$%>w z?dEbwQ(i<(G>2b%d}x@7)?8StKNihVil+?ssG~cgH=H4vR_Fga zz}ZKh$v5xuFNTvrpvE8m98yYTCyQ4QF=4rs4Y{2Y*rp4&dU~_z3sdw*(lzuic`>D0 z4byw3buGteaPrWYVcEg|s%ZT>Ta(3%AcKFifg@-Jslpm7NZ8yj0mB1f2>N!+9;bAT z|GM;XP%ry`GFBih*BAp0Ckf&^o3y-S=5*qwW21lqB2hn%urlfxDlH>-PWhR&D#jR9VsQH^^Ydmb zZ8+Ng?R6cd+ajzONeLNg*dETQ$%ssCR($9SmNUdyLw?L=!0tD@ykRY4iwiyhvI`;x>Q@{E&Pi$YH6{F9c5v-OuYm$zQVGGkPKE)b zVO0tyc>cmCAh0;9fIHd?3<)T12|%j**r6b)$V2kIsK+5fy=WMi0!#B_2f_0IBLaa3 ztP*A6v2bl(R$U3(l6aMYBe|Tv1YnJ8p6R&UUabHOf-_m^>c{~;(2jA_a&y^nOF>1@&v|b)@d_{SRXB^$+GG-Ph%m>@*GQPxF03N{+OW?Ab7wF&;!nxVSd(IFZaP)HR%h%Q?G2F55(g6jJFnZq+p6q zmc+O_=BL-%_cmklh?-nnV=&roT-uH=@_pgkW7LO_{0W1Dum@E><-$lW9wbG9Q*$dJ zjru_$K%mR~#n|l-Fcb#!)oCL>d60)&toK0r?kiyok-1^qLwY%5bg3$BXyyC_t!%Sy zoTYqO-8{|_928Va58So-zhoFpLBLhFr58&^{3gq;1&p*^20e$eAK{i)I#0PS^N%v)7+2Ev9JrO~_mj2@y*E@M;W_jeyO(vC!CCJ1@Pyoz+6CW@cuA%(dRX zw?P_$w$$t_zRCe=HFNk%a~idJHL)%uV0Tmq%*3&U=yO8~y($YvJS1)R1Ns-XI&m=E zAJD)pKjuZ!pnCLOa%J@9`^s57LB2w^RC>4wwhUWZ>bvodL%V0IS$=t=TE=`R+t0^$ z^at|nqsCz6md;g_!=kunYgz$cjom8AC-XfrXhB7h6RU7TXp;`MA~>EYlF_v}6dCeKk?zmv0$cTEQ1f`~JQktNEG z7h3q9BR0yVF0%GFP2Eupjdzt6puO{`3GW&z9L-UITSk^m%{MN*YomOvt)cjDg8I|c zZXsRh$=8rCPa-ad-S1^g{VjS$;#Ok}&uh?6!abWy7RZaLKF4v`SMp)S7o zG0AgZzlx;IxnNH&$lR4MK}`5M;&xty$}M2P36XqwVE?XJ+9jlR){hxKMb2S!+II)N zKNi4-tV&0zMTfin0t8eW%cof^Kv+)H_T7FJ`lH~VR25?K3Y}Qw1lOF|x2*BDZ~OXM z%z!Go_k6mTkC|<+7*Yn~=<9FZ;P?=>sKi6@Zfh_}Zj#mYc0XwPQ6!h{sOda_caSqC z!EFQu>e#xHaw4|kHFxWi(uBbGT`A~$WoM->c5+9x_04g`HMO(yX)pcKKa$Uru)r}R zHjXU-l(96g+RpDJar&ba#5^5q!91T3t9>jLAJqrgEC4%Ww7Tt-LCT&%hB%QvbzAc~pN47dR0Q_iF)c?9~QSuaTepVgE&N1XC?pV!q zL*uM+6CapI?(4!uZs~o4YcVy`-OQFpMSVs6o81dkI_HWk(hJS36@p(+mV`(LyyN(_ ztSxRH|CD=V)(59TVrkwW6pl@<=S9NiUyWsX`=DT?2q~q}?j`1Nz{L8E=lUl#4^hPv zn*i>~VhYpvUPtXKPk}&tXv*&tAtAlvGtLGI(@0D44aPr;+H^3jIoPZ6{i;8H_#e-# z6Z0q4%Z^;txcWEW>yMZI@r(+F1<^wS#HY`r z^TT)#2^pUCg{7!+lxFB;_&pAxMu3qZtvxVlTK4Gnr6+42ZclmEbK*MqPmED!6wZEI z5!S;Ro1c@VHxIX7Mq8K6!-p)@Rznf{DB)tX&l)T}koj z{3SN0E}mcD0NflEhs{ETXjkJ52IqBe>~jH0tX{ktR$wOFQes*%bv5NucnPY4Z3p?I7uW`yCn2e6IjCo>2uIsgh}Ub|?Y zaY&ur&&=ENn@xPogCCNO##lTcZufr~(vEX+mK7HFS#&JTpRdQdd$=FmTSvy|j70Uq zsDbE0+32-rOx@G7=@Es%k5f;eEogMW9y%iMZ2Ag z(Xh5*;C+L|rJgh$j~^FUi-a}|lp8|?>BQT@ z!oBzCA$Gu|5iAR~(U}{~Vwlgd37+y*x1tF>Lg5x#JF{&5JEYBMS}cd)WL;qpW3PtV zWRgX&D0n%r^=%knDNi8z`@Vz)Eh|R5LPBEzl3l;q1;E5vt?b^!tn;eN=8|T!1Bdxr z&VbfXDPStV7-Sa5;~1Bbx9f%o4!H(?&rgZ@!E}m$1(wwU|I~pMkOzaGCrd z`p8lP2y}FLzZalbMFo=!_>vnj=cd3@K$+qLloJUMY=7!q#RYF#j$Pf;u}^kv_q0~+ z{U$4G(6t_B$ibZXO;vxjpa2|2rFwMoPmR0inT9Fv2%(7`=ZNJqOIp z_tdb@dq+TP(pn$I9Ruoa0lu@nb_?GZ7nL+5dF|B-9zcqSGx4W;Tv+uJH!6un0W*ud z7aR8L1S`xh#%>d()@tyVGXxq1Tl8E9ux4E)P1sREi`P7(OBM@aBuJRXK`KsQ)@+|p zAF)`(YE~#a4U-pBs+P^PY==yjdc>1_;Wk1F*AUSm>mO6B@x!0H@~XmX00S*HCqsi@ z0$#IL#AZ?zEEw512%h4NZpNbO@7}5|g5d`~k4&;uXYk0!J&L7SVcIiQxV&Muxs+rm zysg$fNAGy!Dc!{rP7bu8tPug@i-x{?)|zEruHBJALhbBIlaMg_Dh9d4h1UsO=l zeH9Hl<2#YnpL5$@8ZVzc?8?!fqquNHzEPn!^+9kqg3Sigd<-r!#t7_8^1E`t0Vj-r zyAalwPc64%w1fLM6y!`C!?8g>vldrXQXFH~J@{%*NJkh{;00{47;oFj? zbv2f!YElF9pS!t~xNGV)+;N82%ka!l3D{#{uAix)PEvKcjR(8V`i&H z8{K@Y{CcuA(Hg@`!IL4gpI`$)o;4alP=AinT7Ng87L}Fk=f%Vk_>safo)~-Q#K@8 zS7&o~;%C}+pWEJIg+?D7_ht?P6vO7HS9=z6#Ecdz=V-OhRSs=2X!krlT;p`7#ketvU-E$c$Ym?^C z$HUiNMC7bZw(`%2sRJ|4eO=vev~O3V0{S)4ZTGub(zTdq>f7{F>CJ@uXCTc0qg#$` zphS&;1XW}Vz$>_vR`zAoj7)BwWBOb%os1`3E=xN_yf?-cu`e|=xC%6E1j=%q+25N{ zZPP>!QYQU%xB!A{b(lEM(Y44JaU;lsW#F5Xga*rwDFk(V9(pY@wFfRQ0`1aqLqb!u zp)g}vb@-TeW~klru~I-w~r#73C)FBZs!~_R?VY# znGh=QN=k)8U#UvyYD1swrjZOV_ax~PsMY2Yj>It_k2Tkb(if(U8=5F>eX@&~%adg7 zN|HP198kTZ=TZ)s(Y*U=;oBz-?y{r91)b(Ki+W-3t1^G3O?V3ZDsJ+jFr~}qW03#---*$`yY$Z^OhCrLG?9Qu|J4%~NA`H( z`|N;_&l=Jfh@SCQ2HB;nPX#F+a}fB;8sP7Ogng-+QWeoV|MtK0m~$f=lPVBqS8mJU z{@MB!JQ38RITDCGcO=yqg`4~ngIVdDRq)5ouzwRS1E})9J8Me-iKX!?DW+E2L>2z( z^kUsv9R89A?J%K7kEO@&Y=kxsTOz;l@2Ag0i?Ek9TNz<7!dQTj{@Ev{wiE_PSwEF` z`)as!yXJP!8U)E%y-d?&QS%BU?&?gAQ9=XD=1 zD?As^gH75>%)gz#(P(FBmuTaZXx%t|x%8+?rdKG?wDxWUr&PMkZ`FBZtHjndj%ep1 zYB~P#E|z43epqgew~`~GEg#CSTNYESY;3JUfhoUgfcxOHB&gzcFKVAZW{HLt>Bs7$ zbvn6^js}=O_(Knf5p|IC-rvysogSNbY#Q$=r!BZmMLzb@ftTZ7o{DbVi`!SFJIi%V9Ed`*LmBxOb`@8rzWSUBvmcaa0Sj&JEtL9(>)<03ACW0p=31 zW=@PsO^~sYv&g*nRBH>^N+qAvL#xG4AEC(9Q*qn zbzLJZGvO+OgZGCp;}*|_Un;n4_!h4b`jIkH-9y2jmn|LO&Rg4+X|sH+{W<+AJtMLS zW>3Qhvk2#UW4sA==RI^17Fp%t{iY{{A{z_t?|J!Ud(v9okYope4m-kC;fd7#Hmkh3 zA0q+3cYJ%=M)YV7vtpBxP5v>3xe6iby@Lo9OK8bn2B~YupB``_;55**M-1=Zp62mv8*m_eBYbzg*3S)@n5S0LZ^sdaEmVp4~=n?t@@CGUKT3?}TYsf`9N@EFcqLLRB9JWgrfoJrv~ z_Sx_?bs6clsDmgBt-bxiP93LYm-k`xlM*$+{hzQ&s8t()p3Wchm{VOz7WHco&zFw0 z0)#!GBnfc;BNV_zbqng|#)V+>gacmA2@zN{myJ_c#pp7dSHn#JV2lSJpLt{>AC7(Y zaTy55pim*2Nksu_>HPepDAcXVe15w61AhcauDHyH1Hvn>BR~DchFB;&+I$!U&wcNe+I7)_?hTx1C>3(3jlBu z(7Srs>|xd-A?QWHmK|{g?`LUl8E8bmL7!BwC5_rUQ0yis&RoauUpd3V!tx=_;N&TV znybg2UH#$Iq3ELp--#bJJa$N0xQ*rDQ3>OgOOCH8qxJ}%JB{`9jIr#U`GtkbB{gIz z>4TV(GorewvUJaU2#uYRcX#<1j4TQZ?LvgD4K8mbqZ@lX`~p=ZY&0s^F6!LgGDPQ2D(Zj6L`&G>mYGYWdLf}FmPrUE8>vLOgqfnQ+o-mg!} zFut?ocMgF?BqNGjohg4nhxS*M}BAWW}y^HHMV!KsW za+K?}!pZTv>+<0=ha>*f@a=A9IU2hD%i8(LaHh~Yj@}eFvxaCwPHohq4R`K=Q+ee)?)W=EWb0v5iP6igd}?>zW{$L92>hYr-1ugV>w%r z*(yGF3jBzhZ5&x~?KRbG+lxGq0;ACFJ|8>L7C9P{-e|+4@qqa{s#^NNb5`JmuiBHn z*0^0wgevQ!(_LWHiy@42pQq!Xd2t~#FHh$*+tA4_(D{$q*#8NJ2!nx&3#CqPcUU4t z7bXeY`(e1IhPSbY7{~gb102iWyg%@_zuVvVw106+WMW8lWN>ciTEtu_?#l<$4e9c)S zMyOLZb~aK=JnkLl0jkKbqx?k6R4p#OB%2?@xc#Hub-42pUSm?3iU*&Ac-&dc^{fL_ zpGCvG=avWz<6ge?5F=lOWZ6imziL@UA6z)<1|S^7W&Ia}jRHlDvK%Jdb1msnWS807 z-WjZqlx!-rgX}%vV~cjqZV}up3!@(86rpK{U>0E5miWPc-Lbso^Xri@REofMEeRGE z*$ucFjmsvJP$~R`?)+@F;4ryciSQo4^>(dYvAv&iWIzB)|4X$8Ys(EvL1gK(U$u1e zieyL|?2pEhXHjo^3G7#TU@2GQi|j9j0{`++j~SN93WfQRo*A4$T1Nu$<-4 zksO{7>KR&%Np-81dgkSw1pRZp;KGbQ%t>(rk8J+DMEtgodNeO?+^nixNEa{_NM(6s zM?vyF)1<#oN%TDbmxnxgcf=~ z)pFz?l&y&vmPc3aD<1|FAN_ARyMr~ZUpnY`O!4p4xZhsDG<=kbIqD9yQjVVcK5SVfpg&B+?X z5`FGcowoxvw&^EEW&dva-(>#q>eMEy=21;*_4I26v4ttb23JTq8+K(!Sf@+r75xUJ zm-!jp{E9^X@{pV!6A{b!Dh4fU-szf+h;@;VO%2|o4!4Z31#o%?(XK9h(e@68-^4en zjEb27qh(8~@$-HT_f;EGYQqKQPuz&&|PJA}9mC}H@m6Cjz{oG99 zPcs*Ko660u=N{;KrJx`6Ze`Rqzvqx|4P?ULA_pM9Te zQE$3mNo@Hw{W}(LU=*7$IuJi}y$Fx;Kyl~XYH*hsn512+R3w>-K#rGLIGy8iTrM#W z1urOFTZ3B_F*aF??^n79_lp`*0&hSV?HUqoB`N?4dPDC<`tRhP{JOq7W>(Py)~;bK zVhu)^{J}$}WH6xYR+(LKYHCNV$@@_U5#ZYN4x@;*wZ*i8TxP#^HVE^uuB?nQHtG=m zV+776PxKx!B)6foN@exfQ{+Q6;Ya2{V??*&3F$h5-0Oy9dd^nbFVEzxVfT$Tp0hq8 zya@aX{3C$>h5{Mmx(_&<3eJ>B#qw^2oy5~;cNk3;2OQP(`E>GXB+QOAU{mkF@VBOx<(LA9KXgV?w65ibIbUchmw#7 z8ZEAt^2}>gOx%2kBye_%9Dwb(uo21rO8qCNT$NZNmwd2%SFvTS$(oX`1!a^t^hw> z8qbMxSF20~9+l_~n1MCj$;thG)%g@Hyu3^&ofZDG;v-0TV&UqO>ub)@uh+EN_0085 zX6xA>rT4-Dlg{`>Cq}P%s`L0a;fe#q%|B+i0*bjZ2Jrq^GA*>HYVl%kGC6Bzt9%$x zFs+eEC9##7&1Kn-xaXD)VK9URjiZNvfusOz=`h)_YC)zKCnoXYj*HbCIRSX(dDp5? zA$oQvqSjN5(?84Xnc}1L6qocb1!QV)4~vM-p$K+`ff^ahV>&&RB$?jJpTJkKOl5s! zS0v%fhQo?;X4`$FvnHb$LqcMkE%IEUJ=M;-@V(v0ydKpsYH<%&P*42nDEP`3)G1x% z@t}~Kp@1Q@z` z=u;X#{S2>LL{Cf-TWbA=m_i$@ARdqM{0AOqG`IvHLMc5?ZRe?%(pu%XCcTIxA1`GOm#)#! zznJ%TJOu=H;K9#}*A6(cfB(POeqVX}LiznC4MOOpNs9B{bLft9cGyySL~PS^C1RZw zy6fE2ezIPOu=amXq~uqo0#Lcj00v3gj3{WTmS)=4R-&~`T%w_t9saj-Oz)#v;3L)$|-Ku;WH9boT=yN^OrMx;;PI#^PAB6l8D{CvO*A zPoZX%q1%J!#RZhm@(({Un_nIEa5_6!jo>A$Xqm_D{#saxTp+Ld*@EY~Z;3Yh{XeZ`B>>fqhUqalJY z&sU5?!?zmx_G%t95Q@`JtjiMR8e5+VKeEHgiy+|n6jE>x%v1P{Y`-VbE>-zcJ`XTwjSzZ`z;B$`C#klz(n{RVv7&% z{aOLKIWT9pWnh?QYy5s7V&X?}=kY@t0ZSZ+7r%WWocbSobR;DQ<6S`G|jc+Z(>c#JEtyaJsUX&_m(c zyD-UHh)%m)9>R&``Q2pR_#Va;UH97F$^LtJfzM7{d{px6sF6sN;(Ri%dM0g3t-01t zLVr@D;m!W1^?%4fv=QpDTJpk^V>csEnP?@UHJ7 zMjLfyhS&A(uG}Dhp)|+{p6>qz&Ue-i*FV=ol%dvhhLU-d*CEZXGzNu2TqHxur-jJ% zoaSU)NB-b;5R2Eir+px?#S_M1*UtHglGL9ru7)91nA>goTI%4|c5tcSb^`YhjU3p+ z71AT1iK{Tc2k`xbw1CCY){E}nPq_+y*rAx`kcw=sI^PTZ$s_{RmHv)7)t}xz5lo4b z_h7DgH(lB$FI0*$YM+8TpNOz;fb@@Z+IiX5R0l!9=)sGi#9>NvRpphy_n3|R%$P)& zZO3}}UME~6NGJbFV4F4gK>z3KLaDV?F!|um(j{j4muK9;yvesDuRD8*J0xS0J6Pa=p{zCjA}5 z*%ocPzY=$2BH|c5%VBX#h)*|JMbxQjQDd-Uubzs7K=OA*o@#;wpfcl&HQtwUzR5)I z176Cvg41AquzduTIl>zq@|&=noDiztHnw?dv}L;Gp~CNY-JeTJ;BdgF??I;4as(`* z|C(kLw(j!657FkZHRK?)c^l+}8Q?ThHi37{_T`d)wElPC_zJB5UEj)Rh-=*bRcy;g zkI#<^IH*+cvWj8@7RfEn$2T^cH0R{QJ}=Y8m^)uvrjI{OCdNRS z15m;F+gz%1am-m}|Cm6}kr1yNVt>vpi_>j5V#Ze2nl~dN;_R>i@N(w^Pv3vTNUQuzYrRL4I z3)OKPE%%++L7h*P>oqAzPM!n6Mw5a}7VbXj-J{uhDPx!|Kh&w0MCU*7Q3XcfAwp zwGmDjgn3Ep-APS7_{i>*-kmxd7*qw+SJW2^JASl0cK$iLf_lD$iPa3*Kf|z!5;CUa zhcMMkcs0Y_a^tIpQSzB#kS+YybZ68L-LxsSkgk;H0_Fxi%;9RXaMM6IJhEn(%xf z+pA+d-?q)C*WghnMK3r&Jp_iqqDe#k$RrV>;ofnc_K+a{ZGO5c4Je>_<*c@jtLv);q6^@u4 zi_GYLs^*2}$q$)WxuMpJKKOgmhC8!l&YG5DqGMbva~OPmn6i0BeX?6q$qQGHxZPPR zql)sPlnD-Rz!C4r>h_mS?eF@pzmSr9psQrJu+NtMn;%vp;=(r;iu~y%i1vV8)N|5P zLA(TMcR?3g?v@kg@o9Ql6J8ZI(*#wnUwPr%W4|f5Y3BnLZ zs6n*NV7DxsZgWKhN-c5(T2%fzJ?1&AeaFL7p8x%pJ0C>PL}L|T};+h_WH8%UcwYHp!3r6}-y zX@E`bJMFW2<|vY6r!Sw*rIJ+kM-j;`;rz16QqkI0=fJ#>sFa943LmIn4Y|O`xSl&* zP^$0(_B2S1X$Cwp1~rO&n-BERv&k7Xn3Os82ADnTFqn=l}*XTBQx<%pwEXUz?yn1rE+a|3Qoi{o;!!izx)&DKE>=vtr! zN58#(`BPYTXxvXaSiI0aBfTKhxu&jvs>J(-MaP%9!bx3i!en%q3_=v z#kbu1?}_XZn3{GzX!n_TlxCD&|21e-mAf11rmwR4sG?tlYr7nPWkaj{|LT?^{oLmQ z%|wO8g6&4-LQQT;LbmirhSVOh&rN{OUKfllG37QsKwlvXususn^^D@qBaP1ro z%aI9oQ;FL*-d0pB<}rT}RuA(pSkV(y>#YjvE>nU!h>?Xgo4r?myYr7q!XGOkR(k#X zD`(v}ZpKe{kLfrI@qE$_4bRmlSlZH#UBiXwHrMDFbp%IZ7EQ7%v?nMHnVfM4BBofm zMQw*bd+bVfqTASL8!Ppy%hX7RSNu#685J4qUeXg#S#G1&5Oy4K_(#cTh~ehTW}n~tALVW|^r=r7DX$#k|tn++$MBqtm`>xbl?`oR+c8QI=KcC0i~ zuYU(}6He`gUIL>Vd#TD*N|*ru?z9oda|GgrqM+x}630j?E5RpR$A^aUJSF9a1Y2T$o~PsCGW`qf>f`qKy1Eq4J*`}j zAIm{U;Fn^v6?o_Ms&~_Wl5hO_r5D?O084lqaZ8UdGRLPpV1ZBMCh}6gLY`?X&&I`+ z;S8H93JvfDnDrZ$-9ioEz!}i*?{$85;D32RVBT9Sv5-Ho`brDsN0DC6VXUb1tzGJs%E(;CwyxX)FdM_x0 zEEEa$+BbA1`5Ll%%n;exL+iuSQO!qd0jiJdjkaBnB>Jn^NTb72v0sPOH9Y+`rUvXS~|HiLPJ-{!?qLd@}WCc4w7A3ozh81 zHOy*(J9r!75OEkh;em%~4|Y{{dnp~QiYBbH`}blrONh+j5Cn^fj4 z*CWf}QAzSx{@Q)baz9OM)JF#TEZ>2$*0;ILC&XzORL$$g zt@GxvjuY>Zk4H_@9!B3Wa*_114cq$J=sD>6zx`+lv2-xY7~ed`0$?+j4QPx!awqOf z!%Df!^~}f&N@RVdo0Q0uuVKRN?#0iVY$O|yAGBoU{~|bYLFtH>$OSH$TGoHL;!1vK zl~MLJ&oV_Y`0RQW;dq-3;eLX@hA@1TsBq($97AZ?3NV`2&OoS|a z^Q-6hb7+xqPkez9WOX4A|LenU+uY^w*3c_CiEinSAH4A%k|5pamzbUy9~V{Y-G6EU zp?NsW@MX?v7O$g!M9|-Lc)wfjSZEtxOBbiM(Z{SRg^goZ6VR=c(4fssCSo$Oa83E7B3D>sxd5S8?ue5>+1VJ$Y{`l z?!8OAlG7^Z9_lVG;(ND$%TM5`rfyqcSnZylAY56U^XymU@Vi2P zk%BuU2RZl*S)%QVYt4&6ll{Y4d?J{%38htaYY?T8HIXL!gm)e=>=tK#*O6^qB6Kn( zDSS2Wv)fzXeyJ?G+5?+{in>XH%y1$%;RIz~nm33zGY7ZQCp9OLI~FRfGxx!qBUV?+ zucWS__B!@0XqKDunQK&Jy%-$#7a&Qj_~W0Liy(%S<7x+URK=Q=`yf0Pd}on0uo8>Y zBOM>F8`lh=PZJarpWtREx?e0ru=HdWizOEYmlU+4f%A##SA+KAO1IAv*ItTN4F%insXtl=4 z2|5j-iy0eYw|&B>7BA0#J^mCj)sZH)H(>-C3E6=;{e9DDE`RDP=djgkT@KN95Ow6T z)XPXYp~0Vgx)R3otGYgasY>Qu`M^{AFu}s`DhT$;^n&rnRWSxjZI=#%B&G12e#k5& z&@)b&mVH*Xl7`14Q28C}YbuN%fHW(lyo($wq`9`hoZ`T_j<#l;*V`AzlTcYtU-{GQ zUlvtEepNZLukS{eH!DAtRu65N8QyZ5Nguub5roikKXzALw5h}k4VoJ4&Zx&R>)V8} zElfjRLfQGn-y%2QehgGXJ>3ve(S2{NQ&7V_8>vYLtBW?eZyP11pSXzd1Zv$7kby6G zx57?}d*-Q6M9M)YhT=^>_LA&3^)0g(O)if%zprl6WXN9M7fmuW66>qnO4UOoW>#wn zdCNNJOMZ4il~6>beAKvgXBI@Gc3%WG^Rn%k*+C|#Dx=k+wS(srz3iaSQF}oUx7NGd z#-%!|Dqc=CYB0uXWeA||n;C732`(&q64=&(fCaqn#GraK`ueuFZs^+oP*xAB_qu=yrVc8rDf`Uo4K%E}J3EFEjF&WNp?mFWeILw7WV>^aa+tf*SDJ?^@r5?3`h99Q>Fl?oZw9bLU~*KY4RSEns*4x)B>o>lc2Gf1NWdPRG7q+2l3i4&}y< z#f0?~pQHKdt1t9c`Rz?c=HdH98LCc=jo=Y5)N{`6A%WyVyWfrufx4g)ny}0E@egqu z?5g+z#&nR*0Xl8(&5fL9I^!m7(erv%RkzS~rM2ew5RgE>&*#$`w21VUOr_>m3cb}M zBbDyV2tHCfOi7S6&S`Y|#M-@msn@B^=kuf$gh?G>jhhx(4jE}_*W5+t9N!!z3! zoUOmUszK}5ZhCFzrfxY5ulaPti7NSXfy9OxJIusW%1Hpm_w`36u5zlous*B$*l{dg-;^Y^&@_uk5wX!?~MIPi!}{%GKrgzeLdkH zlQ1`!eRxsV!Qb#|PH`WvaxStu4s?9HjTBcJo+R*8%5z|*_oBa$4Mw!h<}}RbLS#jc z)G==t48#S3$?oYXJF*+0B`xl37uM5uC2-$XGUw#bJ_~o4P@a4@wpMVu=uUR9&7#nk z-MIJW4n*Ce173a}2 zl&>XMr@nVq0V!4+>IT>~54%=|M*Zkzhet^g<6QSyfrmjvh=aZjOn;uEf6=>`TbN{{ zLD0ab_Pa_#ljb&VhW`dvH@*4->q86^_${uSt?R3?u$w2QrWDA?n%iWBi55Xw07dD_ zZL;c-_1(Sf?qG@mW33jp<+bc!^mbhraC8NaAj!Z5=4~QGh9*Zqc`2&N_>1Vi!S)|y zC?SASe{GmTj1t{;t#_WY0HH524x+Yr3Xu1d*TgYyCY!_)vvky>{i{r+isS5uY~m0c zc|||+f~Ij-rG_-$yQRtz59)nrjK$05Vfml8oii`_Dc<|dhntW(c5SLV^n5^NUApJi zhj}YcuMJkQYe-DRf;SR8Vb(HuQTZ@iHCCv}Q+|C=Xys!EoFT?Phd;5S}lr)TYE0yP16&@<~ksV1srL2xw_b+X;mLsOl zrLfvTiGGS{A{P{&uq$Ma$JkbIInYqK&CEzvulI!}E&-=TmRtE(i9YXno=bbH>+ECF3B~Ayeo+`8~>t79y@KdDW|;nF+S%K_^c90Q}LZ{O4%@#UX~q03%R!1sNeY>mLwZ}t2e>U}#i_Kh+9 eFKsAh^89+r@Orow23#Ki=;;_w@=Z6-#~w}He%@x#bzhuM@aaYE zTQRp;V~h-*vWDHdbmJcx&p+SI2m$!$hiG37bWT=KKAbDYCOUc%mHhnB1(+ye9H=(8 zLurA`Q_{eBwTxqRg2$Nv^?y7BBqLO4LJa=;6k!kF5?<=6{+wg*3h&YaN9~r)L0J$r z^RRw639v1`PYYg3F71ZJro_RH1XJKjVHK(`SxO>uf6M|dS5)SRXYyQu<87?0x{)HV zrUNtv8f>UsFg{XHYnQ&iWVag^9ejUoBb*$_>r=}Uu$p!=T{(|X;!u`%xGHk!^kqYx zeGVV6+q>ITyB)nNzeU(zuN}k?Hh743)rSXF^Yy$zK64xXSQKtbfro=y6IYJK7OH1n zoxjKUsQBRh)j`K-MA zMj2Vz@ooC#wQr=Y_ zYP$e%-8;(D@*?Dibe~Dhz|Blv&fPsM8YV%#5ltHVJsYbeiNL+7^sX|z5~Q!jpX~j9 z_z|-w>S#&17Ic8R+wL!E{x6sFJ68PLDfCS{_YsjQ3}vAX&bY~Dqw{|BAKjw>U^g+* zFafFMpKYF|%GqJrVX9O)$g73lSG3uun;>r{VRYs`c+9pF+q z61M)auQhfQ)7W{O`$SI(^6nr+y>{~i@V*8YGe772zV2)J;Ba=rtd|4cDLSkJ$kC5Y zXx%V;xv}EV-FY0UaQ0n;ydz-rzF(;C9p<&F0>-dnvc#FD&UleO%$e<3Xq2kHS?4kn z&@0lW9rgyp^i%4%=!;AG*hi}>hb?Yc{if*lP0uBm%|y?#fCE)wYbgOB z4O)*2c)(De+&U2H>d&A4qmh zd5OpfZrYJy#*swhYoWA~4H2r>VeSAh_8k!NWa~`{$p>MDuT8D4W(Ahaa`lWiYa}Yt zEMH#upSV-A|GfUk51zz9?zSWwyI;ikg2^_}ceQIpHv_pb=c?XvdteNfSla&vOqGla z0{n(|%D8P`~=@`(aOJO#@p?5>S?#{}Bk${0{-}c7HlE|J* zpRywc2I6p0&=1DlWToh|^p_RGI#hYnSoYcbuA9DlFg$#|TcBvmbLl3fcym7nmdUjd zbf`q*-|(4cUqAR@0vGLCA=S}G2% zE_lP+rpsn;W(F5!FA+7kyD(gcD`r??o9JnM(bEt%u{MiF1=rLnzXLwlq{$m}6LEcB zPsAJ##oM)8nrpp|*AL}Y9M_;6?6M|H!8=iUHnk#Y-S{iqGiGj=GB5aNxR8HZAj|pUibdOy_Q|d9b4vwH z;+G~^Y)b?1aYX-hMH_c}btx%?aD?izsZmRmu?BT5*+?DG>Do z^yR>~E=r)7Xrb^cVdsjG&ll=Y3HCMSg_Xa)%MWXqc};p9+1XsQLidI}kvUHk>M1{N zfCZPvD!11pPvxa{!TPiA@t@C|We{gs1n~@fn%D9ZfshxPvA2A!o#Alz2gO%oRq&l+ zEfgBh7g8aC?_Xb8e|Edic3_i3jhjTUYGIz}x!;P0VLJB*DNDY`Of)<*3$NVzGJrd=2D$|tZft;$3YMFxoX49oj{Ixf_;RDjN>4J zeNHg{^h3Z%tnG=K!Ss^f5ewngKR))91BMV0mtbEo{-s^R$N=R#W-F2XoV+{Dc&32P z5<3mggT1iOPPw3^cb!Z=oiUfgJ=Z3)k7+>0d;@e9wx$Nl`^S2MsiZ?hUH84J*3x+1 zY7E`-BTV-U(r#n~UQ^xI9Jo@VL8~O7+ncsbs}ayCyC%aF+$qZ>g%g1lEl>{!!qupWmR~v7`7sL>s zE1ga6svYOn$9vvo^%F!m1k*n?GBV=jE(8pfIXH5ny=GG5T>jWG$sh}4e_8_@x~Y`3 z*W7cd?nTT#dusyZxy*F#ZAHNAA9G6kt1O2hrZ5<-ynwDzAo0BNVw4IEm7z)&_)o2~ z43Z^3VEVE$WL2)h-1Umxv5-M2Wazc!5V6U+CP0&y zT1c2%ynBHIQEPX8b6a_LpU^*lE}gVEG`b?2&AS~_I~BkfyD3t;S4>sf!r+KBXi}&* z*gF_S2kQl|Ir5UIBOysQXhN+1Tn*^X$UhVb`g$%nk7QSD$rHd}ICQo4Ll*__AMa9C zQYHC2)i(UJ4?YCv7EK-N#ov|3QS3nkG~yR`Ml{oGhBgglgyL&F8fkt(YKz_B_p`pS z_n+&NAvi0*bsu8@Bpv@2>1bpSgK6cbv6mL!E0n8;-K4`Jz1r;no2CgcKl^pjd)!33 z)1#3qF8`j>Q(8^9fF+9>v7SAxtlg)@TH`Qda;jz3pct~8p#nnhYCS){kc^63j5;1l zYumc_=8iWmliwGGE>uk`RDBIYWH0~PLKg9~G3YR=`08?SN4F}#-$X)jpnDeC-a@tl zdncXM!1+o#XLF?sF8iwb7K0lxAN6{~X)=_cLG1kF=@eRm=xgwVn zoUg0>e#StgWk*2`+;U+)S-+y9BB20l_HgG`mcMdWmsGlQ-k|5kF2A4 zN@ARf`)MW6=B738VqdH3?xa8^85WEdQ(pC0(q&8YeVf@P!Awa!IU0F<=v;t}{MKwl zQTn1BrqF#g;WhR+V}CZBl>cx` zrK>51@Nn(+yG*zI+p*};u!JZ*r7oi#{;wComvq=Lwot)FW{$FBS4-v$zxZk8lSh`Hsa?T2r$hP<2M&uUNU)WrK zG2Y>4BUg*D63o{*;Fkt_>#?IXX$jOyF%Pj)tHB2#j$ukGai z(1F$52G=5sMQJZblZB@4eE9&vWZ__Nt6`{+%m7UbaPd4xB%M$yqB_f&?^bbw<)PC~ zMnH3==7_w@j9B5UGLyONTy#$dH))_#H;B_vO6nocC~Xd&ya7$~(KbO|u+em(xUuJ? zsiyBNGX;_eHXL(IxYBr~jc%swG}Zo}ic5!l-#+eXKQWT;7TgvXSX{I0%`Fk~T5G;N z&MM9CT@HhdrpYv>mgGObV~h{T&xQn3bO=Pn{THrQem|O=_A|%H3?R}=O3coHsWO0w zZl&{k?fS)cqW|8-@E;{=*%Onhc{DX)KF)Tf#b5 zS8}_fLI9eieS_o<5uu+{%#h$;7+O4(w+^S+a)bS z&qkPiBP{!CfqdD7T^V}`qH4ocQiGVG2AR6|-xWbOW_RRwe5b_}0p_&s$4btV zAwnv@%f6EFxhl!lDZx+T8Q#}3|yuK|x2oitd zcgY}meaX*wcMZ5Lt>+hq$|TYT#01q&Kx-%Pka zPqqwlF@w&XQZ?R78JPv23A(-pB=P)4hPk0ziujosz*c`vQC~Ri(P=aS3LA~&k@dNi z27mij(9#kV6kG&~N#QN?+MwYMkQdbqt*4KWLI%HK9KXV!*LmEEz2<3%#R!lCJH0Ku zJ~m8FWvdv}W}_9QKPHL&RnmAsJJkwrmJyegd6Ci53cO(I#Z!IDUf`GG(7E@yqS|af zwZA>4lb$w=$bT#8^YUh_{IaWwa7ml?@jBF@5Ng|45?Nmc%Plg*6)@< zR%vtpa%HOZ;7;kwfvp^2B)#?upmP$8s_^s3#DqtXD=}0rHmWD9(7bSAw+FD*!&)0v zjhd!Z`y*D_E}K=4jakABrt?ijGOHDVq&tPC#?#4_DT|kD4w_M-PH;=3FaG(aKTC(~ z=b9G^t_HfoEjfo>UWs<88O$~AvT4>VkU1!zB4hxYTPcY)>NMiZnRAYaP8#5$<{Me#{Q!6%#Bl2W}yOn0FVB473 zENzGZD07fnYW6V&H6=OH%TY6)X|9lwVsq>pzd$`4sUUHtwN%I6?476<8#Be=WXKKQ ziB7RsX@@%zzuvib{+%Fwg}JV$0-X2OPQug$?+lxN{HvfNB!0#^1967=g7iqWH*cGf zIWJcu*ESr+>K3LdRjG{C5E1D9rdHLp62tA^;G6{ugWNTL~Ghy%0X!uRYKrG_}nQ z+Ag2Hvdyu(;dZ#A%r&=7+W*3`u*`z1B27{1)58q{Ia-41{<`45;nBA&ZQo)8;ppGr z{p{f_xyoM^~V5BL$d_P zAxsc|&E8Dk-c09#s2z*P`G$z82t_;$bq@3g41+c}udQ?gbuPXrxE?$7kK&8f!# z6`gBi_k)LJo)BZ^>wBnnWj4U}E@)ufX4t_MYgH79E(*3RfoVTJTc?0TO9G8Fa$To}%NSCD<8Y~r!Bhp2PkYg+fz8TLh8lP8R zAo~?bFafiheo(c0Sr;GI&i?9@(e}i#L0zJaZ$O$Ri8i~h?OFpHrAj`PRzBi>%f{Wp zW48IMYCqyPSbr+%T|_f^aEaibBqp8+f&K^z|B`MMf0O`$B^gSSq@`xiOu3osPcO&d zab8`R-T@DSvcWX{(`FEqPo@k@g*d@jvjf5lzsXH}tuGe4FM8T^!wo`smc2o}1jonPvSC(Iu^D!|? z(Bs|rVt+`WP})a`RDu_wjyP?WbCGLlRHj{S>hqxVp4^mlXYmUalAchD_xXoP>-2!7 zklV^O>D1pHN?{Z}zv?=xuOzc7w-kGQPcA?gqu`c`8UB=z$0)7fb!>>C`VVuRlvc|7 zLMH@3BcdFQzSbq@n-KX(vF<~D87{%?#TC4fgixQhmS+{h-f4b%_ui7w&sl<7#tLV^ z7WSQsqyGY&O|OUqw#~LriJEj#8Y!SgfzN80!=LUA+B@ZmBF`XW=}jCI3n$oJ{Go%p zJE+#~k4tyjPwa*V&5A`#9=N@r^r!}}F4}O-CjqZCPHTm)j15=2Y&hrq+HDmsxnAz4 zk+o}?(b_S}=ag$)YV~fs-E*b^6>FMj4e14iXuWp>di{R>ShKQt#|gjG#^2W9!nS8; zI!1C;?mn@q_^Zpv)ppXv6|wYJGroq1j`963jfNScE5*V^Sg%P~+M03NnoKRn0@zsR zrq4NpQ4W|F4L=J_&~F6Q=)xl|%sufgyppGyzOvt%=OGo#!reViDO_2Q5e?@5sx5(4 zTrKjbv%c;vX`KDlWh3IXQvp#kT)#m+Apa8Hf68tur5J~ZLE*en@Wz3K zcI3%+V#9~K4s^En74=h;x$?0w3YfyHWpj(GRs{J@8|9zsy-kc?lTD@#{iOzfeRF$Z zW6uCYcK#gP`DRLX*79tcoboU5KnvF|m40YnlmuU)VUS>l=n1{Xa?TSRb)Wl)fsSp& zE1+OE&Q`JR1ivq~llhgj5r%Li_n$*8`g4)?S19Db_ej#lyC4Y4cb5T;^C~2{M8{Vl z@Uo;D1`kg!Z$u{y?(zVeM(tX^qPzNu4P**Xltx(UIp$+mR-AWRrzUR9_6(tB*5ky|r_+g~$}^PCsTfzi&UFtUYiq@6J( zGCE|wccQ(*=Zf)pf4za5j#xuS)Y4q1cR!uq-RyXe*%wiz)_LzH^F*~OAijN^bPf-;>tS|Ry9PWV zWdj>FdgVd5+&H(w`~%wPM{dPLd8!A+#ZA0Z^rUkkaban_LmhTXI^=~#(v`U#0AR5> z+6$mC*xQY<>)>JRLw|Lc%JM4ff+>v;jA^|arU?bZa7N(dEy5~`i6dwfSXBH-g~bv_ zb{eFblf#ziai+TGhUiVpeB`KINAc1UJki4|SRXB#-61l}3AZ=T^UufAX_<$CrjY<{ zYiAKmJwI!h$4;0rL%3>3;q!cn+t_mBgm{Q@POGk5=8(~8e|izr+aV(}EzU%O>}1@e zSYhhpbrZbwEb_{Ar7)mwVwP$+rSh&Zw%Er(+T}v5>6-z+H-(GITH#fxBFMXi%b%2v z5y_y*XRBv$yTc_pMZJqqZb_qx7jV5q}QB*_=_#1IGIm@9F%2aZl@~`Mx z9Vs4u{CM^ssp(rc_~#wfznn7jNO=xBJx=m{_yxf}OROlVky}U15@*Z7Z343BubrF@ z0e@h*Ij+bxmyu}Y+R5J?oj-vIUV~9Qt)UXO?sST^3%s3+y*6yuX-h?Mn^_? zWV?>Ialv1SF-WgI{qk{F=I^k*zh!AS5XV;6$DpbYT0=*Sbj2-kP=s#=Dx|H=SE%Z1 zD$gV@Y`K-4SJp2I#-dI|0o$8M@9MmQsszvJvSyVslZHS}SG!@xv!+XYX{u=sUq#!4 zE}C%SKyIB(DK0m9hcS7Fv3l3chmQm6R9MEwh3F4fI>ryH#b@d=+F=vr;LxSKDdlFs zN;yQ?ONedK)gCm&MEy|b(?_J?{>axeV7>xpU(^hTM|*CL3a{f@Iu=XgJA>uAk-d2% zufuxu@}4zaM%MIAj9Fz_-D9H*c@dG1O3+t#c0<2J7_WIOd`gMJ&cALl8%dVqt<8OF z#4^BYq6iYVm((EWe;L?UxoM#9IneG$IHsfD=JH~<(TDpJ;ZbudRMRGTeju~VN7i^i z1X(`zd3Yn+h?HM&eUPw+fXnrPwl8@`!(7Wed(u2F?DCtUw0XG;csN+vl2;A-jaxM_n&cDn~Z$*nXla*8cS&@v6V=1pOIbyWdXM%O{bJxek9W4|_ds|&&0)kiP67BOU z$`rJR(Zx8z)4u;= zHPFx7BI`tEt8}=)9o{F}+^%>mXdH+;T&RK|tbE-CmLjw7ShysYg*$pZy8tf6NOfup z1#03jHuh4SetxHRX>NDtV5_GZWGv!gX=Z7FCpUR^rUj3(cLD>EXRGlb>*V*3+RZ>A z3M1ePC8h6G5v0@`gR$#B_jFM4-d!!Qj?mkW@;eF?t}@%{SD4u(+US@ptzgw1hd%Iz z{D5c+O^DI}`%Ca$6?<@cWr=F=nxSu8xEzZTIz($e2@G<)c}OmU%6RY0e!-1>;H~p; zv2H_pX&0uxVuJ;`785&B*V@a{77xkPv3pB-CDn-H-Sv$;^r(7HCj_K22ahWHH2<7} z9ps&|wl@Jbt!0L4*7?oT(>Lw*?|^1L*l!4CfgE(bShjlm6o@A|@eQ4v;hc$5{jd-+*`7sO+Bpe!$i( zV(PA##^4k7IcZ&FR$f8dvAT)r8Vu{-0po9W#_#mXdZf2fm+7#HAE{6la1{LO-pA|L zAsRuQdt<5BUw8aA0iN1TxiT-69^~-_(MU#Up6;*QijL~Vgy@uw+;HKTWjUx0(zCD_wPPqJ6QIXkzh`1O@hkZMO(@$b#-|os|FtqX>+DVcrTiQqdvf(0gLt8Newx}&P{YwGX;3$b z&%4(WO!eZ$#ie_bV6j=^;wJ%r)9f<^70a^{8gO^ue>079p0LpYR1Ui1AnZ@3l~>$IjD2gMM+hl=U{X3H(}vYg(Hi1=$dq zl-7yqOVlB3hWw(-PQvYVMRKevHp|#s0hS9X^nq5|>z#7=QrkD-|`pD-U=e!Gu3R%~F)uLvB$ATxc3-z5F8 z$+F*W!P>A-I77+~JNPnKE8BDR*!k#-@yz39F;`rzJB($~i>K95rlg;Z(;19wd@)y+ zRmhohU%`$zf?%rtYfbqj1 z(oGEyN??H<_t}u{WQFtjJ*ySI4ISnE8(HLpOVR< zdeKh*9q^K_a(iv}?~0buNM1z=bnr6wPc)~E4%U@z^E-BhpX6ba zUB2GALiRln1mF9!MmCJoRB+GGMrSJT?J8X1^~V;_anO>AH5F2hcVIs*U^l{a9E9bC z4P4m_B38QUOuiwnxJyM%8nq`jo-cc0BMv_`tpV6NH^|sP!$VQf4;V8yJ9pxqs95dS zjt0%7y;Fcr;l<5(zLn$qTDIXb8=j%ezqSybgQHdc`q3K4RLa;%v^)lrg?(aid2x9x z9JR?AHk&XUSr2mDb#RZF+rwHYZeJH^7(+-^Q;6^=wh(^EXwwhlp)jlJt5r%hYW_Ak zTz_wT8iTRM)L{0dM>^6ff^L*cRccB>p5drC6P{bga&C=?v#L*Y1YY$j26HgqylUp+ zwsJ!0m16dCiyI1@#MXT-zfOO$1jC7Sks$YRuIn~g8!j}4rR83zAA-5qt%qKhdd5R+ z)OZBh%{PEQlWR^&|0V@l?i<_j%#a$(KkE1ViP{P-{(q&m{=ZgOs^Dm@)LqU9^h+8; z??m$1ki)v)+ut@1gIl&&ctVYwrV=(FV8_ueM4#s?W`vLyk)SXhkAxCI;XaNaSy1J@ z3Wm9Md_oNFasR%5(#>h+d0dscBgcl;8BSgkX3)pa`|RxMCSSw;FA^rD)!yq7M1HIU z+-N9R#d&f|`0x0;IqL=_&@Fh>a}x-0d-2zb?KevKYkrF_+s~MiP0)hDXhN_;QFawv zR&8b(z0xMJIYr`hfPWlu#qc}qvu}4IA0A^jHKs4<_A~+a-~*a!dbf&HZJ+)xN9E)H diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_denied_light.png b/test/features/settings/screens/goldens/settings_10d_notifications_denied_light.png index fa958b51ebd1ac65cd6269d2c566c62270cf701d..a373913509998245f7b8b00def97d3dc9664d34f 100644 GIT binary patch literal 12541 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%0A+dTz0!hFG4T7!2#gCGISSaWK4+4vRkgLd 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 Np{jGY?9TmP{ts6geQW># diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_disabled_dark.png b/test/features/settings/screens/goldens/settings_10d_notifications_disabled_dark.png index a18e6f30441268a65a4c0515305ceaa4ef96e616..0068de36ceddf76e1fc04838ee6e138399f1ecc3 100644 GIT binary patch literal 13004 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 diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_disabled_light.png b/test/features/settings/screens/goldens/settings_10d_notifications_disabled_light.png index b2ae211826362c4b45d6c4664705561e40451a31..dd973e8e663e7dbbc918b1d4943b7a1e70081e5f 100644 GIT binary patch literal 13307 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 NsOa7<8T{{ajv$WH(O literal 13480 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 MWq7mv2m8nW1@V?6fdBvi diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_refused_light.png b/test/features/settings/screens/goldens/settings_10d_notifications_refused_light.png index 79f0f0b9c1d3f4bf80065ba13c9f6c16d0e18fd0..e4391f28693933b1b1e96e81cca97f3edda163fb 100644 GIT binary patch literal 13586 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 KtMsPz^Zx}nVRiEW literal 13710 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 literal 12298 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 diff --git a/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_light.png b/test/features/settings/screens/goldens/settings_10d_notifications_unsupported_light.png index 8ef18c781df8a01c8f36150b1f9e281c3da7f998..bafb490c181f4db1d81d6b07f75e94c1b5819206 100644 GIT binary patch literal 12368 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 literal 12483 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