Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

376 line
11 KiB

  1. import 'dart:io';
  2. import 'dart:typed_data';
  3. import 'package:chat/chat/ChatPageItem.dart';
  4. import 'package:chat/data/chat_data_mgr.dart';
  5. import 'package:chat/data/constants.dart';
  6. import 'package:chat/generated/i18n.dart';
  7. import 'package:chat/models/ChatMsg.dart';
  8. import 'package:chat/models/UserInfo.dart';
  9. import 'package:chat/photo/entity/options.dart';
  10. import 'package:chat/photo/photo.dart';
  11. import 'package:chat/proto/chat.pb.dart';
  12. import 'package:chat/r.dart';
  13. import 'package:chat/utils/CustomUI.dart';
  14. import 'package:chat/utils/HttpUtil.dart';
  15. import 'package:chat/utils/file_cache_mgr.dart';
  16. import 'package:chat/utils/image_util.dart';
  17. import 'package:chat/utils/keyboard_utils.dart';
  18. import 'package:chat/utils/msgHandler.dart';
  19. import 'package:chat/utils/screen.dart';
  20. import 'package:flutter/material.dart';
  21. import 'package:flutter/services.dart';
  22. import 'package:flutter_screenutil/flutter_screenutil.dart';
  23. import 'package:multi_image_picker/multi_image_picker.dart';
  24. import 'package:oktoast/oktoast.dart';
  25. import 'package:photo_manager/photo_manager.dart';
  26. import 'package:chat/utils/MessageMgr.dart';
  27. class CompanyServerPage extends StatefulWidget {
  28. @override
  29. _CompanyServerPageState createState() => _CompanyServerPageState();
  30. }
  31. class _CompanyServerPageState extends State<CompanyServerPage> {
  32. final TextEditingController _textCtrl = TextEditingController();
  33. FocusNode editFocus = NoKeyboardEditableTextFocusNode();
  34. bool _isComposingMessage = false;
  35. double keyboardHeight;
  36. KeyboardBloc _bloc = KeyboardBloc();
  37. ScrollController _scrollCtrl = ScrollController();
  38. List<MsgModel> msgList = [];
  39. static int companyId = 10000;
  40. UserInfo companyInfo = UserInfo(
  41. userId: companyId,
  42. headimgurl: R.assetsImagesServerIcon,
  43. nickName: I18n.of(Constants.getCurrentContext()).feedback_assistant);
  44. @override
  45. void initState() {
  46. super.initState();
  47. _bloc.start();
  48. //10000号为服务小助手
  49. MsgHandler.updateActiveSesstion(companyId);
  50. msgList = ChatDataMgr().getRecord();
  51. MessageMgr().on('New Chat Message', receiveMsg);
  52. }
  53. @override
  54. void dispose() {
  55. MsgHandler.curActiveSession = 0;
  56. _textCtrl.dispose();
  57. _bloc.dispose();
  58. editFocus.dispose();
  59. _scrollCtrl.dispose();
  60. MessageMgr().off('New Chat Message', receiveMsg);
  61. super.dispose();
  62. }
  63. receiveMsg(sessionId) {
  64. print('收到反馈助手消息');
  65. if (mounted) {
  66. setState(() {});
  67. if (_scrollCtrl.hasClients) {
  68. _scrollCtrl.animateTo(0,
  69. duration: new Duration(milliseconds: 500), curve: Curves.ease);
  70. }
  71. }
  72. }
  73. hideKeyBoard() {
  74. editFocus.unfocus();
  75. }
  76. bool checkMessage() {
  77. if (_textCtrl.text.length == 0) {
  78. showToast(I18n.of(context).msg_not);
  79. return false;
  80. }
  81. return true;
  82. }
  83. Future<Null> _textMessageSubmitted(String text) async {
  84. if (!checkMessage()) {
  85. _textCtrl.clear();
  86. return;
  87. }
  88. _textCtrl.clear();
  89. _sendMessage(text);
  90. }
  91. _sendTextMessage() {
  92. if (!checkMessage()) {
  93. return;
  94. }
  95. var sendStr = _textCtrl.text;
  96. _textCtrl.clear();
  97. _sendMessage(sendStr);
  98. }
  99. _sendMessage(String messageText) {
  100. MsgModel msg = MsgHandler.createSendMsg(ChatType.TextChatType, messageText,
  101. friendId: companyId, channelType: ChatChannelType.CSD);
  102. setState(() {
  103. _isComposingMessage = _textCtrl.text.length > 0;
  104. });
  105. sendMsg(msg);
  106. }
  107. sendMsg(MsgModel msg) async {
  108. ChatDataMgr().saveCompanyMsg(msg);
  109. if (mounted) {
  110. setState(() {});
  111. if (_scrollCtrl.hasClients) {
  112. _scrollCtrl.animateTo(0,
  113. duration: new Duration(milliseconds: 500), curve: Curves.ease);
  114. }
  115. }
  116. await HttpUtil().commitInfoToCompany(msg);
  117. if (mounted) {
  118. setState(() {});
  119. }
  120. }
  121. void _openPhotoView() async {
  122. List<Asset> resultList = List<Asset>();
  123. try {
  124. resultList = await MultiImagePicker.pickImages(
  125. maxImages: 9,
  126. enableCamera: false,
  127. selectedAssets: [],
  128. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  129. materialOptions: MaterialOptions(
  130. actionBarColor: "#50A7F9",
  131. actionBarTitle: "Hibok",
  132. allViewTitle: "",
  133. useDetailsView: false,
  134. selectCircleStrokeColor: "#000000",
  135. ),
  136. );
  137. if (resultList != null && resultList.length > 0) {
  138. for (var i = 0; i < resultList.length; i++) {
  139. Asset photoEntity = resultList[i];
  140. ByteData byteData = await photoEntity.getByteData();
  141. File file = await FileCacheMgr().writeFile('temp-photo-${DateTime.now().millisecondsSinceEpoch}-$i', byteData.buffer.asInt8List(0));
  142. _sendPhotoFile(file);
  143. }
  144. }
  145. } on Exception catch (e) {
  146. print(e.toString());
  147. }
  148. // var photos = await PhotoPicker.pickAsset(
  149. // context: context,
  150. // themeColor: Color(0xFFF0F0F0),
  151. // textColor: Color(0xFF3F3F3F),
  152. // pickType: PickType.onlyImage);
  153. //
  154. // if (photos != null && photos.length > 0) {
  155. // for (var i = 0; i < photos.length; i++) {
  156. // AssetEntity photoEntity = photos[i];
  157. // var file = await photoEntity.file;
  158. // _sendPhotoFile(file);
  159. // }
  160. // }
  161. }
  162. void _sendPhotoFile(File imgFile) async {
  163. var imgSize = await imgFile.length();
  164. print('图片大小:${imgSize / 1024}KB');
  165. var sendImg;
  166. if (imgSize > 33 * 1024 * 1024) {
  167. showToast(I18n.of(context).video_more_big);
  168. return;
  169. }
  170. bool isNeedUpload = false;
  171. if (imgSize > ImgSizeLimit) {
  172. print('图片大于 $ImgSizeLimit,压缩');
  173. //发送压缩图
  174. sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path );
  175. isNeedUpload = true;
  176. } else {
  177. sendImg = imgFile.readAsBytesSync();
  178. }
  179. var rect = await WidgetUtil.getImageWH(
  180. image: Image.memory(Uint8List.fromList(sendImg)));
  181. print('图片大小 Rect : $rect');
  182. int aspectRatio = rect.width * 100 ~/ rect.height;
  183. var msg = MsgHandler.createSendMsg(ChatType.ImageChatType, sendImg,
  184. localFile: isNeedUpload ? imgFile.absolute.path : null,
  185. extra: aspectRatio,
  186. friendId: companyId,
  187. channelType: ChatChannelType.CSD);
  188. sendMsg(msg);
  189. }
  190. _inputBar() {
  191. Widget input = Container(
  192. child: TextField(
  193. keyboardAppearance: Brightness.light,
  194. onChanged: (String messageText) {
  195. setState(() {
  196. _isComposingMessage = _textCtrl.text.length > 0;
  197. });
  198. },
  199. cursorColor: Constants.BlueTextColor,
  200. style: TextStyle(
  201. fontSize: ScreenUtil().setSp(16),
  202. textBaseline: TextBaseline.alphabetic),
  203. maxLines: 3,
  204. minLines: 1,
  205. controller: _textCtrl,
  206. textInputAction: TextInputAction.newline,
  207. inputFormatters: <TextInputFormatter>[
  208. LengthLimitingTextInputFormatter(600) //限制长度
  209. ],
  210. onSubmitted: _textMessageSubmitted,
  211. focusNode: editFocus,
  212. decoration: InputDecoration(
  213. hintText: I18n.of(context).input_content,
  214. hintStyle: TextStyle(color: const Color(0xffBDBDBD), fontSize: 16),
  215. border: null,
  216. hintMaxLines: 1,
  217. contentPadding: EdgeInsets.only(left: 5, right: 5, top: 8, bottom: 8),
  218. ),
  219. ),
  220. );
  221. return GestureDetector(
  222. onTap: () {
  223. print('放置触控隐藏键盘');
  224. },
  225. child: Container(
  226. width: Screen.width,
  227. color: Colors.white,
  228. child: Container(
  229. padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7),
  230. alignment: Alignment.topCenter,
  231. decoration: BoxDecoration(
  232. color: Colors.white,
  233. border: Border(top: BorderSide(color: Color(0xFFDFDFDF)))),
  234. child: Row(
  235. children: <Widget>[
  236. //输入框
  237. Expanded(child: input), SizedBox(width: 10),
  238. _isComposingMessage
  239. ? InkWell(
  240. child: Padding(
  241. padding: EdgeInsets.fromLTRB(50, 2, 10, 2),
  242. child: Icon(
  243. Icons.send,
  244. color: Color(0xFF087FF3),
  245. size: 28,
  246. )),
  247. onTap: _sendTextMessage)
  248. : InkWell(
  249. child: Icon(
  250. IconData(0xe60c,
  251. fontFamily: Constants.IconFontFamily),
  252. color: Color(0xFF797A7C),
  253. size: 26,
  254. ),
  255. onTap: () {
  256. _openPhotoView();
  257. }),
  258. ],
  259. ))));
  260. }
  261. Widget _buildMessageList() {
  262. return Container(
  263. alignment: Alignment.topCenter,
  264. child: msgList.length == 0
  265. ? Padding(
  266. padding: EdgeInsets.all(8),
  267. child: Text(
  268. I18n.of(context).feedback_tips,
  269. textAlign: TextAlign.center,
  270. textScaleFactor: 1.0,
  271. style: TextStyle(color: Colors.grey, fontSize: 12),
  272. ))
  273. : Scrollbar(
  274. child: ListView.builder(
  275. reverse: true,
  276. shrinkWrap: true,
  277. itemCount: msgList.length,
  278. controller: _scrollCtrl,
  279. padding: EdgeInsets.all(8.0),
  280. itemBuilder: _buildItem,
  281. )),
  282. );
  283. }
  284. Widget _buildItem(BuildContext context, int index) {
  285. var lastMsgTime;
  286. if (index < msgList.length - 1) {
  287. lastMsgTime = msgList[index + 1].time;
  288. }
  289. MsgModel msg = msgList[index];
  290. return ChatPageItem(
  291. key: Key(msg.time.toString()),
  292. msg: msg,
  293. lastMsgTime: lastMsgTime,
  294. friendInfo: companyInfo);
  295. }
  296. @override
  297. Widget build(BuildContext context) {
  298. return GestureDetector(
  299. onTap: hideKeyBoard,
  300. child: Scaffold(
  301. backgroundColor: const Color(0xFFE2E9F1),
  302. appBar: AppBar(
  303. title: Text(
  304. I18n.of(context).feedback_assistant,
  305. textScaleFactor: 1.0,
  306. style:
  307. TextStyle(color: Constants.BlackTextColor, fontSize: 16.47),
  308. ),
  309. leading: CustomUI.buildCustomLeading(context),
  310. titleSpacing: -10,
  311. centerTitle: false,
  312. elevation: 1,
  313. ),
  314. body: SafeArea(
  315. child: Column(
  316. children: <Widget>[
  317. Expanded(child: _buildMessageList()),
  318. _inputBar(),
  319. ],
  320. ))),
  321. );
  322. }
  323. }