RoomInfoNew.dart 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_redux/flutter_redux.dart';
  4. import 'package:shared_preferences/shared_preferences.dart';
  5. import 'package:url_launcher/url_launcher.dart';
  6. import 'package:battery/battery.dart';
  7. import 'package:wanna_battle/model/PlayerInfo.dart';
  8. import 'package:wanna_battle/pages/RoomInfoDetail.dart';
  9. import 'package:wanna_battle/redux/AppState.dart';
  10. import 'package:wanna_battle/styles/totast.dart';
  11. import '../model/HouseInfo.dart';
  12. import '../Constants.dart';
  13. import '../styles/colors.dart';
  14. import '../net/HttpManager.dart';
  15. import '../net/Result.dart';
  16. import '../plugins/ScreenStramPlugin.dart';
  17. import './StartWindow.dart';
  18. import '../widget/Dialog.dart';
  19. import 'CompetitionNotice.dart';
  20. import 'SecondRoomInfo.dart';
  21. class RoomInfo extends StatefulWidget {
  22. final HouseInfo houseInfo;
  23. final PlayerInfo playerInfo;
  24. final bool interrupted;
  25. RoomInfo(this.houseInfo, {Key key, this.playerInfo, this.interrupted = false}) : super(key: key);
  26. @override
  27. State<StatefulWidget> createState() {
  28. return _RoomInfoState();
  29. }
  30. }
  31. class _RoomInfoState extends State<RoomInfo> with SingleTickerProviderStateMixin {
  32. HouseInfo mHouseInfo;
  33. PlayerInfo mPlayerInfo;
  34. TabController tabController;
  35. RoomInfoDetail roomInfoDetail;
  36. int finishedPlayerNum = 0;
  37. Timer timer;
  38. final Key key1 = GlobalKey<RoomInfoDetailState>();
  39. final Key key2 = GlobalKey<SecondPageState>();
  40. @override
  41. void initState() {
  42. super.initState();
  43. mHouseInfo = widget.houseInfo;
  44. mPlayerInfo = widget.playerInfo;
  45. tabController = TabController(
  46. length: 2,
  47. vsync: this,
  48. );
  49. Future.delayed(Duration.zero, () async {
  50. final prefs = await SharedPreferences.getInstance();
  51. bool showed = prefs.getBool('house_' + mHouseInfo.id.toString()) ?? false;
  52. if (!showed) {
  53. prefs.setBool('house_' + mHouseInfo.id.toString(), true);
  54. showNotice(context);
  55. }
  56. refreshData();
  57. });
  58. if (mHouseInfo.statusFlag == HouseStatus.WAIT || mHouseInfo.statusFlag == HouseStatus.START) {
  59. timer = Timer.periodic(Duration(seconds: 1), (timer) async {
  60. refreshData();
  61. });
  62. Future.delayed(Duration.zero, () async {
  63. if (mHouseInfo.statusFlag == HouseStatus.START) {
  64. showFinishDialog();
  65. } else {
  66. final battery = Battery();
  67. final batteryLevel = await battery.batteryLevel;
  68. showCustomDialog(context, (batteryLevel < 50 ? '系统检测到你的电量低于50%' : '') + ' 为了正常上传比赛结果,建议插上电源线保持电量充足', submitText: '知道了');
  69. }
  70. });
  71. }
  72. }
  73. @override
  74. void dispose() {
  75. super.dispose();
  76. tabController.dispose();
  77. if (timer != null) {
  78. timer.cancel();
  79. }
  80. }
  81. @override
  82. Widget build(BuildContext context) {
  83. return WillPopScope(
  84. child: Scaffold(
  85. appBar: AppBar(
  86. title: Container(
  87. child: TabBar(
  88. controller: tabController,
  89. labelColor: PRIMARY_COLOR,
  90. unselectedLabelColor: Color(0xCCFFFFFF),
  91. labelStyle: TextStyle(fontSize: 16.0),
  92. indicatorColor: PRIMARY_COLOR,
  93. indicatorWeight: 3,
  94. indicatorSize: TabBarIndicatorSize.label,
  95. tabs: <Widget>[
  96. Tab(text: '房间信息'),
  97. Tab(text: '参赛成员'),
  98. ],
  99. ),
  100. ),
  101. centerTitle: true,
  102. elevation: 0,
  103. actions: <Widget>[
  104. Container(
  105. padding: EdgeInsets.only(right: 30, left: 20),
  106. )
  107. ],
  108. ),
  109. body: Container(
  110. child: TabBarView(
  111. controller: tabController,
  112. children: [
  113. Builder(
  114. builder: (context) {
  115. roomInfoDetail = RoomInfoDetail(
  116. mHouseInfo,
  117. mPlayerInfo,
  118. onStart: () {
  119. showStart();
  120. },
  121. key: key1,
  122. finishedPlayerNum: finishedPlayerNum,
  123. );
  124. return roomInfoDetail;
  125. },
  126. ),
  127. SecondPage(mHouseInfo, key: key2, playerInfo: mPlayerInfo),
  128. ],
  129. ),
  130. ),
  131. ),
  132. onWillPop: () {
  133. if ((mHouseInfo?.statusFlag ?? 0) == 0) {
  134. showCustomDialog(context, '比赛即将开始,确定离开房间?', isCancel: true, onsubmit: () async {
  135. Toast.show(context, '退出房间', -1, 'loading');
  136. await HttpManager.get('houseInfo/quitRoom', data: {'houseId': mHouseInfo.id});
  137. Toast.hide();
  138. Navigator.of(context).pop();
  139. });
  140. return Future.value(false);
  141. }
  142. return Future.value(true);
  143. },
  144. );
  145. }
  146. Future<void> refreshData() async {
  147. setState(() {});
  148. HttpManager.get('houseInfo/getOne', data: {'id': mHouseInfo.id}).then((res) {
  149. if (res.success) {
  150. if (mHouseInfo.statusFlag == 0 && res.data['statusFlag'] == 2) {
  151. showStart();
  152. }
  153. setState(() {
  154. mHouseInfo = HouseInfo.fromJson(res.data);
  155. });
  156. }
  157. });
  158. HttpManager.get('playerInfo/getOne', data: {
  159. 'userId': StoreProvider.of<AppState>(context).state.userInfo.id,
  160. 'houseId': mHouseInfo.id,
  161. }).then((res) {
  162. if (res.success) {
  163. setState(() {
  164. mPlayerInfo = PlayerInfo.fromJson(res.data);
  165. });
  166. }
  167. });
  168. HttpManager.get('playerInfo/endNum', data: {'houseId': mHouseInfo.id}).then((res) {
  169. if (res.success) {
  170. setState(() {
  171. finishedPlayerNum = res.data;
  172. });
  173. }
  174. });
  175. }
  176. Future<void> showStart() async {
  177. if (mPlayerInfo == null) {
  178. return;
  179. }
  180. final result = await Navigator.of(context).push(
  181. PageRouteBuilder(
  182. opaque: false,
  183. transitionDuration: Duration(milliseconds: 300),
  184. transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
  185. return FadeTransition(
  186. opacity: CurvedAnimation(parent: animation, curve: Curves.linear),
  187. child: child,
  188. );
  189. },
  190. pageBuilder: (BuildContext context, _, __) {
  191. return StartWindow();
  192. },
  193. ),
  194. );
  195. final Map<String, dynamic> data = {'id': mPlayerInfo.id};
  196. bool success = true;
  197. if (result) {
  198. success = await ScreenStreamPlugin.start(mPlayerInfo.id.toString());
  199. if (success) {
  200. data['statusFlag'] = 2;
  201. data['played'] = true;
  202. data['beginTime'] = DateTime.now().millisecondsSinceEpoch;
  203. } else {
  204. data['statusFlag'] = 6;
  205. data['played'] = false;
  206. }
  207. } else {
  208. data['statusFlag'] = 6;
  209. data['played'] = false;
  210. }
  211. final Result res = await HttpManager.post('playerInfo/update', data: data);
  212. if (res.success) {
  213. if (data['statusFlag'] == 2) {
  214. const url = 'pubgmhd1106467070://';
  215. if (await canLaunch(url)) {
  216. Timer(Duration(seconds: 1), () async {
  217. await launch(url);
  218. showFinishDialog();
  219. });
  220. } else {
  221. showCustomDialog(context, '自动启动游戏失败,请手动切换到游戏app开始竞赛', submitText: '知道了');
  222. Timer(Duration(seconds: 10), () {
  223. showFinishDialog();
  224. });
  225. }
  226. } else {
  227. showStartFailDialog(success ? 1 : 0);
  228. }
  229. }
  230. }
  231. void showFinishDialog() {
  232. if (widget.interrupted) {
  233. showCustomDialog(
  234. context,
  235. '您已经完成比赛了吗,确认完成,那就点击下方完成竞赛按钮,上传本次成绩,祝您赢取大奖',
  236. title: '完成比赛',
  237. submitText: '我已完成比赛',
  238. onsubmit: () async {
  239. await HttpManager.post('playerInfo/update', data: {
  240. 'id': mPlayerInfo.id,
  241. 'endTime': DateTime.now().millisecondsSinceEpoch,
  242. 'statusFlag': 9,
  243. });
  244. setState(() {
  245. mPlayerInfo.statusFlag = 3;
  246. });
  247. refreshData();
  248. },
  249. );
  250. } else {
  251. showCustomDialog(
  252. context,
  253. '您已经完成比赛了吗,确认完成,那就点击下方完成竞赛按钮,上传本次成绩,祝您赢取大奖',
  254. title: '完成比赛',
  255. submitText: '我已完成比赛',
  256. onsubmit: () async {
  257. await HttpManager.post('playerInfo/update', data: {'id': mPlayerInfo.id, 'endTime': DateTime.now().millisecondsSinceEpoch});
  258. await ScreenStreamPlugin.stop();
  259. setState(() {
  260. mPlayerInfo.statusFlag = 3;
  261. });
  262. refreshData();
  263. },
  264. );
  265. }
  266. }
  267. void showStartFailDialog(type) {
  268. showCustomDialog(context, (type == 1 ? '由于您未在十秒内点击开始按钮' : '由于您未授权录屏') + ',系统已经判定您放弃比赛,谢谢您的参与。', title: '很遗憾');
  269. }
  270. }