More platform-independent approach to managing registered state

This commit is contained in:
Henry Hiles 2026-09-22 14:34:08 -04:00
commit 41806be9bf
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 49 additions and 42 deletions

View file

@ -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<int> {
Future<File> downloadMedia(DownloadMediaRequest request) async =>
.new((await _sendCommand("download_media", request.toJson()))["path"]);
Future<void> logout() => _sendCommand("logout");
Future<void> logout() async {
await ref.watch(UnifiedPushController.provider.notifier).deregister();
await _sendCommand("logout");
}
Future<void> markRead(Room room) async {
final eventRowId = room.timeline[room.timeline.keys.reduce(max)];

View file

@ -32,11 +32,11 @@ class UnifiedPushController extends AsyncNotifier<bool> {
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<bool> {
pushKey: pushKey,
),
);
state = .data(true);
},
onMessage: (message, instance) async {
debugPrint("UP message received for $instance");
@ -61,14 +63,14 @@ class UnifiedPushController extends AsyncNotifier<bool> {
);
}
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<bool> {
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,14 +117,16 @@ class UnifiedPushController extends AsyncNotifier<bool> {
}
Future<void> register([bool alreadyRegistered = false]) async {
state = .loading();
try {
final clientStateProvider = ClientStateController.provider;
while (ref.watch(clientStateProvider)?.deviceId == null) {
while (ref.read(clientStateProvider)?.deviceId == null) {
await Future.delayed(.new(milliseconds: 250));
}
final clientState = ref.watch(clientStateProvider);
final clientState = ref.read(clientStateProvider);
final capabilities = await ref
.watch(ClientController.provider.notifier)
.read(ClientController.provider.notifier)
.getCapabilities();
if (capabilities.webpush?.vapid == null) {
@ -146,28 +144,33 @@ class UnifiedPushController extends AsyncNotifier<bool> {
instance: clientState!.deviceId!,
vapid: capabilities.webpush?.vapid,
);
if (!alreadyRegistered) ref.invalidateSelf();
} catch (_) {
state = .data(false);
rethrow;
}
}
Future<void> deregister() async {
final clientState = ref.watch(ClientStateController.provider);
final key = await ref.watch(
PushKeyController.provider(clientState!.deviceId!).future,
Future<void> 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<UnifiedPushController, bool>(