fix:第一轮跑
This commit is contained in:
1 parent
e834ec7586
commit
33235f450b
56 files changed
+4357
-210
No files matched your search
@@ -0,0 +1,218 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:umeng_verify_sdk/umeng_verify_sdk.dart';
|
||||
|
||||
import '../../../common/config/app_h5_urls.dart';
|
||||
import '../../../common/tracking/umeng_service.dart';
|
||||
|
||||
enum OneKeyLoginOutcome { success, fallback, cancelled, unsupported, busy }
|
||||
|
||||
/// Runs only after an explicit user login action. Do not add an availability
|
||||
/// probe or `accelerateLoginPage` outside this class: Xiaomi rejects that as
|
||||
/// background carrier-auth prefetch.
|
||||
class OneKeyLoginService {
|
||||
Future<OneKeyLoginOutcome>? _operation;
|
||||
bool _authPageOpened = false;
|
||||
bool _terminal = false;
|
||||
Timer? _resumeCancellation;
|
||||
void Function(OneKeyLoginOutcome)? _completeCurrent;
|
||||
|
||||
Future<OneKeyLoginOutcome> start({
|
||||
required BuildContext context,
|
||||
required Future<void> Function(String token) verifyToken,
|
||||
VoidCallback? onNativeRequestDispatched,
|
||||
VoidCallback? onAuthPageOpened,
|
||||
}) {
|
||||
if (_operation != null) return Future.value(OneKeyLoginOutcome.busy);
|
||||
_terminal = false;
|
||||
_authPageOpened = false;
|
||||
final operation = _start(
|
||||
context: context,
|
||||
verifyToken: verifyToken,
|
||||
onNativeRequestDispatched: onNativeRequestDispatched,
|
||||
onAuthPageOpened: onAuthPageOpened,
|
||||
);
|
||||
_operation = operation;
|
||||
return operation.whenComplete(() {
|
||||
_operation = null;
|
||||
_completeCurrent = null;
|
||||
});
|
||||
}
|
||||
|
||||
Future<OneKeyLoginOutcome> _start({
|
||||
required BuildContext context,
|
||||
required Future<void> Function(String token) verifyToken,
|
||||
VoidCallback? onNativeRequestDispatched,
|
||||
VoidCallback? onAuthPageOpened,
|
||||
}) async {
|
||||
if (kIsWeb || (!Platform.isAndroid && !Platform.isIOS)) {
|
||||
return OneKeyLoginOutcome.unsupported;
|
||||
}
|
||||
final uiConfig = _uiConfig(context);
|
||||
await UmengService.initOneKeyLoginIfAllowed();
|
||||
final completer = Completer<OneKeyLoginOutcome>();
|
||||
|
||||
void complete(OneKeyLoginOutcome outcome) {
|
||||
if (_terminal) return;
|
||||
_terminal = true;
|
||||
_resumeCancellation?.cancel();
|
||||
_resumeCancellation = null;
|
||||
_clearCallbacks();
|
||||
completer.complete(outcome);
|
||||
}
|
||||
|
||||
_completeCurrent = complete;
|
||||
|
||||
void handleUiResult(Object? result) {
|
||||
final code = _code(result);
|
||||
if (code == '700000') complete(OneKeyLoginOutcome.cancelled);
|
||||
if (code == '700001') complete(OneKeyLoginOutcome.fallback);
|
||||
}
|
||||
|
||||
void handleTokenResult(Object? result) {
|
||||
final code = _code(result);
|
||||
// iOS 700002 is only the native button click; token follows later.
|
||||
if (Platform.isIOS && code == '700002') return;
|
||||
// 600024 is Android environment availability, not a login result.
|
||||
if (code == '600024') return;
|
||||
if (code == '600001') {
|
||||
if (!_authPageOpened) {
|
||||
_authPageOpened = true;
|
||||
onAuthPageOpened?.call();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (code == '700000') {
|
||||
complete(OneKeyLoginOutcome.cancelled);
|
||||
return;
|
||||
}
|
||||
if (code == '700001') {
|
||||
complete(OneKeyLoginOutcome.fallback);
|
||||
return;
|
||||
}
|
||||
if (code != '600000' || result is! Map) {
|
||||
complete(OneKeyLoginOutcome.fallback);
|
||||
return;
|
||||
}
|
||||
final token = result['token']?.toString();
|
||||
if (token == null || token.isEmpty) {
|
||||
complete(OneKeyLoginOutcome.fallback);
|
||||
return;
|
||||
}
|
||||
unawaited(() async {
|
||||
try {
|
||||
await verifyToken(token);
|
||||
complete(OneKeyLoginOutcome.success);
|
||||
} catch (_) {
|
||||
complete(OneKeyLoginOutcome.fallback);
|
||||
} finally {
|
||||
_closeNativePage();
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
if (Platform.isIOS) {
|
||||
UmengVerifySdk.getLoginTokenCallback(handleTokenResult);
|
||||
UmengVerifySdk.getWidgetEventCallback((_) {});
|
||||
} else {
|
||||
UmengVerifySdk.setTokenResultCallback_android(handleTokenResult);
|
||||
UmengVerifySdk.setUIClickCallback_android(handleUiResult);
|
||||
}
|
||||
try {
|
||||
final request = UmengVerifySdk.getLoginTokenWithTimeout(3, uiConfig);
|
||||
onNativeRequestDispatched?.call();
|
||||
unawaited(
|
||||
request.catchError((Object _) {
|
||||
complete(OneKeyLoginOutcome.unsupported);
|
||||
}),
|
||||
);
|
||||
return await completer.future.timeout(
|
||||
const Duration(seconds: 20),
|
||||
onTimeout: () => OneKeyLoginOutcome.fallback,
|
||||
);
|
||||
} finally {
|
||||
_clearCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
void onAppResumed() {
|
||||
if (!Platform.isAndroid ||
|
||||
!_authPageOpened ||
|
||||
_terminal ||
|
||||
_resumeCancellation != null) {
|
||||
return;
|
||||
}
|
||||
_resumeCancellation = Timer(const Duration(milliseconds: 500), () {
|
||||
_resumeCancellation = null;
|
||||
if (_terminal) return;
|
||||
_completeCurrent?.call(OneKeyLoginOutcome.cancelled);
|
||||
_closeNativePage();
|
||||
});
|
||||
}
|
||||
|
||||
UMCustomModel _uiConfig(BuildContext context) {
|
||||
const ink = Color(0xFF202124);
|
||||
const muted = Color(0xFF8A8F98);
|
||||
const background = Color(0xFFFFFFFF);
|
||||
final model = UMCustomModel()
|
||||
..logoIsHidden = true
|
||||
..numberColor = ink.toARGB32()
|
||||
..numberFont = 30
|
||||
..navTitle = ['', Colors.transparent.toARGB32(), 0]
|
||||
..navColor = background.toARGB32()
|
||||
..backgroundColor_ios = background.toARGB32()
|
||||
..sloganText = ['', background.toARGB32(), 0]
|
||||
..privacyPreText = '我已阅读并同意'
|
||||
..privacyOne = ['《隐私政策》', AppH5Urls.privacyUrl]
|
||||
..privacyTwo = ['《用户协议》', AppH5Urls.userProtocolUrl]
|
||||
..privacyColors = [muted.toARGB32(), ink.toARGB32()]
|
||||
..changeBtnTitle = ['其他手机号登录', ink.toARGB32(), 16]
|
||||
..loginBtnText = ['本机号码一键登录', Colors.white.toARGB32(), 16]
|
||||
..privacyFont = 12
|
||||
..checkBoxIsChecked = false;
|
||||
if (Platform.isAndroid) {
|
||||
model.numberFrame = [-1, 156, -1, -1];
|
||||
model.loginBtnFrame = [-1, 283, -1, -1, 52];
|
||||
model.changeBtnFrame = [368, -1, -1, -1];
|
||||
model.privacyFrame = [-1, 427, -1, -1];
|
||||
} else {
|
||||
final title = UMCustomWidget('title', UMCustomWidgetType.textView)
|
||||
..title = '金值'
|
||||
..titleFont = 26
|
||||
..titleColor = ink.toARGB32()
|
||||
..width = MediaQuery.sizeOf(context).width.toInt()
|
||||
..height = 54
|
||||
..top = 26
|
||||
..textAlignment = UMCustomWidgetTextAlignmentType.center
|
||||
..isClickEnable = false
|
||||
..rootViewId = UMRootViewId.body;
|
||||
model.customWidget = [title.toJsonMap()];
|
||||
model.privacyFont = 13;
|
||||
model.checkBoxWH = 20;
|
||||
model.checkBoxIsChecked = true;
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
String _code(Object? result) => result is Map
|
||||
? (result['code'] ?? result['resultCode'] ?? '').toString()
|
||||
: '';
|
||||
|
||||
void _clearCallbacks() {
|
||||
UmengVerifySdk.getLoginTokenCallback(null);
|
||||
UmengVerifySdk.getWidgetEventCallback(null);
|
||||
UmengVerifySdk.setTokenResultCallback_android(null);
|
||||
UmengVerifySdk.setUIClickCallback_android(null);
|
||||
}
|
||||
|
||||
void _closeNativePage() {
|
||||
if (Platform.isIOS) {
|
||||
unawaited(UmengVerifySdk.cancelLoginVCAnimated(true));
|
||||
} else {
|
||||
UmengVerifySdk.quitLoginPage_android();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user