Hibok
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

411 行
12 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'package:chat/chat/gift_select_widget.dart';
  5. import 'package:chat/data/UserData.dart';
  6. import 'package:chat/generated/i18n.dart';
  7. import 'package:chat/home/VipPage.dart';
  8. import 'package:chat/map/google_map_location_picker.dart';
  9. import 'package:chat/models/UserInfo.dart';
  10. import 'package:chat/models/money_change.dart';
  11. import 'package:chat/proto/all.pbserver.dart';
  12. import 'package:chat/utils/ChargeMoney.dart';
  13. import 'package:chat/utils/CustomUI.dart';
  14. import 'package:chat/utils/HttpUtil.dart';
  15. import 'package:chat/utils/LoadingDialog.dart';
  16. import 'package:chat/utils/app_navigator.dart';
  17. import 'package:chat/utils/image_util.dart';
  18. import 'package:chat/utils/msgHandler.dart';
  19. import 'package:chat/utils/screen.dart';
  20. import 'package:dio/dio.dart';
  21. import 'package:flutter/material.dart';
  22. import 'package:flutter_image_compress/flutter_image_compress.dart';
  23. import 'package:google_maps_flutter/google_maps_flutter.dart';
  24. import 'package:image_picker/image_picker.dart';
  25. import 'package:oktoast/oktoast.dart';
  26. import 'package:permission_handler/permission_handler.dart';
  27. import 'package:provider/provider.dart';
  28. import 'package:video_thumbnail/video_thumbnail.dart';
  29. import 'package:file_picker/file_picker.dart';
  30. import '../r.dart';
  31. class UtilKeyboard extends StatelessWidget {
  32. final double keyboardHeight;
  33. final Function sendMsg;
  34. final bool isGroup;
  35. UtilKeyboard({this.keyboardHeight, this.sendMsg, this.isGroup});
  36. bool isAuthority = false;
  37. @override
  38. Widget build(BuildContext context) {
  39. bool isShowRedPacket = UserData().redPacketSW > 0;
  40. List<Widget> iconList = [];
  41. iconList.add(
  42. _buildOtherSelect(R.assetsImagesChatItem1, I18n.of(context).camera, () {
  43. print('开始选择拍照');
  44. _sendPicture(context);
  45. }));
  46. iconList.add(
  47. _buildOtherSelect(R.assetsImagesChatItem2, I18n.of(context).video, () {
  48. print('开始选择视频');
  49. _sendVideo(context);
  50. }));
  51. if (!isGroup) {
  52. iconList.add(
  53. _buildOtherSelect(R.assetsImagesChatItem3, I18n.of(context).chat, () {
  54. _audioChat(context);
  55. }));
  56. }
  57. iconList.add(
  58. _buildOtherSelect(R.assetsImagesChatItem4, I18n.of(context).locate, () {
  59. _openMap(context);
  60. }));
  61. if (!isGroup) {
  62. iconList.add(Offstage(
  63. offstage: !isShowRedPacket,
  64. child: _buildOtherSelect(
  65. R.assetsImagesChatItem5, I18n.of(context).red_money, () {
  66. AppNavigator.pushCoinBagPage(context);
  67. })));
  68. iconList.add(_buildOtherSelect(
  69. R.assetsImagesChatItem6, I18n.of(context).giving_gift, () {
  70. _showGiftSheet(context);
  71. }));
  72. }
  73. iconList.add(_buildOtherSelect(R.assetsImagesChatItem7, '文件', () async {
  74. _sendFile(context);
  75. }));
  76. return Container(
  77. width: Screen.width,
  78. color: Colors.white,
  79. height: keyboardHeight,
  80. padding: EdgeInsets.only(top: 20, bottom: 10, left: 20),
  81. alignment: Alignment.topLeft,
  82. child: Wrap(spacing: 10.0, runSpacing: 20.0, children: iconList));
  83. }
  84. _showGiftSheet(BuildContext context) {
  85. int friendId = 0;
  86. if (!isGroup) {
  87. friendId = Provider.of<int>(context);
  88. }
  89. showModalBottomSheet(
  90. context: context,
  91. elevation: 2.0,
  92. shape: RoundedRectangleBorder(
  93. borderRadius: BorderRadius.only(
  94. topLeft: Radius.circular(20), topRight: Radius.circular(20))),
  95. backgroundColor: Colors.transparent,
  96. builder: (BuildContext context) {
  97. return StatefulBuilder(
  98. builder: (BuildContext context, setBottomSheetState) {
  99. return GiftSelectWidget(friendId, sendMsg);
  100. },
  101. );
  102. });
  103. }
  104. _openMap(BuildContext context) async {
  105. if (await CustomUI.showPermissionSetting(
  106. context, PermissionGroup.location, I18n.of(context).open_location)) {
  107. var result = await LocationPicker.pickLocation(
  108. context, 'AIzaSyAb9JNtW0BEZ_qLeDg87ZhvxSmZply-7hU',
  109. initialCenter: LatLng(UserData().latitude, UserData().longitude));
  110. if (result == null ||
  111. result.address == null ||
  112. result.address.length == 0) {
  113. return;
  114. }
  115. var reslutStr = jsonEncode(result);
  116. int friendId = 0;
  117. if (!isGroup) {
  118. friendId = Provider.of<int>(context);
  119. }
  120. var msg = MsgHandler.createSendMsg(
  121. ChatType.PlaceChatType, utf8.encode(reslutStr),
  122. friendId: friendId,
  123. channelType:
  124. isGroup ? ChatChannelType.Group : ChatChannelType.Session);
  125. sendMsg(msg);
  126. }
  127. }
  128. _audioChat(BuildContext context) async {
  129. if (await CustomUI.showPermissionSetting(context,
  130. PermissionGroup.microphone, I18n.of(context).video_permission)) {
  131. int friendId = Provider.of<int>(context);
  132. UserInfo info = await HttpUtil().getFriendInfo(friendId, true);
  133. if (info == null) {
  134. print('获取用户信息失败');
  135. return;
  136. }
  137. if (info.chatStatus == 0) {
  138. showToast(I18n.of(context).cantt_voice);
  139. return;
  140. }
  141. //对方关闭陌生人消息,则提示
  142. if (!info.isCanStrangerNews) {
  143. showToast(I18n.of(context).stranger_close_tips);
  144. return;
  145. }
  146. if (info.isAuthority ||
  147. (!UserData().isMan() && UserData().basicInfo.isAttestation) ||
  148. info.distince < 200) {
  149. isAuthority = true;
  150. }
  151. becomeVip() {
  152. Navigator.of(context).push(
  153. new MaterialPageRoute(
  154. builder: (context) {
  155. return VipPage();
  156. },
  157. ),
  158. );
  159. }
  160. payCallback() {
  161. if (Provider.of<MoneyChangeProvider>(context).money <
  162. UserData().accountPrice) {
  163. Navigator.of(context).pop();
  164. CustomUI.buildOneConfirm(
  165. context,
  166. I18n.of(context).balance_insufficien,
  167. I18n.of(context).recharge, () {
  168. Navigator.of(context).pop();
  169. ChargeMoney.showChargeSheet(context, () {});
  170. });
  171. return;
  172. }
  173. Navigator.of(context).pop();
  174. HttpUtil().buyChatAccount(UserData().accountPrice, info.userId, context,
  175. () {
  176. isAuthority = true;
  177. });
  178. }
  179. freeTime() {
  180. HttpUtil().userFreeTime(context, info.userId, 2, () {
  181. UserData().basicInfo.usedNum++;
  182. Navigator.of(context).pop();
  183. isAuthority = true;
  184. });
  185. }
  186. if (!isAuthority) {
  187. if (UserData().isVip) {
  188. UserData().basicInfo.freeNum < UserData().basicInfo.usedNum
  189. ? CustomUI.buildOneConfirm(
  190. context,
  191. I18n.of(context).unlock_information,
  192. I18n.of(context)
  193. .pay_unlock
  194. .replaceFirst('/s1', UserData().accountPrice.toString()),
  195. payCallback)
  196. : CustomUI.buildOneConfirm(
  197. context,
  198. I18n.of(context).unlock_information,
  199. I18n.of(context).unlock_choose,
  200. freeTime,
  201. );
  202. } else {
  203. CustomUI.buildTowConfirm(
  204. context,
  205. I18n.of(context).unlock_information,
  206. I18n.of(context).become_member,
  207. becomeVip,
  208. I18n.of(context)
  209. .pay_unlock
  210. .replaceFirst('/s1', UserData().accountPrice.toString()),
  211. payCallback);
  212. }
  213. return;
  214. }
  215. AppNavigator.pushAudioChatPage(context, info);
  216. }
  217. }
  218. void _sendPicture(BuildContext context) async {
  219. if (await CustomUI.showPermissionSetting(
  220. context, PermissionGroup.camera, I18n.of(context).camera_permission)) {
  221. File imgFile = await ImagePicker.pickImage(source: ImageSource.camera);
  222. if (imgFile == null) {
  223. return;
  224. }
  225. var imgSize = await imgFile.length();
  226. print('图片大小:${imgSize / 1024}KB');
  227. var sendImg;
  228. bool isNeedUpload = false;
  229. if (imgSize > ImgSizeLimit) {
  230. print('图片大于 $ImgSizeLimit,压缩');
  231. //发送压缩图
  232. sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path);
  233. isNeedUpload = true;
  234. } else {
  235. sendImg = imgFile.readAsBytesSync().toList();
  236. }
  237. var rect = await WidgetUtil.getImageWH(
  238. image: Image.memory(Uint8List.fromList(sendImg)));
  239. int aspectRatio = rect.width * 100 ~/ rect.height;
  240. int friendId = 0;
  241. if (!isGroup) {
  242. friendId = Provider.of<int>(context);
  243. }
  244. var msg = MsgHandler.createSendMsg(ChatType.ImageChatType, sendImg,
  245. extra: aspectRatio,
  246. friendId: friendId,
  247. localFile: isNeedUpload ? imgFile.absolute.path : null,
  248. channelType:
  249. isGroup ? ChatChannelType.Group : ChatChannelType.Session);
  250. sendMsg(msg);
  251. }
  252. }
  253. void _sendFile(BuildContext context) async {
  254. File file = await FilePicker.getFile();
  255. int fileSize = file.lengthSync();
  256. print('选择的文件 ${file.path} 大小 $fileSize');
  257. if (fileSize > 33 * 1024 * 1024) {
  258. showToast('文件大于33M');
  259. return;
  260. }
  261. int friendId = 0;
  262. if (!isGroup) {
  263. friendId = Provider.of<int>(context);
  264. }
  265. var fileName = file.path.split('/').last;
  266. print('fileName $fileName');
  267. var ext = '';
  268. var extList = fileName.split('.');
  269. if (extList.length > 1) {
  270. ext = extList.last;
  271. }
  272. print('ext $ext');
  273. var fileMsg = FileChat.create();
  274. fileMsg.type = ext;
  275. fileMsg.size = fileSize;
  276. fileMsg.name = fileName;
  277. var msg = MsgHandler.createSendMsg(ChatType.FileChatType, fileMsg.writeToBuffer(),
  278. friendId: friendId,
  279. localFile: file.path,
  280. channelType:
  281. isGroup ? ChatChannelType.Group : ChatChannelType.Session);
  282. sendMsg(msg);
  283. }
  284. void _sendVideo(BuildContext context) async {
  285. if (await CustomUI.showPhotoPermissionSetting(context)) {
  286. File video = await ImagePicker.pickVideo(source: ImageSource.gallery);
  287. if (video == null) {
  288. return;
  289. }
  290. var videoSize = await video.length();
  291. print('视频大小:$videoSize');
  292. if (videoSize > 33 * 1024 * 1024) {
  293. showToast(I18n.of(LoadingManage.context).video_more_big);
  294. return;
  295. }
  296. final thumbnail = await getVideoThumbnail(video);
  297. var rect = await WidgetUtil.getImageWH(
  298. image: Image.memory(Uint8List.fromList(thumbnail)));
  299. int aspectRatio = rect.width * 100 ~/ rect.height;
  300. int friendId = 0;
  301. if (!isGroup) {
  302. friendId = Provider.of<int>(context);
  303. }
  304. var msg = MsgHandler.createSendMsg(ChatType.ShortVideoChatType, thumbnail,
  305. extra: aspectRatio,
  306. friendId: friendId,
  307. localFile: video.path,
  308. channelType:
  309. isGroup ? ChatChannelType.Group : ChatChannelType.Session);
  310. sendMsg(msg);
  311. }
  312. }
  313. getVideoThumbnail(File video) async {
  314. List<int> thumbnail = await VideoThumbnail.thumbnailData(
  315. imageFormat: ImageFormat.JPEG,
  316. video: video.path,
  317. quality: 20,
  318. );
  319. if (thumbnail.length > ImgSizeLimit) {
  320. print('图片较大 ${thumbnail.length}');
  321. thumbnail =
  322. await FlutterImageCompress.compressWithList(thumbnail, quality: 10);
  323. print('压缩后 ${thumbnail.length}');
  324. }
  325. return thumbnail;
  326. }
  327. }
  328. Widget _buildOtherSelect(String imgPath, String title, VoidCallback onTap) {
  329. var imgWidth = Screen.width / 4 - 20;
  330. return InkWell(
  331. child: Container(
  332. width: imgWidth,
  333. child: Column(
  334. children: <Widget>[
  335. SizedBox(
  336. child: Image.asset(imgPath, fit: BoxFit.contain),
  337. width: 40,
  338. height: 40,
  339. ),
  340. SizedBox(height: 5),
  341. Text(title,
  342. maxLines: 1,
  343. overflow: TextOverflow.ellipsis,
  344. textScaleFactor: 1.0,
  345. style: TextStyle(color: Color(0xFF090909), fontSize: 12))
  346. ],
  347. ),
  348. ),
  349. onTap: onTap,
  350. );
  351. }