From 41806be9bf4e3e42836fedd134f2c63f138c465d Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Tue, 22 Sep 2026 14:34:08 -0400 Subject: [PATCH] More platform-independent approach to managing registered state --- lib/controllers/client.dart | 6 ++- lib/controllers/unified_push.dart | 85 ++++++++++++++++--------------- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/lib/controllers/client.dart b/lib/controllers/client.dart index 90f8896..c855d0d 100644 --- a/lib/controllers/client.dart +++ b/lib/controllers/client.dart @@ -15,6 +15,7 @@ import "package:nexus/controllers/rooms.dart"; import "package:nexus/controllers/space_edges.dart"; import "package:nexus/controllers/sync_status.dart"; import "package:nexus/controllers/top_level_spaces.dart"; +import "package:nexus/controllers/unified_push.dart"; import "package:nexus/helpers/extensions/gomuks_buffer.dart"; import "package:nexus/main.dart"; import "package:nexus/models/capabilities.dart"; @@ -344,7 +345,10 @@ class ClientController extends AsyncNotifier { Future downloadMedia(DownloadMediaRequest request) async => .new((await _sendCommand("download_media", request.toJson()))["path"]); - Future logout() => _sendCommand("logout"); + Future logout() async { + await ref.watch(UnifiedPushController.provider.notifier).deregister(); + await _sendCommand("logout"); + } Future markRead(Room room) async { final eventRowId = room.timeline[room.timeline.keys.reduce(max)]; diff --git a/lib/controllers/unified_push.dart b/lib/controllers/unified_push.dart index 719a096..49a73ea 100644 --- a/lib/controllers/unified_push.dart +++ b/lib/controllers/unified_push.dart @@ -32,11 +32,11 @@ class UnifiedPushController extends AsyncNotifier { onNewEndpoint: (endpoint, instance) async { final pushKey = endpoint.pubKeySet!.pubKey; await ref - .watch(PushKeyController.provider(instance).notifier) + .read(PushKeyController.provider(instance).notifier) .set(pushKey); await ref - .watch(ClientController.provider.notifier) + .read(ClientController.provider.notifier) .registerPusher( .new( appDisplayName: "Nexus", @@ -52,6 +52,8 @@ class UnifiedPushController extends AsyncNotifier { pushKey: pushKey, ), ); + + state = .data(true); }, onMessage: (message, instance) async { debugPrint("UP message received for $instance"); @@ -61,14 +63,14 @@ class UnifiedPushController extends AsyncNotifier { ); } final event = await ref - .watch(ClientController.provider.notifier) + .read(ClientController.provider.notifier) .handlePush(json.decode(String.fromCharCodes(message.content))); if (event == null || event.unreadType?.shouldNotify() != true || (!isInBackground && await windowManager.isFocused().onError((_, _) => false) && - await ref.watch( + await ref.read( KeyController.provider(KeyController.roomKey).future, ) == event.roomId)) { @@ -103,13 +105,7 @@ class UnifiedPushController extends AsyncNotifier { if (isInBackground) exit(0); }, - onRegistrationFailed: (error, instance) => throw error, - onUnregistered: (instance) async { - await ref - .watch(PushKeyController.provider(instance).notifier) - .set(null); - ref.invalidateSelf(); - }, + onUnregistered: deregister, ); if (registered) { @@ -121,53 +117,60 @@ class UnifiedPushController extends AsyncNotifier { } Future register([bool alreadyRegistered = false]) async { - final clientStateProvider = ClientStateController.provider; - while (ref.watch(clientStateProvider)?.deviceId == null) { - await Future.delayed(.new(milliseconds: 250)); - } - final clientState = ref.watch(clientStateProvider); + state = .loading(); + try { + final clientStateProvider = ClientStateController.provider; + while (ref.read(clientStateProvider)?.deviceId == null) { + await Future.delayed(.new(milliseconds: 250)); + } + final clientState = ref.read(clientStateProvider); - final capabilities = await ref - .watch(ClientController.provider.notifier) - .getCapabilities(); + final capabilities = await ref + .read(ClientController.provider.notifier) + .getCapabilities(); - if (capabilities.webpush?.vapid == null) { - throw UnsupportedError( - "Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.", + if (capabilities.webpush?.vapid == null) { + throw UnsupportedError( + "Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.", + ); + } + + if (!alreadyRegistered && + !await UnifiedPush.tryUseCurrentOrDefaultDistributor()) { + throw Exception("No UnifiedPush distributors found"); + } + + await UnifiedPush.register( + instance: clientState!.deviceId!, + vapid: capabilities.webpush?.vapid, ); + } catch (_) { + state = .data(false); + rethrow; } - - if (!alreadyRegistered && - !await UnifiedPush.tryUseCurrentOrDefaultDistributor()) { - throw Exception("No UnifiedPush distributors found"); - } - - await UnifiedPush.register( - instance: clientState!.deviceId!, - vapid: capabilities.webpush?.vapid, - ); - - if (!alreadyRegistered) ref.invalidateSelf(); } - Future deregister() async { - final clientState = ref.watch(ClientStateController.provider); - final key = await ref.watch( - PushKeyController.provider(clientState!.deviceId!).future, + Future deregister([String? instance]) async { + final clientState = ref.read(ClientStateController.provider); + + final keyProvider = PushKeyController.provider( + instance ?? clientState!.deviceId!, ); + final key = await ref.read(keyProvider.future); if (key != null) { await ref - .watch(ClientController.provider.notifier) + .read(ClientController.provider.notifier) .deregisterPusher(.new(appId: "nexus.federated.nexus", pushKey: key)); + await ref.read(keyProvider.notifier).set(null); } else { debugPrint( "No matching pushKey found. Skipping deregistration from homeserver.", ); } - await UnifiedPush.unregister(clientState.deviceId!); - ref.invalidateSelf(); + await UnifiedPush.unregister(instance ?? clientState!.deviceId!); + state = .data(false); } static final provider = AsyncNotifierProvider(