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

417 lines
14 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.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/app_localizations.dart';
import 'package:aslan/chatvibe_ui/components/dialog/dialog_base.dart';
import 'package:aslan/chatvibe_data/sources/repositories/room_repository_imp.dart';
import 'package:aslan/chatvibe_domain/models/res/at_get_game_config_data.dart';
import 'package:aslan/chatvibe_managers/rtc_manager.dart';
import 'package:aslan/chatvibe_features/wallet/wallet_route.dart';
import '../../chatvibe_data/models/enum/at_game_mode_type.dart';
class GameBsWebviewPage extends StatefulWidget {
final String url;
///安全高度
final double height;
final double width;
final String gameMode;
final String gameId;
const GameBsWebviewPage({
Key? key,
required this.url,
required this.height,
required this.width,
this.gameMode = "",
this.gameId = "",
}) : super(key: key);
@override
_GameBsWebviewPageState createState() => _GameBsWebviewPageState();
}
class _GameBsWebviewPageState extends State<GameBsWebviewPage> {
late WebViewController _controller;
double _progress = 0.0;
bool _isLoading = true;
final EventChannel _eventChannelPlugin = EventChannel('baishunChannel');
@override
void initState() {
super.initState();
Provider.of<RtcProvider>(context, listen: false).closeFullGame = false;
// 初始化 WebViewController
_controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
"baishunChannel",
onMessageReceived: (sjMessage) {},
)
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
setState(() {
_progress = progress / 100.0;
});
},
onPageStarted: (String url) {
setState(() {
_isLoading = true;
});
},
onPageFinished: (String url) {
_injectJavaScriptInterface();
},
onWebResourceError: (WebResourceError error) {
_onWebResourceError(error);
},
),
)
..loadRequest(Uri.parse(widget.url));
bindChannel();
_uploadGameRecord();
}
@override
void dispose() {
_controller.loadRequest(Uri.parse('about:blank'));
super.dispose();
}
void _injectJavaScriptInterface() async {}
@override
Widget build(BuildContext context) {
return widget.height < 0
? SizedBox(
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
child: buidMainContent(),
)
: Column(
children: [
widget.gameMode == ATGameModeType.CHAT_ROOM.name
? Container()
: 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(),
resizeToAvoidBottomInset: false,
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
.getWebViewPageProgressBarActiveColor(),
),
),
),
],
),
),
);
}
Widget _progressBar(double progress, BuildContext context) {
return progress < 1.0
? LinearProgressIndicator(
value: progress,
backgroundColor:
ATGlobalConfig.businessLogicStrategy
.getGameWebViewProgressBarBackgroundColor(),
minHeight: 1.0,
valueColor: AlwaysStoppedAnimation<Color>(
ATGlobalConfig.businessLogicStrategy
.getWebViewPageProgressBarActiveColor(),
),
)
: const SizedBox.shrink();
}
void _onWebResourceError(WebResourceError error) {
print('_onWebResourceError:${error.description}');
setState(() {
_isLoading = false;
});
// 可以在这里添加错误处理逻辑,比如显示错误页面
}
void bindChannel() {
if (Platform.isAndroid) {
_eventChannelPlugin.receiveBroadcastStream().listen((event) {
final obj = json.decode(event);
String jsFunName = obj['jsCallback'];
if (jsFunName.contains('getConfig')) {
print("BSGAME游戏调⽤getConfig main.dart");
ATGetGameConfigData _configData = ATGetGameConfigData(
appChannel: ATGlobalConfig.gameAppChannel,
appId: ATGlobalConfig.gameAppid,
userId: AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
gameMode:
widget.height < 0
? "3"
: (widget.gameMode == ATGameModeType.CHAT_ROOM.name
? "3"
: "2"),
language: ATGlobalConfig.lang == "ar" ? "7" : "2",
gsp: 101,
roomId:
Provider.of<RtcProvider>(
context,
listen: false,
).currenRoom?.roomProfile?.roomProfile?.id ??
"",
gameRoomId: "",
code: AccountStorage().getToken(),
role:
Provider.of<RtcProvider>(context, listen: false).isFz()
? "2"
: "0",
gameConfig: GameConfig(
sceneMode: 0,
currencyIcon:
"https://tkm-atu.oss-ap-southeast-1.aliyuncs.com/avatar/b1bc4425-0037-433b-bf00-6977620ff57e.png",
),
);
String jsUrl = jsFunName + "(${jsonEncode(_configData.toJson())})";
_controller!.runJavaScript(jsUrl);
} else if (jsFunName.contains('destroy')) {
print("BSGAME游戏调⽤destroy main.dart");
//关闭游戏TODO客⼾端
_controller.loadRequest(Uri.parse('about:blank'));
if (widget.gameMode == ATGameModeType.CHAT_ROOM) {
Provider.of<RtcProvider>(
context,
listen: false,
).roomMannyGameClose();
} else {
Navigator.of(context).pop();
}
super.dispose();
} else if (jsFunName.contains('gameRecharge')) {
print("BSGAME游戏调⽤gameRecharge main.dart");
//拉起⽀付商城TODO客⼾端
_showGameRecharge();
} else if (jsFunName.contains('gameLoaded')) {
print("BSGAME游戏调⽤gameLoaded main.dart");
setState(() {
_isLoading = false;
});
//游戏加载完毕TODO客⼾端
} else if (jsFunName.contains('sendGameAction')) {
print("BSGAME游戏调⽤sendGameAction main.dart--${obj}");
String str = sendGameActionUtil(obj);
if (str.isNotEmpty) {
_controller.runJavaScript(str);
}
}
});
} else {
_controller.addJavaScriptChannel(
"getConfig",
onMessageReceived: (JavaScriptMessage jsonMessage) {
print("BSGAME 游戏调⽤getConfig main.dart ios");
final obj = json.decode(jsonMessage.message);
String jsFunName = obj['jsCallback'];
ATGetGameConfigData _configData = ATGetGameConfigData(
appChannel: ATGlobalConfig.gameAppChannel,
appId: ATGlobalConfig.gameAppid,
userId: AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
gameMode: widget.height < 0 ? "3" : "2",
language: ATGlobalConfig.lang == "ar" ? "7" : "2",
gsp: 101,
roomId:
Provider.of<RtcProvider>(
context,
listen: false,
).currenRoom?.roomProfile?.roomProfile?.id ??
"",
code: AccountStorage().getToken(),
gameConfig: GameConfig(
sceneMode: 0,
currencyIcon:
"https://tkm-atu.oss-ap-southeast-1.aliyuncs.com/avatar/b1bc4425-0037-433b-bf00-6977620ff57e.png",
),
);
String jsUrl = jsFunName + "(${jsonEncode(_configData.toJson())})";
_controller!.runJavaScript(jsUrl);
},
);
_controller.addJavaScriptChannel(
"destroy",
onMessageReceived: (JavaScriptMessage message) {
print("BSGAME 游戏调⽤destroy main.dart ios");
_controller.loadRequest(Uri.parse('about:blank'));
if (widget.gameMode == ATGameModeType.CHAT_ROOM) {
Provider.of<RtcProvider>(
context,
listen: false,
).roomMannyGameClose();
} else {
Navigator.of(context).pop();
}
super.dispose();
},
);
_controller.addJavaScriptChannel(
"gameRecharge",
onMessageReceived: (JavaScriptMessage message) {
print("BSGAME 游戏调⽤gameRecharge main.dart ios");
_showGameRecharge();
},
);
_controller.addJavaScriptChannel(
"gameLoaded",
onMessageReceived: (JavaScriptMessage message) {
setState(() {
_isLoading = false;
});
print("BSGAME 游戏调⽤gameLoaded main.dart ios");
},
);
_controller.addJavaScriptChannel(
"sendGameAction",
onMessageReceived: (JavaScriptMessage message) {
String str = sendGameActionUtil(message.message);
if (str.isNotEmpty) {
_controller.runJavaScript(str);
}
},
);
}
}
void _showGameRecharge() {
SmartDialog.dismiss(tag: "showConfirmDialog");
SmartDialog.show(
tag: "showConfirmDialog",
alignment: Alignment.center,
animationType: SmartAnimationType.fade,
builder: (_) {
return MsgDialog(
title: ATAppLocalizations.of(context)!.tips,
msg: ATAppLocalizations.of(context)!.balanceNotEnough,
btnText: ATAppLocalizations.of(context)!.confirm,
onEnsure: () {
SmartDialog.dismiss(tag: "showConfirmDialog");
ATNavigatorUtils.push(
context,
WalletRoute.recharge,
replace: false,
);
},
);
},
);
}
String sendGameActionUtil(message) {
String result = '';
int type = message['type'];
Map<String, dynamic> params = message['params'];
switch (type) {
case 13: //游戏开始
break;
case 14: //游戏结束
break;
case 15: //上下座
int optType = params['optType']; //0 上座,1 下座
String userId = params['userId']; //用户 id
int seat = params['seat']; ////座位位置
//如果不鉴权就直接把下面的消息返回
final Map<String, dynamic> map = {};
map["optType"] = optType;
map["userId"] = userId;
map["seat"] = seat;
final Map<String, dynamic> parentMap = {};
parentMap["type"] = 4; // 使用下标操作符添加数据
parentMap["params"] = map;
result = "gameActionUpdate(${json.encode(parentMap)})";
break;
case 17: //踢人
String userId = params['userId'];
int seat = params['seat'];
//如果不鉴权就直接把下面的消息返回
final Map<String, dynamic> map = {};
map["optResult"] = 0;
map["optUserId"] = AccountStorage().getCurrentUser()?.userProfile?.id;
map["userId"] = userId;
map["reason"] = seat;
final Map<String, dynamic> parentMap = {};
parentMap["type"] = 6; // 使用下标操作符添加数据
parentMap["params"] = map;
result = "gameActionUpdate(${json.encode(parentMap)})";
break;
}
return result;
}
void _uploadGameRecord() {
ChatRoomRepository().ludoHistoryRecord(
widget.gameId,
widget.height > 0 ? "IN_ROOM" : "OUT_ROOM",
);
}
}