fix race condition on startup

This commit is contained in:
Henry Hiles 2026-09-22 11:36:29 -04:00
commit 6e47594a91
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
3 changed files with 74 additions and 68 deletions

View file

@ -7,7 +7,7 @@ class MultiProviderController(final IList<AsyncNotifierProvider> providers)
extends AsyncNotifier<void> { extends AsyncNotifier<void> {
@override @override
Future<void> build() => .wait( Future<void> build() => .wait(
providers.map((provider) => ref.read(provider.future)), providers.map((provider) => ref.watch(provider.future)),
eagerError: true, eagerError: true,
); );

View file

@ -22,7 +22,6 @@ class UnifiedPushController extends AsyncNotifier<bool> {
Future<bool> build() async { Future<bool> build() async {
if (!Platform.isLinux && !Platform.isAndroid) return false; if (!Platform.isLinux && !Platform.isAndroid) return false;
final client = ref.watch(ClientController.provider.notifier);
final registered = await UnifiedPush.initialize( final registered = await UnifiedPush.initialize(
linuxOptions: .new( linuxOptions: .new(
dbusName: "nexus.federated.nexus.UnifiedPush", dbusName: "nexus.federated.nexus.UnifiedPush",
@ -36,7 +35,9 @@ class UnifiedPushController extends AsyncNotifier<bool> {
.watch(PushKeyController.provider(instance).notifier) .watch(PushKeyController.provider(instance).notifier)
.set(pushKey); .set(pushKey);
await client.registerPusher( await ref
.watch(ClientController.provider.notifier)
.registerPusher(
.new( .new(
appDisplayName: "Nexus", appDisplayName: "Nexus",
appId: "nexus.federated.nexus", appId: "nexus.federated.nexus",
@ -59,9 +60,9 @@ class UnifiedPushController extends AsyncNotifier<bool> {
"Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.", "Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.",
); );
} }
final event = await client.handlePush( final event = await ref
json.decode(String.fromCharCodes(message.content)), .watch(ClientController.provider.notifier)
); .handlePush(json.decode(String.fromCharCodes(message.content)));
if (event == null || if (event == null ||
event.unreadType?.shouldNotify() != true || event.unreadType?.shouldNotify() != true ||
@ -120,8 +121,11 @@ class UnifiedPushController extends AsyncNotifier<bool> {
} }
Future<void> register([bool alreadyRegistered = false]) async { Future<void> register([bool alreadyRegistered = false]) async {
final clientState = ref.watch(ClientStateController.provider); final clientStateProvider = ClientStateController.provider;
if (clientState?.deviceId == null) return ref.invalidateSelf(); while (ref.watch(clientStateProvider)?.deviceId == null) {
await Future.delayed(.new(milliseconds: 250));
}
final clientState = ref.watch(clientStateProvider);
final capabilities = await ref final capabilities = await ref
.watch(ClientController.provider.notifier) .watch(ClientController.provider.notifier)

View file

@ -151,8 +151,7 @@ class const App({super.key}) extends StatelessWidget {
builder: (_, ref, _) => ref builder: (_, ref, _) => ref
.watch(ClientController.provider) .watch(ClientController.provider)
.betterWhen( .betterWhen(
data: (_) => ref data: (_) => switch (ref.watch(
.watch(
MultiProviderController.provider( MultiProviderController.provider(
.new([ .new([
NotificationController.provider, NotificationController.provider,
@ -162,16 +161,14 @@ class const App({super.key}) extends StatelessWidget {
KeyController.provider(KeyController.spaceKey), KeyController.provider(KeyController.spaceKey),
]), ]),
), ),
) )) {
.betterWhen( AsyncData(value: _) || AsyncLoading(value: _?) => Consumer(
data: (_) => Consumer(
builder: (_, ref, _) { builder: (_, ref, _) {
final clientState = ref.watch( final clientState = ref.watch(
ClientStateController.provider, ClientStateController.provider,
); );
if (clientState == null || if (clientState == null || !clientState.isInitialized) {
!clientState.isInitialized) {
return Loading(); return Loading();
} }
@ -184,8 +181,8 @@ class const App({super.key}) extends StatelessWidget {
} }
}, },
), ),
),
loading: () => Scaffold( AsyncLoading _ => Scaffold(
appBar: Appbar( appBar: Appbar(
actions: .new([ actions: .new([
IconButton( IconButton(
@ -199,6 +196,11 @@ class const App({super.key}) extends StatelessWidget {
), ),
body: Loading(), body: Loading(),
), ),
AsyncError(:final error, :final stackTrace) => ErrorDialog(
error,
stackTrace,
),
},
), ),
), ),
), ),