Hibok
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

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