434 lines
14 KiB
Dart
434 lines
14 KiB
Dart
import 'dart:async';
|
||
import 'dart:io';
|
||
|
||
import 'package:cargame/tools/shop/shop_page.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||
|
||
import '../beans/game_token_bean.dart';
|
||
import '../beans/queue_bean.dart';
|
||
import '../beans/reconnect_bean.dart';
|
||
import '../common/EventBusUtil.dart';
|
||
import '../common/Global.dart';
|
||
import '../common/func.dart';
|
||
import '../dialog/line_up_dialog.dart';
|
||
import '../dialog/reconnect_dialog.dart';
|
||
import '../network/NetworkConfig.dart';
|
||
import 'game/game_page.dart';
|
||
import 'home/my_home_page.dart';
|
||
import 'home_model.dart';
|
||
import 'me/my_page.dart';
|
||
|
||
class HomePage extends StatefulWidget {
|
||
const HomePage({super.key});
|
||
|
||
@override
|
||
State<HomePage> createState() => _HomePageState();
|
||
}
|
||
|
||
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||
final pageController = PageController();
|
||
|
||
GlobalKey<LineUpDialogState> lineUpDialogKey = GlobalKey();
|
||
|
||
List<StatefulWidget> bodyList = [];
|
||
late List<Widget> tabs;
|
||
late TabController _tabController;
|
||
|
||
int currentIndex = 0;
|
||
late StreamSubscription<StartGames> _startGamesEvent;
|
||
late StreamSubscription<TabSwitch> _tabSwitchEvent;
|
||
late StreamSubscription<RefreshUserdata> _refreshUserEvent;
|
||
|
||
late StreamSubscription subscription;
|
||
final HomeModel _viewModel = HomeModel();
|
||
late Timer _timer;
|
||
|
||
// late BuildContext lineUpContext;
|
||
|
||
late ReconnectBean reconnectBean;
|
||
bool isLineUp = false;
|
||
|
||
DateTime? _lastPressTime;
|
||
int unreadNum = 0;
|
||
|
||
late OverlayEntry entry;
|
||
|
||
@override
|
||
void initState() {
|
||
// TODO: implement initState
|
||
super.initState();
|
||
|
||
tabs = [
|
||
Text("主页"),
|
||
Text("游戏"),
|
||
Text("商城"),
|
||
Text("我的"),
|
||
];
|
||
|
||
bodyList = [MyHomePage(), GamePage(), ShopPage(), MyPage()];
|
||
_tabController = TabController(initialIndex: 0, length: tabs.length, vsync: this);
|
||
|
||
///eventBus
|
||
///启动游戏
|
||
_startGamesEvent = EventBusUtil.listen((event) {
|
||
if (NetworkConfig.token == "") {
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
|
||
final DateTime now = DateTime.now();
|
||
if (_lastPressTime != null && now.difference(_lastPressTime!) < Duration(seconds: 2)) {
|
||
// 两次点击时间间隔小于2秒,拦截第二次点击
|
||
print('Button pressed again within 2 seconds. Ignoring the second press.');
|
||
return;
|
||
}
|
||
// 更新最后一次点击时间
|
||
setState(() {
|
||
_lastPressTime = now;
|
||
});
|
||
|
||
FunctionUtil.loading();
|
||
NetworkConfig.gameId = event.gameId;
|
||
print("_startGamesEvent");
|
||
_viewModel.playGame(event.gameId);
|
||
});
|
||
|
||
///tab切换
|
||
_tabSwitchEvent = EventBusUtil.listen((event) {
|
||
if (NetworkConfig.token == "") {
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
setState(() {
|
||
currentIndex = event.index;
|
||
});
|
||
pageController.jumpToPage(event.index);
|
||
});
|
||
|
||
///刷新用户信息
|
||
_refreshUserEvent = EventBusUtil.listen((event) {
|
||
_viewModel.getUserInfo();
|
||
});
|
||
|
||
subscription = _viewModel.streamController.stream.listen((event) {
|
||
String code = event['code'];
|
||
if (code.isNotEmpty) {
|
||
switch (code) {
|
||
case "getToken":
|
||
GameTokenBean gameTokenBean = event['data'];
|
||
Map<String, dynamic> gameMap = {
|
||
"gameToken": gameTokenBean.token,
|
||
"BsUrl": NetworkConfig.configBean?.bsUrl,
|
||
"channelId": NetworkConfig.configBean?.channelId,
|
||
"userToken": NetworkConfig.token,
|
||
"signKey": NetworkConfig.signKey,
|
||
"Channel": NetworkConfig.Channel,
|
||
"Version": NetworkConfig.Version,
|
||
"Url": NetworkConfig.ServerDomain_Online,
|
||
};
|
||
|
||
///传值初始化游戏token
|
||
invokeNativeMethod("initData", gameMap);
|
||
_viewModel.getMyScList();
|
||
break;
|
||
|
||
///启动游戏
|
||
case "playGame":
|
||
isLineUp = false;
|
||
EasyLoading.dismiss();
|
||
Map<String, dynamic> gameMap = {
|
||
"gameId": event['gameId'],
|
||
"playGameData": "${event['data']}",
|
||
"isReconPlay": "false",
|
||
};
|
||
invokeNativeMethod("playGame", gameMap);
|
||
break;
|
||
|
||
///游戏错误
|
||
case "gameError":
|
||
EasyLoading.showToast("${event['data']}");
|
||
_viewModel.cancelQueue(event['gameId']);
|
||
break;
|
||
|
||
///线路不足游戏开始排队
|
||
case "gameQueue":
|
||
EasyLoading.dismiss();
|
||
QueueBean queueBean = event['data'];
|
||
String gameId = event['gameId'];
|
||
|
||
if (!isLineUp) {
|
||
final overlay = Overlay.of(context);
|
||
entry = OverlayEntry(builder: (BuildContext context) {
|
||
return LineUpDialog(
|
||
lineUpDialogKey,
|
||
num: queueBean.queue_pos!,
|
||
onTap: () {
|
||
entry.remove();
|
||
_timer.cancel();
|
||
_viewModel.cancelQueue(gameId);
|
||
},
|
||
);
|
||
});
|
||
overlay.insert(entry);
|
||
// showDialog(
|
||
// context: context,
|
||
// barrierDismissible: false,
|
||
// builder: (BuildContext context) {
|
||
// lineUpContext = context;
|
||
// return LineUpDialog(
|
||
// lineUpDialogKey,
|
||
// num: queueBean.queue_pos!,
|
||
// onTap: () {
|
||
// _timer.cancel();
|
||
// _viewModel.cancelQueue(gameId);
|
||
// },
|
||
// );
|
||
// });
|
||
isLineUp = true;
|
||
}
|
||
|
||
//调用排队
|
||
_timer = Timer.periodic(const Duration(milliseconds: 5000), (as) {
|
||
print("playGameQueue");
|
||
_viewModel.playGameQueue(NetworkConfig.gameId);
|
||
});
|
||
break;
|
||
|
||
///游戏排队队列
|
||
case "playGameQueue":
|
||
QueueBean queueBean = event['data'];
|
||
lineUpDialogKey.currentState?.setNum(queueBean.queue_pos);
|
||
break;
|
||
|
||
///取消排队
|
||
case "cancelQueue":
|
||
isLineUp = false;
|
||
lineUpDialogKey.currentState?.setNum(0);
|
||
_timer.cancel();
|
||
break;
|
||
|
||
///排队成功 开始游戏
|
||
case "gameQueueSuccess":
|
||
print("gameQueueSuccess");
|
||
entry.remove();
|
||
// Navigator.pop(lineUpContext);
|
||
_timer.cancel();
|
||
_viewModel.playGame(NetworkConfig.gameId);
|
||
break;
|
||
|
||
///可重连游戏
|
||
case "getMyScList":
|
||
reconnectBean = event['data'];
|
||
|
||
///重连弹窗
|
||
FunctionUtil.popDialog2(
|
||
context,
|
||
ReconnectDialog(
|
||
reconnectBean: reconnectBean,
|
||
onTap: (gameId, type) {
|
||
if (type == 1) {
|
||
FunctionUtil.loading();
|
||
_viewModel.reconPlayGame(gameId);
|
||
} else {
|
||
_viewModel.exitPlayGame(gameId);
|
||
}
|
||
},
|
||
));
|
||
break;
|
||
|
||
///重连游戏
|
||
case "reconPlayGame":
|
||
EasyLoading.dismiss();
|
||
Map<String, dynamic> gameMap = {
|
||
"gameId": event['gameId'],
|
||
"playGameData": "${event['data']}",
|
||
"isReconPlay": "true",
|
||
};
|
||
invokeNativeMethod("playGame", gameMap);
|
||
break;
|
||
|
||
case "reconPlayGameError":
|
||
EasyLoading.showToast(event['data']);
|
||
break;
|
||
|
||
case "getUserMessageNotReadCount": //是否有新消息
|
||
unreadNum = event['data'];
|
||
setState(() {});
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
_viewModel.getToken();
|
||
if (NetworkConfig.token != "") {
|
||
_viewModel.getUserMessageNotReadCount();
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
// TODO: implement dispose
|
||
super.dispose();
|
||
_startGamesEvent.cancel();
|
||
_tabSwitchEvent.cancel();
|
||
_timer.cancel();
|
||
_refreshUserEvent.cancel();
|
||
subscription.cancel();
|
||
}
|
||
|
||
void onPageChanged(int index) {
|
||
// streamSink.add(index);
|
||
if (NetworkConfig.token == "") {
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
setState(() {
|
||
currentIndex = index;
|
||
});
|
||
pageController.jumpToPage(index);
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final size = MediaQuery.of(context).size;
|
||
final l11 = size.width / 32.727272727272;
|
||
final l13 = size.width / 26.666666666666; //13.5
|
||
final w1 = size.width / 360;
|
||
final s7 = size.width / 51.428571428571;
|
||
final c10 = size.width / 36;
|
||
final b5 = size.width / 72;
|
||
final c2 = size.width / 180;
|
||
|
||
return WillPopScope(
|
||
onWillPop: doubleClickBack,
|
||
child: Scaffold(
|
||
backgroundColor: Color(0xFF17181A),
|
||
body: Stack(
|
||
children: [
|
||
PageView(
|
||
controller: pageController,
|
||
// onPageChanged: onPageChanged,
|
||
children: bodyList,
|
||
physics: NeverScrollableScrollPhysics(), // 禁止滑动
|
||
),
|
||
Container(
|
||
color: Color(0xFF17181A),
|
||
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + c10, bottom: b5),
|
||
// height: h12,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
///搜索
|
||
GestureDetector(
|
||
onTap: () {
|
||
if (NetworkConfig.token == "") {
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
Navigator.pushNamed(context, "/SearchPage");
|
||
},
|
||
child: Container(
|
||
margin: EdgeInsets.only(left: l11),
|
||
child: Image(width: l11, height: l11, image: AssetImage('assets/images/ic_search.png')),
|
||
),
|
||
),
|
||
|
||
///tab
|
||
TabBar(
|
||
tabs: tabs,
|
||
controller: _tabController,
|
||
labelPadding: EdgeInsets.symmetric(horizontal: l13),
|
||
indicator: UnderlineTabIndicator(
|
||
insets: EdgeInsets.symmetric(horizontal: w1),
|
||
borderSide: BorderSide(color: const Color(0xFF0978FF), width: w1),
|
||
borderRadius: BorderRadius.circular(c10),
|
||
),
|
||
dividerHeight: 0,
|
||
tabAlignment: TabAlignment.start,
|
||
//设置未选中时的字体颜色,tabs里面的字体样式优先级最高
|
||
unselectedLabelColor: Color(0xFF8F8F8F),
|
||
//设置未选中时的字体样式,tabs里面的字体样式优先级最高
|
||
unselectedLabelStyle: TextStyle(fontSize: s7, fontWeight: FontWeight.w700),
|
||
//设置选中时的字体颜色,tabs里面的字体样式优先级最高
|
||
labelColor: Color(0xFF0978FF),
|
||
//设置选中时的字体样式,tabs里面的字体样式优先级最高
|
||
labelStyle: TextStyle(fontSize: s7, fontWeight: FontWeight.w700),
|
||
isScrollable: true,
|
||
onTap: (int index) {
|
||
if (NetworkConfig.token == "" && index > 0) {
|
||
_tabController.animateTo(0);
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
setState(() {
|
||
currentIndex = index;
|
||
});
|
||
pageController.jumpToPage(index);
|
||
},
|
||
),
|
||
|
||
///消息
|
||
GestureDetector(
|
||
onTap: () {
|
||
if (NetworkConfig.token == "") {
|
||
Navigator.pushNamed(context, "/LoginPage");
|
||
return;
|
||
}
|
||
Navigator.pushNamed(context, "/MessageCenterPage").then((value) {
|
||
_viewModel.getUserMessageNotReadCount();
|
||
});
|
||
},
|
||
child: Container(
|
||
margin: EdgeInsets.only(right: l11),
|
||
child: Stack(
|
||
children: [
|
||
Image(width: l11, height: l11, image: AssetImage('assets/images/ic_message.png')),
|
||
Positioned(
|
||
top: c2,
|
||
right: c2,
|
||
child: unreadNum > 0
|
||
? Container(
|
||
width: c2,
|
||
height: c2,
|
||
decoration: const BoxDecoration(color: Colors.red, borderRadius: BorderRadius.all(Radius.circular(10))),
|
||
)
|
||
: Container())
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
)
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
int last = 0;
|
||
|
||
Future<bool> doubleClickBack() async {
|
||
int now = DateTime.now().millisecondsSinceEpoch;
|
||
|
||
if (now - last > 2500) {
|
||
last = DateTime.now().millisecondsSinceEpoch;
|
||
EasyLoading.showToast("再按一次退出");
|
||
return Future.value(false);
|
||
} else {
|
||
_viewModel.exitApp();
|
||
SystemNavigator.pop();
|
||
exit(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取原生的值
|
||
invokeNativeMethod(String method, Map<String, dynamic> map) async {
|
||
dynamic args;
|
||
try {
|
||
args = await Global.method.invokeMethod(method, map);
|
||
} on PlatformException catch (e) {}
|
||
}
|