Files
jingyun 3b089e2205 feat: 对齐常驻商城与七鱼客服交互
- 同步商城 H5 登录态与原生 token
- 完善商城/原生 tab 切换、动画及返回交互
- 修复七鱼客服键盘避让和状态栏恢复
- 调整开屏跳过按钮与登录入口交互
2026-09-07 15:47:01 +08:00

88 lines
2.4 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:dsbridge_flutter/dsbridge_flutter.dart';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'js_api_result.dart';
class JsApi extends JavaScriptNamespaceInterface {
JsApi({
this.onClose,
this.onLoginRequested,
this.onMallStateChanged,
Future<String> Function()? appVersionResolver,
}) : _appVersionResolver = appVersionResolver ?? _readAppVersion;
final VoidCallback? onClose;
final VoidCallback? onLoginRequested;
final ValueChanged<Map<dynamic, dynamic>?>? onMallStateChanged;
final Future<String> Function() _appVersionResolver;
@override
void register() {
registerFunction(close);
registerFunction(getAppVersion);
registerFunction(mallStateChanged);
registerFunction(login);
}
@pragma('vm:entry-point')
void close(dynamic arg, CompletionHandler handler) {
onClose?.call();
handler.complete(const JsApiResult.success().toMap());
}
@pragma('vm:entry-point')
void getAppVersion(dynamic arg, CompletionHandler handler) {
unawaited(_completeAppVersion(handler));
}
Future<void> _completeAppVersion(CompletionHandler handler) async {
try {
final version = await _appVersionResolver();
handler.complete(
JsApiResult(
code: 0,
message: 'success',
data: <String, dynamic>{'version': version},
).toMap(),
);
} catch (_) {
handler.complete(
const JsApiResult(code: 1, message: 'app version unavailable').toMap(),
);
}
}
static Future<String> _readAppVersion() async =>
(await PackageInfo.fromPlatform()).version;
@pragma('vm:entry-point')
void mallStateChanged(dynamic arg, CompletionHandler handler) {
onMallStateChanged?.call(coerceMallStateMap(arg));
handler.complete(const JsApiResult.success().toMap());
}
@pragma('vm:entry-point')
void login(dynamic arg, CompletionHandler handler) {
onLoginRequested?.call();
handler.complete(const JsApiResult.success().toMap());
}
}
Map<dynamic, dynamic>? coerceMallStateMap(dynamic arg) {
if (arg is Map) return arg;
if (arg is String && arg.isNotEmpty) {
try {
final decoded = jsonDecode(arg);
if (decoded is Map) return decoded;
} catch (_) {}
}
if (arg is List && arg.isNotEmpty && arg.first is Map) {
return arg.first as Map<dynamic, dynamic>;
}
return null;
}