aslan-flutter/lib/chatvibe_features/webview/game_ry_webview_page.dart
2026-07-01 18:25:58 +08:00

229 lines
6.6 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:provider/provider.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_data/sources/repositories/room_repository_imp.dart';
import 'package:aslan/chatvibe_managers/rtc_manager.dart';
import 'package:aslan/chatvibe_features/wallet/wallet_route.dart';
import 'package:aslan/chatvibe_features/webview/bridge/at_js_bridge.dart';
class GameRyWebviewPage extends StatefulWidget {
final String url;
///安全高度
final double height;
final double width;
final String gameId;
const GameRyWebviewPage({
Key? key,
required this.url,
required this.height,
required this.width,
this.gameId = "",
}) : super(key: key);
@override
_GameRyWebviewPageState createState() => _GameRyWebviewPageState();
}
class _GameRyWebviewPageState extends State<GameRyWebviewPage> {
late WebViewController _controller;
bool _isLoading = true;
String gameLink = "";
String gameUrl = "";
late final ATJSBridge _bridge;
@override
void initState() {
super.initState();
Provider.of<RtcProvider>(context, listen: false).closeFullGame = false;
_bridge = ATJSBridge();
if (widget.url.split("?").length > 1) {
gameLink = "${widget.url}&";
} else {
gameLink = "${widget.url}?";
}
gameUrl =
"${gameLink}sdk=atu&uid=${AccountStorage().getCurrentUser()?.userProfile?.id}&token=${AccountStorage().token}&lang=${ATGlobalConfig.lang}";
_initializeWebViewController();
_bridge.initialize(_controller);
_uploadGameRecord();
}
@override
void dispose() {
_controller.loadRequest(Uri.parse('about:blank'));
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.height < 0
? SizedBox(
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
child: buidMainContent(),
)
: Column(
children: [
Row(
children: [
Spacer(),
ATDebounceWidget(
child: Icon(Icons.close, color: ATGlobalConfig.businessLogicStrategy.getGameWebViewCloseIconColor(), size: 25.w),
onTap: () {
Navigator.of(context).pop();
},
),
SizedBox(width: 3.w),
],
),
SizedBox(height: 6.w),
AspectRatio(
aspectRatio: (750 / widget.height),
child: buidMainContent(),
),
],
);
}
Widget buidMainContent() {
return Scaffold(
backgroundColor: ATGlobalConfig.businessLogicStrategy.getGameWebViewScaffoldBackgroundColor(),
body: SafeArea(
top: false,
child: Stack(
children: [
Selector<RtcProvider, bool>(
selector: (c, p) => p.closeFullGame,
shouldRebuild: (prev, next) => prev != next,
builder: (_, closeFullGame, __) {
if (closeFullGame) {
Navigator.of(context).removeRoute(ModalRoute.of(context)!);
}
return Container();
},
),
WebViewWidget(controller: _controller),
// 加载指示器
if (_isLoading)
Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(ATGlobalConfig.businessLogicStrategy.getGameWebViewLoadingIndicatorColor()),
),
),
],
),
),
);
}
void _onWebResourceError(WebResourceError error) {
print('_onWebResourceError:${error.description}');
// 可以在这里添加错误处理逻辑,比如显示错误页面
}
void _initializeWebViewController() {
_controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() => _isLoading = true);
},
onPageFinished: (url) {
setState(() => _isLoading = false);
_injectBridgeScript();
},
onWebResourceError: (error) {
print('Web资源错误: ${error.description}');
_onWebResourceError(error);
},
),
)
..addJavaScriptChannel(
'ATJSBridge',
onMessageReceived: (JavaScriptMessage message) {
_bridge.handleMessage(message.message);
},
);
_bridge.initialize(_controller);
// 注册quit和recharge方法
_registerHandlers();
// 加载URL
_controller.loadRequest(Uri.parse(gameUrl));
}
void _registerHandlers() {
// 注册quit方法
_bridge.registerHandler('quit', (data) async {
Navigator.of(context).pop();
});
// 注册recharge方法
_bridge.registerHandler('recharge', (data) async {
ATNavigatorUtils.push(context, WalletRoute.recharge, replace: false);
});
}
void _injectBridgeScript() {
_controller.runJavaScript('''
// 确保window.quit是一个对象并有postMessage方法
window.quit = window.quit || {};
window.quit.postMessage = function(message) {
// 构造发送给Flutter的消息
const payload = {
type: 'call',
handlerName: 'quit',
data: message,
callId: 'web_' + Date.now()
};
// 通过JavaScriptChannel发送消息
if (window.JSBridge) {
window.JSBridge.postMessage(JSON.stringify(payload));
}
};
window.recharge = window.recharge || {};
window.recharge.postMessage = function(message) {
// 构造发送给Flutter的消息
const payload = {
type: 'call',
handlerName: 'recharge',
data: message,
callId: 'web_' + Date.now()
};
// 通过JavaScriptChannel发送消息
if (window.JSBridge) {
window.JSBridge.postMessage(JSON.stringify(payload));
}
};
console.log('Flutter JS Bridge 初始化完成 - 支持window.quit.postMessage');
''');
}
void _uploadGameRecord() {
ChatRoomRepository().ludoHistoryRecord(
widget.gameId,
widget.height > 0 ? "IN_ROOM" : "OUT_ROOM",
);
}
}