Commit f9f42622 by tanghuan

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

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