Hibok
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

263 rader
7.9 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:chat/data/UserData.dart';
  4. import 'package:chat/data/constants.dart';
  5. import 'package:chat/data/group_data_mgr.dart';
  6. import 'package:chat/generated/i18n.dart';
  7. import 'package:chat/home/qr_scanner_overlay.dart';
  8. import 'package:chat/utils/CustomUI.dart';
  9. import 'package:chat/utils/LoadingDialog.dart';
  10. import 'package:chat/utils/MessageMgr.dart';
  11. import 'package:chat/utils/app_navigator.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:flutter_qr_reader/flutter_qr_reader.dart';
  14. import 'package:flutter_qr_reader/qrcode_reader_view.dart';
  15. import 'package:image_picker/image_picker.dart';
  16. import 'package:oktoast/oktoast.dart';
  17. import 'package:url_launcher/url_launcher.dart';
  18. import 'join_group_confirm.dart';
  19. class QrScannerPage extends StatefulWidget {
  20. @override
  21. _QrScannerPageState createState() => _QrScannerPageState();
  22. }
  23. class _QrScannerPageState extends State<QrScannerPage>
  24. with SingleTickerProviderStateMixin {
  25. String scanImgPath;
  26. GlobalKey<QrcodeReaderViewState> qrViewKey = GlobalKey();
  27. AnimationController _animationController;
  28. Animation _animation;
  29. QrReaderViewController qrReaderViewController;
  30. @override
  31. void initState() {
  32. super.initState();
  33. _animationController = new AnimationController(
  34. duration: Duration(milliseconds: 600), vsync: this);
  35. _animation = Tween(begin: 1.0, end: 0.45).animate(_animationController)
  36. ..addListener(() {
  37. //这行如果不写,没有动画效果
  38. setState(() {});
  39. });
  40. _animationController.forward();
  41. }
  42. bool isScan = false;
  43. @override
  44. void dispose() {
  45. qrReaderViewController = null;
  46. super.dispose();
  47. }
  48. @override
  49. Widget build(BuildContext context) {
  50. final Size size = MediaQuery.of(context).size;
  51. final double scanWidth = 250;
  52. final double borderWidth = 5;
  53. final screenRect = Rect.fromLTWH(
  54. size.width / 2 - scanWidth / 2 + borderWidth,
  55. size.height / 2 -
  56. scanWidth / 2 +
  57. borderWidth -
  58. kBottomNavigationBarHeight,
  59. scanWidth - 2 * borderWidth,
  60. scanWidth - 2 * borderWidth,
  61. );
  62. return Scaffold(
  63. appBar: AppBar(
  64. leading: IconButton(
  65. iconSize: 22,
  66. icon: Icon(
  67. Icons.arrow_back_ios,
  68. color: Colors.white,
  69. ),
  70. onPressed: () {
  71. Navigator.of(context).pop();
  72. },
  73. ),
  74. backgroundColor: Colors.black,
  75. title:
  76. Text(I18n.of(context).scan, style: TextStyle(color: Colors.white)),
  77. centerTitle: true,
  78. ),
  79. backgroundColor: Colors.black.withOpacity(_animation.value),
  80. body: ScanImageView(
  81. scanColor: Colors.blueAccent,
  82. scanRect: screenRect,
  83. child: Stack(
  84. alignment: Alignment.center,
  85. children: <Widget>[
  86. scanImgPath == null
  87. ? QrReaderView(
  88. width: size.width,
  89. height: size.height,
  90. callback: (container) {
  91. qrReaderViewController = container;
  92. Future.delayed(Duration(milliseconds: 600), () {
  93. qrReaderViewController.startCamera(onQrBack);
  94. });
  95. },
  96. )
  97. : SizedBox.expand(
  98. child: Image.file(
  99. File(scanImgPath),
  100. fit: BoxFit.contain,
  101. )),
  102. Positioned(
  103. left: 0,
  104. right: 0,
  105. bottom: 0,
  106. child: Container(
  107. color: Colors.black,
  108. padding: EdgeInsets.symmetric(vertical: 10),
  109. child: Row(
  110. mainAxisAlignment: MainAxisAlignment.spaceAround,
  111. children: <Widget>[
  112. _iconButton(
  113. IconData(0xe658,
  114. fontFamily: Constants.IconFontFamily),
  115. I18n.of(context).my_qr, () {
  116. AppNavigator.pushQrPage(context);
  117. }),
  118. _iconButton(
  119. IconData(0xe626,
  120. fontFamily: Constants.IconFontFamily),
  121. I18n.of(context).picture, () async {
  122. if (await CustomUI.showPhotoPermissionSetting(
  123. context)) {
  124. _scanImage();
  125. }
  126. })
  127. ],
  128. ),
  129. ))
  130. ],
  131. )),
  132. );
  133. }
  134. Future _scanImage() async {
  135. stopScan();
  136. print('_scanImage 开始');
  137. var image = await ImagePicker.pickImage(source: ImageSource.gallery);
  138. if (image == null) {
  139. startScan();
  140. return;
  141. }
  142. setState(() {
  143. scanImgPath = image.path;
  144. });
  145. final rest = await FlutterQrReader.imgScan(image);
  146. print('_scanImage $rest');
  147. onScan(rest);
  148. }
  149. void startScan() {
  150. isScan = false;
  151. qrReaderViewController.startCamera(onQrBack);
  152. }
  153. void stopScan() {
  154. qrReaderViewController.stopCamera();
  155. }
  156. onScan(String result) {
  157. if (result == null || result.length == 0) {
  158. return;
  159. }
  160. print('扫描 $result');
  161. stopScan();
  162. Navigator.of(context).pop();
  163. if (result.startsWith('https://henho.jphgames.com/')) {
  164. result = result.replaceFirst('https://henho.jphgames.com/?', '');
  165. result = utf8.decode(base64Decode(result));
  166. result = 'https://henho.jphgames.com/?' + result;
  167. var url = Uri.parse(result);
  168. var type = int.parse(url.queryParameters['type']);
  169. int expirationTime = int.parse(url.queryParameters['expirationTime']);
  170. int curTime = DateTime.now().millisecondsSinceEpoch;
  171. print('过期时间$expirationTime');
  172. if (curTime > expirationTime) {
  173. showToast(I18n.of(context).qr_outtime);
  174. return;
  175. }
  176. if (type == 1) {
  177. var targetId = int.parse(url.queryParameters['sessionId']);
  178. //群二维码
  179. print('群二维码');
  180. GroupInfoMgr().getGroupInfo(targetId, isSave: false).then((groupInfo) {
  181. print('--------------------');
  182. print(groupInfo);
  183. if (groupInfo == null) {
  184. showToast(I18n.of(context).no_goupr_info);
  185. return;
  186. }
  187. Navigator.push(LoadingManage.context,
  188. MaterialPageRoute<void>(builder: (BuildContext context) {
  189. return JoinGroupConfirmPage(
  190. groupInfoModel: groupInfo,
  191. );
  192. }));
  193. });
  194. } else {
  195. //个人二维码
  196. print('个人二维码');
  197. var targetId = int.parse(url.queryParameters['sessionId']);
  198. if (targetId == UserData().basicInfo.userId) {
  199. //我的页面
  200. MessageMgr().emit('Show My Profile');
  201. } else {
  202. AppNavigator.pushProfileInfoPage(context, targetId, addMode: 1);
  203. }
  204. }
  205. } else {
  206. //其他的条码
  207. launch(result);
  208. }
  209. }
  210. onQrBack(String result, List<Offset> points) {
  211. print('扫描结果 $result');
  212. if (isScan == true) return;
  213. isScan = true;
  214. stopScan();
  215. onScan(result);
  216. }
  217. Widget _iconButton(IconData code, String iconName, Function onTap) {
  218. return InkWell(
  219. onTap: onTap,
  220. child: Container(
  221. child: Column(children: <Widget>[
  222. Icon(
  223. code,
  224. size: 30,
  225. color: Colors.white,
  226. ),
  227. SizedBox(height: 5),
  228. Text(
  229. iconName,
  230. style: TextStyle(color: Colors.white),
  231. )
  232. ])));
  233. }
  234. }