import 'dart:convert'; 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'; class GameYmWebviewPage extends StatefulWidget { final String url; ///安全高度 final double height; final double width; final String gameId; const GameYmWebviewPage({ Key? key, required this.url, required this.height, required this.width, this.gameId = "", }) : super(key: key); @override _GameYmWebviewPageState createState() => _GameYmWebviewPageState(); } class _GameYmWebviewPageState extends State { late WebViewController _controller; bool _isLoading = true; String gameLink = ""; String gameUrl = ""; @override void initState() { super.initState(); Provider.of(context, listen: false).closeFullGame = false; if (widget.url.split("?").length > 1) { gameLink = "${widget.url}&"; } else { gameLink = "${widget.url}?"; } gameUrl = "${gameLink}platUserId=${AccountStorage().getCurrentUser()?.userProfile?.id}&platAuthCode=${AccountStorage().token}&lang=${ATGlobalConfig.lang}&time=${DateTime.now().millisecondsSinceEpoch}"; _initializeWebViewController(); _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( 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(ATGlobalConfig.businessLogicStrategy.getGameWebViewLoadingIndicatorColor()), ), ), ], ), ), ); } void _onWebResourceError(WebResourceError error) { print('_onWebResourceError:${error.description}'); // 可以在这里添加错误处理逻辑,比如显示错误页面 } void _initializeWebViewController() { _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..loadRequest(Uri.parse(gameUrl)) // 游戏网址 ..addJavaScriptChannel( 'yomi', onMessageReceived: (message) { var json = jsonDecode(message.message); String type = json["type"] ?? ""; if (type == 'closeGame') { Navigator.of(context).pop(); }else if (type == 'hideSplash') { } else if (type == 'insufficient') { ATNavigatorUtils.push( context, WalletRoute.recharge, replace: false, ); } }, ) ..setNavigationDelegate( NavigationDelegate( onPageFinished: (url) { setState(() { _isLoading = false; }); }, onWebResourceError: (WebResourceError error) { _onWebResourceError(error); }, ), ); } /// 调用游戏币更新 void updateCoin() { _controller.runJavaScript('updateCoin();'); } void _uploadGameRecord() { ChatRoomRepository().ludoHistoryRecord( widget.gameId, widget.height > 0 ? "IN_ROOM" : "OUT_ROOM", ); } }