67 lines
2.3 KiB
Dart
67 lines
2.3 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:hooks_riverpod/misc.dart';
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
|
|
import '../../models/pb/jinzhi/v1/push.pb.dart' as pb;
|
|
import '../network/api_exception.dart';
|
|
import 'notification_permission.dart';
|
|
import 'push_api_client.dart';
|
|
import 'umeng_push_service.dart';
|
|
|
|
class DevicePushRegistrar {
|
|
DevicePushRegistrar(this._read);
|
|
final T Function<T>(ProviderListenable<T>) _read;
|
|
StreamSubscription<String>? _subscription;
|
|
String? _lastToken;
|
|
bool? _lastPermission;
|
|
Future<void> _registrationQueue = Future.value();
|
|
|
|
void start() {
|
|
_subscription ??= UmengPushService.onDeviceToken.listen(_enqueue);
|
|
UmengPushService.emitCachedToken();
|
|
}
|
|
|
|
Future<void> stop() async => _subscription?.cancel();
|
|
Future<void> refresh() => UmengPushService.refreshDeviceToken();
|
|
void forceRegisterCurrentToken() {
|
|
// BLOCKED(server contract): guest registration is intentionally preserved.
|
|
// Do not add a client-side unbind call until the backend confirms whether
|
|
// guest registration reliably clears the previous user binding.
|
|
_lastToken = null;
|
|
_lastPermission = null;
|
|
UmengPushService.emitCachedToken();
|
|
}
|
|
|
|
void _enqueue(String token) {
|
|
_registrationQueue = _registrationQueue
|
|
.catchError((_) {})
|
|
.then((_) => _register(token));
|
|
}
|
|
|
|
Future<void> _register(String token) async {
|
|
final permission = await NotificationPermission.isGranted();
|
|
if (token == _lastToken && permission == _lastPermission) return;
|
|
final package = await PackageInfo.fromPlatform();
|
|
final request = pb.RegisterPushDeviceRequest(
|
|
umengDeviceToken: token,
|
|
platform: defaultTargetPlatform == TargetPlatform.iOS
|
|
? pb.Platform.PLATFORM_IOS
|
|
: pb.Platform.PLATFORM_ANDROID,
|
|
appVersion: package.version,
|
|
permissionGranted: permission,
|
|
);
|
|
for (var attempt = 0; attempt < 4; attempt++) {
|
|
try {
|
|
await _read(pushApiClientProvider).registerDevice(request);
|
|
_lastToken = token;
|
|
_lastPermission = permission;
|
|
return;
|
|
} catch (error) {
|
|
if (attempt == 3 || !ApiException.from(error).isRetryable) return;
|
|
await Future<void>.delayed(Duration(seconds: 1 << attempt));
|
|
}
|
|
}
|
|
}
|
|
}
|