- 同步商城 H5 登录态与原生 token - 完善商城/原生 tab 切换、动画及返回交互 - 修复七鱼客服键盘避让和状态栏恢复 - 调整开屏跳过按钮与登录入口交互
122 lines
3.3 KiB
Dart
122 lines
3.3 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
class MallWebHostState {
|
|
const MallWebHostState({
|
|
this.url,
|
|
this.visible = false,
|
|
this.isShowingQiyuPage = false,
|
|
this.isQiyuKeyboardActive = false,
|
|
});
|
|
|
|
final String? url;
|
|
final bool visible;
|
|
final bool isShowingQiyuPage;
|
|
final bool isQiyuKeyboardActive;
|
|
}
|
|
|
|
/// Process-lifetime presentation state for the resident mall WebView.
|
|
class MallWebHostController {
|
|
MallWebHostController._();
|
|
|
|
static final instance = MallWebHostController._();
|
|
|
|
final state = ValueNotifier(const MallWebHostState());
|
|
String? _pendingPreloadUrl;
|
|
Future<void> Function()? _clearCache;
|
|
Future<void> Function()? _handleSystemBack;
|
|
|
|
void open(Uri url) {
|
|
_pendingPreloadUrl = null;
|
|
state.value = MallWebHostState(url: url.toString(), visible: true);
|
|
}
|
|
|
|
void preload(Uri url) {
|
|
final current = state.value;
|
|
if (current.visible) {
|
|
if (current.url == null ||
|
|
cacheKeyFor(current.url!) != cacheKeyFor(url.toString())) {
|
|
_pendingPreloadUrl = url.toString();
|
|
}
|
|
return;
|
|
}
|
|
if (current.url != null &&
|
|
cacheKeyFor(current.url!) == cacheKeyFor(url.toString())) {
|
|
return;
|
|
}
|
|
state.value = MallWebHostState(
|
|
url: url.toString(),
|
|
visible: current.visible,
|
|
);
|
|
}
|
|
|
|
void dismiss() {
|
|
final current = state.value;
|
|
final pending = _pendingPreloadUrl;
|
|
_pendingPreloadUrl = null;
|
|
state.value = MallWebHostState(url: pending ?? current.url);
|
|
}
|
|
|
|
void setShowingQiyuPage(bool isShowingQiyuPage) {
|
|
final current = state.value;
|
|
if (current.isShowingQiyuPage == isShowingQiyuPage) return;
|
|
state.value = MallWebHostState(
|
|
url: current.url,
|
|
visible: current.visible,
|
|
isShowingQiyuPage: isShowingQiyuPage,
|
|
isQiyuKeyboardActive: isShowingQiyuPage
|
|
? current.isQiyuKeyboardActive
|
|
: false,
|
|
);
|
|
}
|
|
|
|
void setQiyuKeyboardActive(bool active) {
|
|
final current = state.value;
|
|
if (current.isQiyuKeyboardActive == active) return;
|
|
state.value = MallWebHostState(
|
|
url: current.url,
|
|
visible: current.visible,
|
|
isShowingQiyuPage: current.isShowingQiyuPage,
|
|
isQiyuKeyboardActive: active,
|
|
);
|
|
}
|
|
|
|
void attachCacheClearer(Future<void> Function() clearer) =>
|
|
_clearCache = clearer;
|
|
|
|
void detachCacheClearer() => _clearCache = null;
|
|
|
|
Future<void> clear() async {
|
|
await _clearCache?.call();
|
|
_pendingPreloadUrl = null;
|
|
state.value = const MallWebHostState();
|
|
}
|
|
|
|
static Uri uriForTheme(Uri uri, {required bool isDark}) {
|
|
final query = Map<String, List<String>>.from(uri.queryParametersAll);
|
|
query['isNight'] = [isDark ? '1' : '0'];
|
|
return uri.replace(queryParameters: query);
|
|
}
|
|
|
|
void attachSystemBackHandler(Future<void> Function() handler) {
|
|
_handleSystemBack = handler;
|
|
}
|
|
|
|
void detachSystemBackHandler() => _handleSystemBack = null;
|
|
|
|
Future<void> handleSystemBack() =>
|
|
_handleSystemBack?.call() ?? Future<void>.value();
|
|
|
|
static String cacheKeyFor(String rawUrl) {
|
|
final uri = Uri.tryParse(rawUrl);
|
|
if (uri == null) return rawUrl;
|
|
return uri
|
|
.replace(
|
|
queryParameters: uri.queryParameters['isNight'] == null
|
|
? const <String, String>{}
|
|
: <String, String>{'isNight': uri.queryParameters['isNight']!},
|
|
fragment: '',
|
|
)
|
|
.toString();
|
|
}
|
|
}
|