improve UP timeout behavior
Hopefully more reliable.
This commit is contained in:
parent
61c5aa94c2
commit
3c6c610f7c
2 changed files with 93 additions and 55 deletions
|
|
@ -18,6 +18,8 @@ import "package:unifiedpush_storage_shared_preferences/storage.dart";
|
||||||
import "package:window_manager/window_manager.dart";
|
import "package:window_manager/window_manager.dart";
|
||||||
|
|
||||||
class UnifiedPushController extends AsyncNotifier<bool> {
|
class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
|
Completer<void>? _endpoint;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> build() async {
|
Future<bool> build() async {
|
||||||
if (!Platform.isLinux && !Platform.isAndroid) return false;
|
if (!Platform.isLinux && !Platform.isAndroid) return false;
|
||||||
|
|
@ -30,33 +32,45 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
shouldWriteService: false,
|
shouldWriteService: false,
|
||||||
),
|
),
|
||||||
onNewEndpoint: (endpoint, instance) async {
|
onNewEndpoint: (endpoint, instance) async {
|
||||||
final pushKey = endpoint.pubKeySet!.pubKey;
|
final task = Future(() async {
|
||||||
await ref
|
final pushKey = endpoint.pubKeySet!.pubKey;
|
||||||
.read(PushKeyController.provider(instance).notifier)
|
await ref
|
||||||
.set(pushKey);
|
.read(PushKeyController.provider(instance).notifier)
|
||||||
|
.set(pushKey);
|
||||||
|
|
||||||
await ref
|
await ref
|
||||||
.read(ClientController.provider.notifier)
|
.read(ClientController.provider.notifier)
|
||||||
.registerPusher(
|
.registerPusher(
|
||||||
.new(
|
.new(
|
||||||
appDisplayName: "Nexus",
|
appDisplayName: "Nexus",
|
||||||
appId: "nexus.federated.nexus",
|
appId: "nexus.federated.nexus",
|
||||||
data: .webPush(
|
data: .webPush(
|
||||||
url: .parse(endpoint.url),
|
url: .parse(endpoint.url),
|
||||||
auth: endpoint.pubKeySet!.auth,
|
auth: endpoint.pubKeySet!.auth,
|
||||||
|
),
|
||||||
|
deviceDisplayName:
|
||||||
|
"Nexus on ${toBeginningOfSentenceCase(Platform.operatingSystem)}",
|
||||||
|
kind: .webPush,
|
||||||
|
lang: "en",
|
||||||
|
pushKey: pushKey,
|
||||||
),
|
),
|
||||||
deviceDisplayName:
|
);
|
||||||
"Nexus on ${toBeginningOfSentenceCase(Platform.operatingSystem)}",
|
|
||||||
kind: .webPush,
|
|
||||||
lang: "en",
|
|
||||||
pushKey: pushKey,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
state = .data(true);
|
state = .data(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_endpoint case final completer? when !completer.isCompleted) {
|
||||||
|
completer.complete(task);
|
||||||
|
} else {
|
||||||
|
await task;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onRegistrationFailed: (reason, instance) {
|
onRegistrationFailed: (reason, instance) {
|
||||||
throw reason;
|
if (_endpoint case final completer? when !completer.isCompleted) {
|
||||||
|
completer.completeError(reason);
|
||||||
|
} else {
|
||||||
|
throw reason;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onMessage: (message, instance) async {
|
onMessage: (message, instance) async {
|
||||||
debugPrint("UP message received for $instance");
|
debugPrint("UP message received for $instance");
|
||||||
|
|
@ -111,48 +125,68 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
||||||
onUnregistered: deregister,
|
onUnregistered: deregister,
|
||||||
);
|
);
|
||||||
|
|
||||||
ref.listen(
|
if (!registered) return false;
|
||||||
ClientStateController.provider.select((value) => value?.deviceId),
|
|
||||||
(_, _) => register(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (registered) {
|
try {
|
||||||
// Needs to be registered every startup
|
return await register();
|
||||||
await register();
|
} catch (error, stackTrace) {
|
||||||
|
showError(error, stackTrace);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return registered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> register() async {
|
Future<bool> register() async {
|
||||||
state = .loading();
|
state = .loading();
|
||||||
try {
|
try {
|
||||||
final deviceId = ref.read(
|
final deviceIdCompleter = Completer<String>();
|
||||||
|
final subscription = ref.listen(
|
||||||
ClientStateController.provider.select((value) => value?.deviceId),
|
ClientStateController.provider.select((value) => value?.deviceId),
|
||||||
|
(_, next) {
|
||||||
|
if (next != null && !deviceIdCompleter.isCompleted) {
|
||||||
|
deviceIdCompleter.complete(next);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fireImmediately: true,
|
||||||
|
);
|
||||||
|
final deviceId = await deviceIdCompleter.future.whenComplete(
|
||||||
|
subscription.close,
|
||||||
);
|
);
|
||||||
if (deviceId == null) return;
|
|
||||||
|
|
||||||
final capabilities = await ref
|
await Future(() async {
|
||||||
.read(ClientController.provider.notifier)
|
final capabilities = await ref
|
||||||
.getCapabilities();
|
.read(ClientController.provider.notifier)
|
||||||
|
.getCapabilities();
|
||||||
|
|
||||||
if (capabilities.webpush?.vapid == null) {
|
if (capabilities.webpush?.vapid == null) {
|
||||||
throw UnsupportedError(
|
throw UnsupportedError(
|
||||||
"Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.",
|
"Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await UnifiedPush.tryUseCurrentOrDefaultDistributor()) {
|
if (!await UnifiedPush.tryUseCurrentOrDefaultDistributor()) {
|
||||||
throw Exception("No UnifiedPush distributors found.");
|
throw Exception("No UnifiedPush distributors found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await UnifiedPush.register(
|
final endpoint = _endpoint = Completer<void>();
|
||||||
instance: deviceId,
|
|
||||||
vapid: capabilities.webpush?.vapid,
|
try {
|
||||||
).timeout(
|
await Future.wait([
|
||||||
.new(seconds: 15),
|
UnifiedPush.register(
|
||||||
|
instance: deviceId,
|
||||||
|
vapid: capabilities.webpush?.vapid,
|
||||||
|
),
|
||||||
|
endpoint.future,
|
||||||
|
], eagerError: true);
|
||||||
|
} finally {
|
||||||
|
if (_endpoint == endpoint) _endpoint = null;
|
||||||
|
}
|
||||||
|
}).timeout(
|
||||||
|
.new(seconds: 10),
|
||||||
onTimeout: () => throw Exception("UnifiedPush registration timed out."),
|
onTimeout: () => throw Exception("UnifiedPush registration timed out."),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state = .data(true);
|
||||||
|
return true;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
state = .data(false);
|
state = .data(false);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,11 @@ import "package:unifiedpush/unifiedpush.dart";
|
||||||
class UnifiedPushAllowedController extends AsyncNotifier<String?> {
|
class UnifiedPushAllowedController extends AsyncNotifier<String?> {
|
||||||
@override
|
@override
|
||||||
Future<String?> build() async {
|
Future<String?> build() async {
|
||||||
if (!await UnifiedPush.tryUseCurrentOrDefaultDistributor()) {
|
if (!await UnifiedPush.tryUseCurrentOrDefaultDistributor().timeout(
|
||||||
|
.new(seconds: 10),
|
||||||
|
onTimeout: () =>
|
||||||
|
throw Exception("UnifiedPush distributor check timed out."),
|
||||||
|
)) {
|
||||||
return "No valid distributors found. ${Platform.isLinux
|
return "No valid distributors found. ${Platform.isLinux
|
||||||
? "Try installing KUnifiedPush"
|
? "Try installing KUnifiedPush"
|
||||||
: Platform.isAndroid
|
: Platform.isAndroid
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue