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 Function()? appVersionResolver, }) : _appVersionResolver = appVersionResolver ?? _readAppVersion; final VoidCallback? onClose; final VoidCallback? onLoginRequested; final ValueChanged?>? onMallStateChanged; final Future 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 _completeAppVersion(CompletionHandler handler) async { try { final version = await _appVersionResolver(); handler.complete( JsApiResult( code: 0, message: 'success', data: {'version': version}, ).toMap(), ); } catch (_) { handler.complete( const JsApiResult(code: 1, message: 'app version unavailable').toMap(), ); } } static Future _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? 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; } return null; }