Commit f9f42622 by tanghuan

增加setScreen指令,整改openLink指令增加参数,以及实现从openLink返回时获取返回值

1 parent ca90354c
import 'dart:convert';
import 'package:appframe/config/routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:webview_flutter/webview_flutter.dart';
......@@ -8,22 +11,26 @@ class LinkState extends Equatable {
final bool loaded;
final String url;
final String title;
final int screenType; // 1: 竖屏, 2: 横屏
const LinkState({
this.loaded = false,
this.url = '',
this.title = '',
this.screenType = 1,
});
LinkState copyWith({
bool? loaded,
String? url,
String? title,
int? screenType,
}) {
return LinkState(
loaded: loaded ?? this.loaded,
url: url ?? this.url,
title: title ?? this.title,
screenType: screenType ?? this.screenType,
);
}
......@@ -32,15 +39,21 @@ class LinkState extends Equatable {
loaded,
url,
title,
screenType,
];
}
class LinkCubit extends Cubit<LinkState> {
late final WebViewController _controller;
String? msg;
WebViewController get controller => _controller;
LinkCubit(super.initialState) {
if (state.screenType != 1) {
_setOrientation(2);
}
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
......@@ -64,19 +77,64 @@ class LinkCubit extends Cubit<LinkState> {
},
),
)
..addJavaScriptChannel("xeJsBridge", onMessageReceived: (JavaScriptMessage message) {})
..loadRequest(Uri.parse(state.url));
}
void _onMessageReceived(JavaScriptMessage message) async {
// try {
// _dispatcher.dispatch(message.message, (response) {
// _sendResponse(response);
// }, webCubit: this);
// } catch (e) {
// debugPrint('消息解析错误: $e');
// }
}
// 向H5发送响应
void _sendResponse(Map<String, dynamic> response) {
String jsonString = jsonEncode(response);
String escapedJson = jsonString.replaceAll('"', '\\"');
final String script = 'xeJsBridgeCallback("$escapedJson");';
_controller.runJavaScript(script);
}
void _finishLoading() {
emit(state.copyWith(loaded: true));
}
Future<void> handleBack(BuildContext context) async {
// 设置屏幕方向
void _setOrientation(int screenType) {
if (screenType == 2) {
// 横屏模式
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
} else {
// 竖屏模式(默认)
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
}
Future<void> handleBack() async {
if (await _controller.canGoBack()) {
_controller.goBack();
} else {
// context.pop(true);
router.pop('ok');
router.pop(msg);
}
}
@override
Future<void> close() {
// 恢复为竖屏模式
if (state.screenType != 1) {
_setOrientation(1);
}
return super.close();
}
}
......@@ -280,9 +280,9 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
_loginIM();
// 针对ios系统,处理侧滑返回
if (Platform.isIOS) {
//if (Platform.isIOS) {
WebCubitHolder.register(this);
}
//}
}
Future<Map<String, String>> _getVersionConfig() async {
......@@ -520,6 +520,21 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
_sendResponse(resp);
}
///
/// 设置主Web状态
/// active: 1-激活状态 2-隐藏状态
///
void handleWebStatus(int active, {String extData = ''}) {
// setWebStatus指令
var resp = {
'unique': '',
'cmd': 'setWebStatus',
'data': {'active': active, 'extData': extData},
'errMsg': ''
};
_sendResponse(resp);
}
Future<void> handleToggleDebug() async {
var sharedPreferences = getIt.get<SharedPreferences>();
var debug = sharedPreferences.getInt('debug') ?? 0;
......@@ -1206,9 +1221,9 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
await _playerService?.close();
await _recorderService?.close();
if (Platform.isIOS) {
// if (Platform.isIOS) {
WebCubitHolder.unregister();
}
// }
// 移除观察者
WidgetsBinding.instance.removeObserver(this);
......
......@@ -24,6 +24,7 @@ import 'package:appframe/data/repositories/message/role_info_handler.dart';
import 'package:appframe/data/repositories/message/save_file_to_disk_handler.dart';
import 'package:appframe/data/repositories/message/save_to_album_handler.dart';
import 'package:appframe/data/repositories/message/scan_code_handler.dart';
import 'package:appframe/data/repositories/message/screen_handler.dart';
import 'package:appframe/data/repositories/message/share_handler.dart';
import 'package:appframe/data/repositories/message/share_to_wx_handler.dart';
import 'package:appframe/data/repositories/message/storage_handler.dart';
......@@ -192,6 +193,9 @@ Future<void> setupLocator() async {
/// 设置用户角色信息
getIt.registerLazySingleton<MessageHandler>(() => RoleInfoHandler(), instanceName: 'setRoleInfo');
/// 设置屏幕模式
getIt.registerLazySingleton<MessageHandler>(() => ScreenHandler(), instanceName: 'setScreen');
/// service
///
/// local server
......
......@@ -18,7 +18,7 @@ import 'package:go_router/go_router.dart';
final GoRouter router = GoRouter(
initialLocation: '/web',
observers: Platform.isIOS ? [AppRouteObserver()] : [],
observers: Platform.isIOS ? [LinkPageObserver(), IosGestureObserver()] : [LinkPageObserver()],
routes: <RouteBase>[
GoRoute(
path: '/web',
......@@ -92,53 +92,98 @@ final GoRouter router = GoRouter(
///
/// 只针对iOS使用
///
class AppRouteObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
class IosGestureObserver extends NavigatorObserver {
// @override
// void didPush(Route route, Route? previousRoute) {
// super.didPush(route, previousRoute);
//
// if (route.settings.name == '/web') {
// // push时,当前路由为 /web,代表 /web 路由被push进栈,展示web页面
// // 设置手势监听回调
// debugPrint("设置监听--------");
// IosEdgeSwipeDetector.onEdgeSwipe(
// () {
// WebCubitHolder.instance?.handleBack();
// },
// );
// } else if (previousRoute?.settings.name == '/web') {
// // push时,前一个路由是 /web,代表是从web页进入此页面
// // 将手势监听回调取消
// debugPrint("取消监听--------");
// IosEdgeSwipeDetector.dispose();
// }
// }
//
// @override
// void didPop(Route route, Route? previousRoute) {
// super.didPop(route, previousRoute);
//
// if (previousRoute?.settings.name == '/web') {
// // Pop时, 前一个路由是/web,代表回到web页面
// // 设置手势监听回调
// debugPrint("设置监听--------");
// IosEdgeSwipeDetector.onEdgeSwipe(
// () {
// WebCubitHolder.instance?.handleBack();
// },
// );
// }
// }
//
// @override
// void didRemove(Route route, Route? previousRoute) {
// super.didRemove(route, previousRoute);
//
// if (route.settings.name == '/web') {
// // remove时, 当前路由为 /web, 代表 /web 路由被删除,展示的不是web页面
// // 将手势监听回调取消
// debugPrint("取消监听--------");
// IosEdgeSwipeDetector.dispose();
// }
// }
if (route.settings.name == '/web') {
// push时,当前路由为 /web,代表 /web 路由被push进栈,展示web页面
// 设置手势监听回调
@override
void didChangeTop(Route<dynamic> topRoute, Route<dynamic>? previousTopRoute) {
if (topRoute.settings.name == '/web') {
debugPrint("设置监听--------");
IosEdgeSwipeDetector.onEdgeSwipe(
() {
WebCubitHolder.instance?.handleBack();
},
);
} else if (previousRoute?.settings.name == '/web') {
// push时,前一个路由是 /web,代表是从web页进入此页面
// 将手势监听回调取消
} else {
debugPrint("取消监听--------");
IosEdgeSwipeDetector.dispose();
}
}
}
///
/// 监控 /link 路由,作相应处理
///
class LinkPageObserver extends NavigatorObserver {
@override
void didPop(Route route, Route? previousRoute) {
super.didPop(route, previousRoute);
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
if (previousRoute?.settings.name == '/web') {
// Pop时, 前一个路由是/web,代表回到web页面
// 设置手势监听回调
debugPrint("设置监听--------");
IosEdgeSwipeDetector.onEdgeSwipe(
() {
WebCubitHolder.instance?.handleBack();
},
);
if (route.settings.name == '/link' && previousRoute?.settings.name == '/web') {
debugPrint('---didPush--- route: ${route.settings.name}, previousRoute ${previousRoute?.settings.name}');
debugPrint('设置 WebStatus 为 2');
WebCubitHolder.instance?.handleWebStatus(2);
// 在 push 时就设置 pop 返回值的监听
route.popped.then((result) {
debugPrint('-------------路由 ${route.settings.name} 被 pop,返回值: $result');
debugPrint('设置 WebStatus 为 1');
WebCubitHolder.instance?.handleWebStatus(1, extData: result ?? '');
});
}
}
@override
void didRemove(Route route, Route? previousRoute) {
super.didRemove(route, previousRoute);
if (route.settings.name == '/web') {
// remove时, 当前路由为 /web, 代表 /web 路由被删除,展示的不是web页面
// 将手势监听回调取消
debugPrint("取消监听--------");
IosEdgeSwipeDetector.dispose();
void didPop(Route route, Route? previousRoute) {
if (previousRoute?.settings.name == '/web' && route.settings.name == '/link') {
debugPrint('---didPop--- route: ${route.settings.name}, previousRoute: ${previousRoute?.settings.name}');
}
}
}
......
......@@ -3,7 +3,7 @@ import 'package:appframe/services/dispatcher.dart';
class OpenLinkHandler extends MessageHandler {
@override
Future<bool> handleMessage(params) async {
Future<dynamic> handleMessage(params) async {
if (params is! Map<String, dynamic>) {
throw Exception('参数错误');
}
......@@ -12,12 +12,10 @@ class OpenLinkHandler extends MessageHandler {
if (url.isEmpty) {
throw Exception('参数错误');
}
int screenType = params['screenType'] ?? 1;
return _openLink(url);
}
router.push('/link', extra: {'url': url, 'screenType': screenType});
bool _openLink(String url) {
router.push('/link', extra: {'url': url});
return true;
}
}
import 'package:appframe/services/dispatcher.dart';
import 'package:flutter/services.dart' hide MessageHandler;
class ScreenHandler extends MessageHandler {
@override
Future<dynamic> handleMessage(dynamic params) async {
if (params is! Map<String, dynamic>) {
throw Exception('参数错误');
}
int type = params['type'];
_setOrientation(type);
return true;
}
void _setOrientation(int screenType) {
if (screenType == 2) {
// 横屏模式
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
} else {
// 竖屏模式(默认)
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
}
}
......@@ -55,7 +55,8 @@ class MessageDispatcher {
h5Message.cmd == "chooseVideo" ||
h5Message.cmd == "goLogin" ||
h5Message.cmd.startsWith("setTitlebar") ||
h5Message.cmd == "audioPlay") {
h5Message.cmd == "audioPlay" ||
h5Message.cmd == "openLink") {
handler.setCubit(webCubit!);
handler.setMessage(message);
}
......
......@@ -12,11 +12,12 @@ class LinkPage extends StatelessWidget {
@override
Widget build(BuildContext buildContext) {
final Map<String, dynamic>? extraData = GoRouterState.of(buildContext).extra as Map<String, dynamic>?;
final String? url = extraData?['url'];
final String url = extraData?['url'];
final String? title = extraData?['title'];
final int screenType = extraData?['screenType'] ?? 1; // 1: 竖屏, 2: 横屏
return BlocProvider(
create: (context) => LinkCubit(LinkState(loaded: false, url: url!, title: title ?? '')),
create: (context) => LinkCubit(LinkState(url: url, title: title ?? '', screenType: screenType)),
child: BlocConsumer<LinkCubit, LinkState>(
builder: (ctx, state) {
final scaffold = Scaffold(
......@@ -25,6 +26,12 @@ class LinkPage extends StatelessWidget {
centerTitle: true,
backgroundColor: Color(0xFF7691FA),
iconTheme: IconThemeData(color: Colors.white),
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
ctx.read<LinkCubit>().handleBack();
},
),
),
body: state.loaded
? SizedBox(
......@@ -46,7 +53,7 @@ class LinkPage extends StatelessWidget {
if (didPop) {
return;
}
ctx.read<LinkCubit>().handleBack(ctx);
ctx.read<LinkCubit>().handleBack();
},
child: scaffold,
);
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!