1.被艾特后,要有推送提醒,并且右上角可以点击到@位置 2. 内容窗口右上角增加状态显示 3. 点击文字内容区域视点击为“机器重译”。 4. 进入聊天对话框后,右上角显示未读消息条数。点击跳转到最开始那条未读消息master
@@ -56,9 +56,9 @@ android { | |||||
// manifestPlaceholders = [ | // manifestPlaceholders = [ | ||||
// AMAP_KEY : "1fd4e93e3b4b13747da41f484c955fe2", /// 高德地图key | // AMAP_KEY : "1fd4e93e3b4b13747da41f484c955fe2", /// 高德地图key | ||||
// ] | // ] | ||||
// ndk { | |||||
// abiFilters 'armeabi-v7a' | |||||
// } | |||||
// ndk { | |||||
// abiFilters 'armeabi-v7a' | |||||
// } | |||||
multiDexEnabled true | multiDexEnabled true | ||||
manifestPlaceholders = [ | manifestPlaceholders = [ | ||||
JPUSH_PKGNAME : 'com.cyhd.henhoandroid', | JPUSH_PKGNAME : 'com.cyhd.henhoandroid', | ||||
@@ -1,11 +1,10 @@ | |||||
#!/bin/sh | #!/bin/sh | ||||
# This is a generated file; do not edit or check into version control. | # This is a generated file; do not edit or check into version control. | ||||
export "FLUTTER_ROOT=/Users/random/sdk/flutter_sdk" | |||||
export "FLUTTER_APPLICATION_PATH=/Users/random/code/flutter/project/hibok" | |||||
export "FLUTTER_TARGET=/Users/random/code/flutter/project/hibok/lib/main.dart" | |||||
export "FLUTTER_ROOT=D:\flutter" | |||||
export "FLUTTER_APPLICATION_PATH=E:\flutterCode\Hibok" | |||||
export "FLUTTER_TARGET=lib\main.dart" | |||||
export "FLUTTER_BUILD_DIR=build" | export "FLUTTER_BUILD_DIR=build" | ||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios" | |||||
export "FLUTTER_FRAMEWORK_DIR=/Users/random/sdk/flutter_sdk/bin/cache/artifacts/engine/ios" | |||||
export "SYMROOT=${SOURCE_ROOT}/../build\ios" | |||||
export "FLUTTER_FRAMEWORK_DIR=D:\flutter\bin\cache\artifacts\engine\ios" | |||||
export "FLUTTER_BUILD_NAME=1.0.9" | export "FLUTTER_BUILD_NAME=1.0.9" | ||||
export "FLUTTER_BUILD_NUMBER=13" | export "FLUTTER_BUILD_NUMBER=13" | ||||
export "TRACK_WIDGET_CREATION=true" |
@@ -257,8 +257,6 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
} else { | } else { | ||||
///todo 翻译管家系统通知消息 | ///todo 翻译管家系统通知消息 | ||||
if (type == ChatType.GroupChatNoticeType.value) { | if (type == ChatType.GroupChatNoticeType.value) { | ||||
var res = GroupChatNotice.fromBuffer(widget.msg.msgContent); | var res = GroupChatNotice.fromBuffer(widget.msg.msgContent); | ||||
@@ -294,9 +292,9 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
_textMsg(List<int> msgContent) { | _textMsg(List<int> msgContent) { | ||||
var msg = utf8.decode(msgContent); | var msg = utf8.decode(msgContent); | ||||
bool isUrl =false; | |||||
if(textList[curTextType].contains('http') ){ | |||||
isUrl =true; | |||||
bool isUrl = false; | |||||
if (textList[curTextType].contains('http')) { | |||||
isUrl = true; | |||||
} | } | ||||
Widget text = Container( | Widget text = Container( | ||||
constraints: BoxConstraints(maxWidth: Screen.width - 120), | constraints: BoxConstraints(maxWidth: Screen.width - 120), | ||||
@@ -304,7 +302,7 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
msg, | msg, | ||||
hideKeyboard: widget.hideKeyboard, | hideKeyboard: widget.hideKeyboard, | ||||
fontSize: FontSize, | fontSize: FontSize, | ||||
color: isUrl?Colors.blue:Colors.black, | |||||
color: isUrl ? Colors.blue : Colors.black, | |||||
), | ), | ||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), | padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), | ||||
decoration: BoxDecoration( | decoration: BoxDecoration( | ||||
@@ -484,7 +482,9 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
_imgMsg(List<int> imgData) { | _imgMsg(List<int> imgData) { | ||||
var imgSize = _getImgSize(); | var imgSize = _getImgSize(); | ||||
ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); | |||||
ImageProvider provider = MemoryImage(widget.msg.localFile == null | |||||
? Uint8List.fromList(imgData) | |||||
: File(widget.msg.localFile).readAsBytesSync()); | |||||
return GestureDetector( | return GestureDetector( | ||||
child: ClipRRect( | child: ClipRRect( | ||||
@@ -631,7 +631,6 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
List<String> actions = [ | List<String> actions = [ | ||||
I18n.of(context).delete, | I18n.of(context).delete, | ||||
I18n.of(context).reply, | I18n.of(context).reply, | ||||
]; | ]; | ||||
actionsFunc.add(() { | actionsFunc.add(() { | ||||
@@ -642,53 +641,48 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
MessageMgr().emit('Reply Select Message', widget.msg); | MessageMgr().emit('Reply Select Message', widget.msg); | ||||
}); | }); | ||||
///转发 | ///转发 | ||||
if (widget.msg.msgType == ChatType.TextChatType.value|| | |||||
widget.msg.msgType == ChatType.ImageChatType.value|| | |||||
widget.msg.msgType == ChatType.ShortVideoChatType.value|| | |||||
widget.msg.msgType == ChatType.PlaceChatType.value|| | |||||
widget.msg.msgType == ChatType.EmoticonType.value|| | |||||
widget.msg.msgType == ChatType.FileChatType.value | |||||
){ | |||||
actions.add( I18n.of(context).forward); | |||||
if (widget.msg.msgType == ChatType.TextChatType.value || | |||||
widget.msg.msgType == ChatType.ImageChatType.value || | |||||
widget.msg.msgType == ChatType.ShortVideoChatType.value || | |||||
widget.msg.msgType == ChatType.PlaceChatType.value || | |||||
widget.msg.msgType == ChatType.EmoticonType.value || | |||||
widget.msg.msgType == ChatType.FileChatType.value) { | |||||
actions.add(I18n.of(context).forward); | |||||
actionsFunc.add(() { | actionsFunc.add(() { | ||||
print('转发消息'); | print('转发消息'); | ||||
if(widget.msg.msgType == ChatType.FileChatType.value && widget.msg.localFile==null){ | |||||
if (widget.msg.msgType == ChatType.FileChatType.value && | |||||
widget.msg.localFile == null) { | |||||
showToast('请先下载文件'); | showToast('请先下载文件'); | ||||
return ; | |||||
return; | |||||
} | } | ||||
AppNavigator.pushForwardPage(context, widget.msg); | AppNavigator.pushForwardPage(context, widget.msg); | ||||
}); | }); | ||||
} | } | ||||
if (widget.msg.msgType == ChatType.FileChatType.value &&widget.msg.localFile!=null) { | |||||
if (widget.msg.msgType == ChatType.FileChatType.value && | |||||
widget.msg.localFile != null) { | |||||
//分享文件 | //分享文件 | ||||
actions.add(I18n.of(context).copy_download_url); | actions.add(I18n.of(context).copy_download_url); | ||||
actionsFunc.add(() async{ | |||||
actionsFunc.add(() async { | |||||
UploadUtil().copyFileUrl(widget.msg, context); | UploadUtil().copyFileUrl(widget.msg, context); | ||||
String path = widget.msg.localFile; | String path = widget.msg.localFile; | ||||
String type='file'; | |||||
if(path.contains('mp4') ||path.contains('mp3')){ | |||||
String type = 'file'; | |||||
if (path.contains('mp4') || path.contains('mp3')) { | |||||
type = 'video'; | type = 'video'; | ||||
}else if(path.contains('png')||path.contains('jpg')||path.contains('jpeg')||path.contains('JPG')||path.contains('PNG')){ | |||||
} else if (path.contains('png') || | |||||
path.contains('jpg') || | |||||
path.contains('jpeg') || | |||||
path.contains('JPG') || | |||||
path.contains('PNG')) { | |||||
type = 'image'; | type = 'image'; | ||||
} | } | ||||
ShareExtend.share(FileCacheMgr.replacePath(path), type); | ShareExtend.share(FileCacheMgr.replacePath(path), type); | ||||
}); | }); | ||||
} | } | ||||
if (widget.msg.msgType == ChatType.TextChatType.value) { | if (widget.msg.msgType == ChatType.TextChatType.value) { | ||||
@@ -716,18 +710,17 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
}); | }); | ||||
} | } | ||||
// String date2 = DateTime.fromMillisecondsSinceEpoch(widget.msg.time).toString(); | // String date2 = DateTime.fromMillisecondsSinceEpoch(widget.msg.time).toString(); | ||||
bool isUrl =false; | |||||
if(widget.msg.msgType==ChatType.TextChatType.value ){ | |||||
if( textList[curTextType].contains('http')){ | |||||
isUrl =true; | |||||
bool isUrl = false; | |||||
if (widget.msg.msgType == ChatType.TextChatType.value) { | |||||
if (textList[curTextType].contains('http')) { | |||||
isUrl = true; | |||||
} | } | ||||
} | } | ||||
return WPopupMenu( | |||||
return WPopupMenu( | |||||
child: item, | child: item, | ||||
actions: actions, | actions: actions, | ||||
onTap: ()async{ | |||||
if(isUrl){ | |||||
onTap: () async { | |||||
if (isUrl) { | |||||
if (await canLaunch(textList[curTextType])) { | if (await canLaunch(textList[curTextType])) { | ||||
launch(textList[curTextType]); | launch(textList[curTextType]); | ||||
} | } | ||||
@@ -794,22 +787,34 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
_receiveText(MsgModel msg) { | _receiveText(MsgModel msg) { | ||||
List<Widget> showMsg = []; | List<Widget> showMsg = []; | ||||
if (textList.length > 0) { | if (textList.length > 0) { | ||||
bool isUrl =false; | |||||
if(textList[curTextType].contains('http') ){ | |||||
isUrl =true; | |||||
bool isUrl = false; | |||||
if (textList[curTextType].contains('http')) { | |||||
isUrl = true; | |||||
} | } | ||||
showMsg.add(Container( | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 140, minHeight: 24), | |||||
alignment: Alignment.centerLeft, | |||||
child: extendedText( | |||||
textList[curTextType], | |||||
color: isUrl?Colors.blue:Constants.BlackTextColor, | |||||
hideKeyboard: widget.hideKeyboard, | |||||
fontSize: FontSize, | |||||
))); | |||||
showMsg.add(InkWell( | |||||
onTap: () { | |||||
if (msg.transTag == 1) { | |||||
return; | |||||
} | |||||
if (msg.transTag == 2 || msg.transTag == 3) { | |||||
setState(() { | |||||
curTextType += 1; | |||||
curTextType %= textList.length; | |||||
}); | |||||
return; | |||||
} | |||||
}, | |||||
child: Container( | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), | |||||
alignment: Alignment.centerLeft, | |||||
child: extendedText( | |||||
textList[curTextType], | |||||
color: isUrl ? Colors.blue : Constants.BlackTextColor, | |||||
hideKeyboard: widget.hideKeyboard, | |||||
fontSize: FontSize, | |||||
)))); | |||||
} | } | ||||
var width = _getTextWidth(textList[curTextType]); | var width = _getTextWidth(textList[curTextType]); | ||||
@@ -825,18 +830,32 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
} | } | ||||
///todo | ///todo | ||||
Widget text = Container( | |||||
width: width + 20, | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth), | |||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), | |||||
child: Column( | |||||
crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), | |||||
decoration: BoxDecoration( | |||||
border: Border.all(color: ReciveBorderColor, width: 0.5), | |||||
color: isLongPressed ? Colors.grey[300] : Colors.white, | |||||
borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), | |||||
); | |||||
Widget text = Stack(children: <Widget>[ | |||||
Container( | |||||
width: width + 20, | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth), | |||||
padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), | |||||
child: Column( | |||||
crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), | |||||
decoration: BoxDecoration( | |||||
border: Border.all(color: ReciveBorderColor, width: 0.5), | |||||
color: isLongPressed ? Colors.grey[300] : Colors.white, | |||||
borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), | |||||
), | |||||
msg.transTag != 1 | |||||
? Positioned( | |||||
right: 5, | |||||
top: 5, | |||||
child: Container( | |||||
child: Row(children: <Widget>[ | |||||
blueDot(curTextType == 0), | |||||
blueDot(curTextType == 1), | |||||
blueDot(curTextType == 2), | |||||
//blueDot(true), | |||||
]))) | |||||
: Container() | |||||
]); | |||||
if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { | if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { | ||||
QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); | QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); | ||||
@@ -903,14 +922,17 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
if (transTag == 1) { | if (transTag == 1) { | ||||
//机器翻译中 | //机器翻译中 | ||||
userTranslateWidget = _translateItemWidget(0xe670, I18n.of(context).man_retranslate, null); | |||||
userTranslateWidget = | |||||
_translateItemWidget(0xe670, I18n.of(context).man_retranslate, null); | |||||
machineTranslateWidget = | machineTranslateWidget = | ||||
_translateItemWidget(0xe671, I18n.of(context).robotTranslate, null); | _translateItemWidget(0xe671, I18n.of(context).robotTranslate, null); | ||||
} else if (transTag == 2) { | } else if (transTag == 2) { | ||||
//人工翻译中 | //人工翻译中 | ||||
userTranslateWidget = _translateItemWidget(0xe670, I18n.of(context).ManTranslate, null); | |||||
machineTranslateWidget = _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { | |||||
userTranslateWidget = | |||||
_translateItemWidget(0xe670, I18n.of(context).ManTranslate, null); | |||||
machineTranslateWidget = | |||||
_translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { | |||||
setState(() { | setState(() { | ||||
curTextType += 1; | curTextType += 1; | ||||
curTextType %= textList.length; | curTextType %= textList.length; | ||||
@@ -962,7 +984,8 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
}); | }); | ||||
} | } | ||||
}); | }); | ||||
machineTranslateWidget = _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { | |||||
machineTranslateWidget = | |||||
_translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () { | |||||
setState(() { | setState(() { | ||||
curTextType += 1; | curTextType += 1; | ||||
curTextType %= textList.length; | curTextType %= textList.length; | ||||
@@ -1017,7 +1040,8 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
)) | )) | ||||
], | ], | ||||
))); | ))); | ||||
machineTranslateWidget = _translateItemWidget(0xe675, I18n.of(context).see_original, () { | |||||
machineTranslateWidget = | |||||
_translateItemWidget(0xe675, I18n.of(context).see_original, () { | |||||
setState(() { | setState(() { | ||||
curTextType = textList.length - 1; | curTextType = textList.length - 1; | ||||
}); | }); | ||||
@@ -1039,15 +1063,16 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
} | } | ||||
_receiveImg(BuildContext context, List<int> imgData, {String downloadData}) { | _receiveImg(BuildContext context, List<int> imgData, {String downloadData}) { | ||||
ImageProvider provider = MemoryImage(widget.msg.localFile==null?Uint8List.fromList(imgData):File(widget.msg.localFile).readAsBytesSync()); | |||||
ImageProvider provider = MemoryImage(widget.msg.localFile == null | |||||
? Uint8List.fromList(imgData) | |||||
: File(widget.msg.localFile).readAsBytesSync()); | |||||
var imgSize = _getImgSize(); | var imgSize = _getImgSize(); | ||||
return DownloadItem( | return DownloadItem( | ||||
isAutoDown: false, | isAutoDown: false, | ||||
msg: widget.msg, | msg: widget.msg, | ||||
onFinishTap: (){ | |||||
onFinishTap: () { | |||||
widget.hideKeyboard(); | widget.hideKeyboard(); | ||||
showFullImg(context, widget.msg); | showFullImg(context, widget.msg); | ||||
}, | }, | ||||
@@ -1062,7 +1087,6 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
), | ), | ||||
), | ), | ||||
); | ); | ||||
} | } | ||||
_receiveVideo(BuildContext context, List<int> imgData, | _receiveVideo(BuildContext context, List<int> imgData, | ||||
@@ -1303,6 +1327,18 @@ class _ChatPageItemState extends State<ChatPageItem> | |||||
})); | })); | ||||
} | } | ||||
blueDot(bool isShow) { | |||||
return Container( | |||||
margin: EdgeInsets.only(right: 5), | |||||
decoration: BoxDecoration( | |||||
shape: BoxShape.circle, | |||||
color: isShow ? Color(0xFFFF7E00) : Color(0xFFCFCFCF), | |||||
), | |||||
width: 6, | |||||
height: 6, | |||||
); | |||||
} | |||||
_reveiveMsg(BuildContext context) { | _reveiveMsg(BuildContext context) { | ||||
Widget item; | Widget item; | ||||
switch (ChatType.valueOf(widget.msg.msgType)) { | switch (ChatType.valueOf(widget.msg.msgType)) { | ||||
@@ -790,16 +790,29 @@ class _GroupChatPageItemState extends State<GroupChatPageItem> | |||||
isUrl = true; | isUrl = true; | ||||
} | } | ||||
showMsg.add(Container( | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), | |||||
alignment: Alignment.centerLeft, | |||||
child: extendedText( | |||||
textList[curTextType], | |||||
color: isUrl ? Colors.blue : Constants.BlackTextColor, | |||||
hideKeyboard: widget.hideKeyboard, | |||||
fontSize: FontSize, | |||||
))); | |||||
showMsg.add(InkWell( | |||||
onTap: () { | |||||
if (msg.transTag == 1) { | |||||
return; | |||||
} | |||||
if (msg.transTag == 2 || msg.transTag == 3) { | |||||
setState(() { | |||||
curTextType += 1; | |||||
curTextType %= textList.length; | |||||
}); | |||||
return; | |||||
} | |||||
}, | |||||
child: Container( | |||||
constraints: | |||||
BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), | |||||
alignment: Alignment.centerLeft, | |||||
child: extendedText( | |||||
textList[curTextType], | |||||
color: isUrl ? Colors.blue : Constants.BlackTextColor, | |||||
hideKeyboard: widget.hideKeyboard, | |||||
fontSize: FontSize, | |||||
)))); | |||||
} | } | ||||
var width = _getTextWidth(textList[curTextType]); | var width = _getTextWidth(textList[curTextType]); | ||||
@@ -827,18 +840,18 @@ class _GroupChatPageItemState extends State<GroupChatPageItem> | |||||
color: isLongPressed ? Colors.grey[300] : Colors.white, | color: isLongPressed ? Colors.grey[300] : Colors.white, | ||||
borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), | borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), | ||||
), | ), | ||||
// msg.transTag != 0 | |||||
// ? Positioned( | |||||
// right: 5, | |||||
// top: 5, | |||||
// child: Container( | |||||
// child: Row(children: <Widget>[ | |||||
// blueDot(true), | |||||
// blueDot(true), | |||||
// blueDot(true), | |||||
// blueDot(true), | |||||
// ]))) | |||||
// : Container() | |||||
msg.transTag != 1 | |||||
? Positioned( | |||||
right: 5, | |||||
top: 5, | |||||
child: Container( | |||||
child: Row(children: <Widget>[ | |||||
blueDot(curTextType == 0), | |||||
blueDot(curTextType == 1), | |||||
blueDot(curTextType == 2), | |||||
//blueDot(true), | |||||
]))) | |||||
: Container() | |||||
]); | ]); | ||||
if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { | if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { | ||||
@@ -47,8 +47,6 @@ class GroupChatPage extends StatefulWidget { | |||||
} | } | ||||
class _GroupChatPageState extends State<GroupChatPage> { | class _GroupChatPageState extends State<GroupChatPage> { | ||||
ScrollController _scrollCtrl = ScrollController(); | |||||
final ItemScrollController itemScrollController = ItemScrollController(); | final ItemScrollController itemScrollController = ItemScrollController(); | ||||
final ItemPositionsListener itemPositionListener = | final ItemPositionsListener itemPositionListener = | ||||
ItemPositionsListener.create(); | ItemPositionsListener.create(); | ||||
@@ -67,6 +65,16 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
//子元素的对应偏移量 | //子元素的对应偏移量 | ||||
Map itemOffsetMap = {}; | Map itemOffsetMap = {}; | ||||
//未读消息数目 | |||||
int unreadNums = 0; | |||||
//最上一条未读消息id | |||||
int unreadTime; | |||||
//@消息索引 | |||||
int alterTime; | |||||
String alterUserName = ''; | |||||
@override | @override | ||||
void dispose() { | void dispose() { | ||||
var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; | var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; | ||||
@@ -78,7 +86,6 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
msgMgr.off('Delete Select Message', _deleteItem); | msgMgr.off('Delete Select Message', _deleteItem); | ||||
MsgHandler.curActiveSession = 0; | MsgHandler.curActiveSession = 0; | ||||
SoundUtils().stop(); | SoundUtils().stop(); | ||||
_scrollCtrl.dispose(); | |||||
super.dispose(); | super.dispose(); | ||||
} | } | ||||
@@ -91,14 +98,28 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
getDefaultSetting(); | getDefaultSetting(); | ||||
startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; | startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; | ||||
unreadNums = ChatDataMgr() | |||||
.groupUnreadProvider | |||||
.getUnreadCount(widget.groupInfoModel.sessionId); | |||||
alterTime = ChatDataMgr() | |||||
.groupUnreadProvider | |||||
.getHavaAltertime(widget.groupInfoModel.sessionId); | |||||
MsgHandler.updateActiveSesstion(widget.groupInfoModel.sessionId, | MsgHandler.updateActiveSesstion(widget.groupInfoModel.sessionId, | ||||
isGroup: true); | isGroup: true); | ||||
msgList = ChatDataMgr().getGroupRecord(); | msgList = ChatDataMgr().getGroupRecord(); | ||||
for (int k = 0; k < msgList.length; k++) { | |||||
MsgModel msg = msgList[k]; | |||||
print('msgList ${msg.msgType} ${msg.from}'); | |||||
if (unreadNums >= 10) { | |||||
unreadTime = msgList[unreadNums - 1].time; | |||||
} | |||||
for (int i = 0; i < msgList.length; i++) { | |||||
if (msgList[i].time == alterTime) { | |||||
alterUserName = | |||||
widget.groupInfoModel.getMember(msgList[i].friendId).nickName; | |||||
break; | |||||
} | |||||
} | } | ||||
msgMgr.on('New Chat Message', receiveMsg); | msgMgr.on('New Chat Message', receiveMsg); | ||||
@@ -117,6 +138,7 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
ChatType.valueOf(originMsg.msgType), originMsg.msgContent, | ChatType.valueOf(originMsg.msgType), originMsg.msgContent, | ||||
channelType: ChatChannelType.Group); | channelType: ChatChannelType.Group); | ||||
msg.extraInfo = originMsg.extraInfo; | msg.extraInfo = originMsg.extraInfo; | ||||
// msg.extraFile = originMsg.extraFile; | // msg.extraFile = originMsg.extraFile; | ||||
if (originMsg.extraFile == null || | if (originMsg.extraFile == null || | ||||
originMsg.extraFile.contains('http')) { | originMsg.extraFile.contains('http')) { | ||||
@@ -133,12 +155,6 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
sendMsg(msg); | sendMsg(msg); | ||||
} | } | ||||
}); | }); | ||||
itemPositionListener.itemPositions.addListener(() { | |||||
print(itemPositionListener.itemPositions.value); | |||||
//itemScrollController.jumpTo(index: 1, alignment: -0.02208835341365462); | |||||
//-0.02208835341365462, itemTrailingEdge: 0.12650602409638553 | |||||
}); | |||||
} | } | ||||
void _sendFile(File file) async { | void _sendFile(File file) async { | ||||
@@ -237,6 +253,9 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
Map refMap = Provider.of<RefNameProvider>(context).refMap; | Map refMap = Provider.of<RefNameProvider>(context).refMap; | ||||
bool isHaveUnreadNews = unreadTime !=null; | |||||
bool isAlterYou = alterTime != null; | |||||
return MultiProvider( | return MultiProvider( | ||||
providers: [ | providers: [ | ||||
ChangeNotifierProvider(create: (_) => _keyboardIndexProvider), | ChangeNotifierProvider(create: (_) => _keyboardIndexProvider), | ||||
@@ -276,27 +295,77 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
InputBar(sendMsg: sendMsg), | InputBar(sendMsg: sendMsg), | ||||
], | ], | ||||
), | ), | ||||
// Positioned( | |||||
// top: 32.5, | |||||
// right: 0, | |||||
// child: Container( | |||||
// decoration: BoxDecoration( | |||||
// boxShadow: [ | |||||
// BoxShadow( | |||||
// color: Color(0x33000000), //阴影颜色 | |||||
// blurRadius: 10.0, //阴影大小 | |||||
// ) | |||||
// ], | |||||
// borderRadius: BorderRadius.only( | |||||
// topLeft: Radius.circular(80), | |||||
// bottomLeft: Radius.circular(80)), | |||||
// color: Colors.white, | |||||
// ), | |||||
// width: 120, | |||||
// height: 39)) | |||||
isHaveUnreadNews | |||||
? Positioned( | |||||
top: 32.5, | |||||
right: 0, | |||||
child: InkWell( | |||||
onTap: () { | |||||
var screenItemNums = | |||||
itemPositionListener | |||||
.itemPositions.value.length; | |||||
int jumIndex = 0; | |||||
if (isAlterYou) { | |||||
for (int i = 0; | |||||
i < msgList.length; | |||||
i++) { | |||||
if (alterTime == msgList[i].time) { | |||||
jumIndex = i - screenItemNums + 2; | |||||
break; | |||||
} | |||||
} | |||||
} else { | |||||
for (int i = 0; | |||||
i < msgList.length; | |||||
i++) { | |||||
if (unreadTime == msgList[i].time) { | |||||
jumIndex = i - screenItemNums + 2; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
itemScrollController.jumpTo( | |||||
index: jumIndex); | |||||
unreadTime = null; | |||||
setState(() {}); | |||||
}, | |||||
child: Container( | |||||
alignment: Alignment.center, | |||||
decoration: BoxDecoration( | |||||
boxShadow: [ | |||||
BoxShadow( | |||||
color: Color(0x33000000), //阴影颜色 | |||||
blurRadius: 10.0, //阴影大小 | |||||
) | |||||
], | |||||
borderRadius: BorderRadius.only( | |||||
topLeft: Radius.circular(80), | |||||
bottomLeft: Radius.circular(80)), | |||||
color: Colors.white, | |||||
), | |||||
constraints: | |||||
BoxConstraints(minWidth: 120), | |||||
height: 39, | |||||
child: Row( | |||||
children: <Widget>[ | |||||
Icon( | |||||
Icons.file_upload, | |||||
color: Color(0xFF3875E9), | |||||
size: 20, | |||||
), | |||||
Text( | |||||
isAlterYou | |||||
? '$alterUserName @你' | |||||
: '$unreadNums条新消息', | |||||
style: TextStyle( | |||||
color: Color(0xFF3875E9)), | |||||
) | |||||
], | |||||
), | |||||
))) | |||||
: Container() | |||||
], | ], | ||||
))), | ))), | ||||
behavior: HitTestBehavior.translucent, | |||||
onPointerDown: (value) { | onPointerDown: (value) { | ||||
for (var state in states) { | for (var state in states) { | ||||
if (!state.containsPosition(value.position)) { | if (!state.containsPosition(value.position)) { | ||||
@@ -418,25 +487,15 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
style: TextStyle(color: Colors.grey), | style: TextStyle(color: Colors.grey), | ||||
)) | )) | ||||
: Scrollbar( | : Scrollbar( | ||||
child: | |||||
// ScrollablePositionedList.builder( | |||||
// itemCount: msgList.length, | |||||
// itemBuilder: _buildItem, | |||||
// itemScrollController: itemScrollController, | |||||
// itemPositionsListener: itemPositionListener, | |||||
// padding: EdgeInsets.all(8.0), | |||||
// reverse: true, | |||||
// ) | |||||
ListView.builder( | |||||
reverse: true, | |||||
shrinkWrap: true, | |||||
itemCount: msgList.length, | |||||
controller: _scrollCtrl, | |||||
padding: EdgeInsets.all(8.0), | |||||
itemBuilder: _buildItem, | |||||
) | |||||
), | |||||
child: ScrollablePositionedList.builder( | |||||
physics: new ClampingScrollPhysics(), | |||||
itemCount: msgList.length, | |||||
itemBuilder: _buildItem, | |||||
itemScrollController: itemScrollController, | |||||
itemPositionsListener: itemPositionListener, | |||||
padding: EdgeInsets.all(8.0), | |||||
reverse: true, | |||||
)), | |||||
); | ); | ||||
} | } | ||||
@@ -460,13 +519,7 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
if (mounted) { | if (mounted) { | ||||
setState(() {}); | setState(() {}); | ||||
} | } | ||||
if (_scrollCtrl.hasClients) { | |||||
_scrollCtrl.animateTo(0, | |||||
duration: new Duration(milliseconds: 500), curve: Curves.ease); | |||||
} | |||||
// testBig(msg); | |||||
itemScrollController.jumpTo(index: 0); | |||||
} | } | ||||
MsgModel msg; | MsgModel msg; | ||||
@@ -487,17 +540,12 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
} | } | ||||
void receiveMsg(args) { | void receiveMsg(args) { | ||||
print("msgList.length: ${msgList.length}"); | |||||
if (args != widget.groupInfoModel.sessionId) { | if (args != widget.groupInfoModel.sessionId) { | ||||
return; | return; | ||||
} | } | ||||
if (mounted) { | if (mounted) { | ||||
setState(() { | |||||
//itemScrollController.jumpTo(index: 3); | |||||
if (_scrollCtrl.hasClients) { | |||||
// _scrollCtrl.animateTo(0, | |||||
// duration: new Duration(milliseconds: 500), curve: Curves.ease); | |||||
} | |||||
}); | |||||
setState(() {}); | |||||
} | } | ||||
} | } | ||||
@@ -513,7 +561,7 @@ class _GroupChatPageState extends State<GroupChatPage> { | |||||
var lastMsgTime; | var lastMsgTime; | ||||
if (index < msgList.length - 1) { | if (index < msgList.length - 1) { | ||||
lastMsgTime = msgList[index + 1].time; | |||||
lastMsgTime = msgList[index].time; | |||||
} | } | ||||
MsgModel msg = msgList[index]; | MsgModel msg = msgList[index]; | ||||
@@ -313,7 +313,7 @@ class ChatDataMgr { | |||||
print('数据为空,无法插入'); | print('数据为空,无法插入'); | ||||
} else { | } else { | ||||
record.insert(0, msg); | record.insert(0, msg); | ||||
//record.add(msg); | |||||
SqlUtil.insert(msg); | SqlUtil.insert(msg); | ||||
updateLastRecordWithMsg(msg); | updateLastRecordWithMsg(msg); | ||||
@@ -149,8 +149,8 @@ class _GroupItemState extends State<GroupItem> { | |||||
//有人@你就优先展示 | //有人@你就优先展示 | ||||
ChatDataMgr() | ChatDataMgr() | ||||
.groupUnreadProvider | .groupUnreadProvider | ||||
.getHavaAlterme(widget | |||||
.groupInfoModel.lastMsg.sessionId) | |||||
.getHavaAltertime(widget | |||||
.groupInfoModel.lastMsg.sessionId) != null | |||||
? Text( | ? Text( | ||||
'[有人@我]', | '[有人@我]', | ||||
textScaleFactor: 1.0, | textScaleFactor: 1.0, | ||||
@@ -5,7 +5,7 @@ class UnreadCountProvider { | |||||
Map<int, int> unreadCountMap = {}; | Map<int, int> unreadCountMap = {}; | ||||
//是否有@我的消息 | //是否有@我的消息 | ||||
Map<int, bool> isHaveAlterme = {}; | |||||
Map<int, int> isHaveAlterme = {}; | |||||
updateUnreadCount(int sessionId, int count) { | updateUnreadCount(int sessionId, int count) { | ||||
if (unreadCountMap[sessionId] == null) { | if (unreadCountMap[sessionId] == null) { | ||||
@@ -16,12 +16,12 @@ class UnreadCountProvider { | |||||
MessageMgr().emit('Update UnreadCount', sessionId); | MessageMgr().emit('Update UnreadCount', sessionId); | ||||
} | } | ||||
getHavaAlterme(int sessionId) { | |||||
return isHaveAlterme[sessionId] ?? false; | |||||
getHavaAltertime(int sessionId) { | |||||
return isHaveAlterme[sessionId] ?? null; | |||||
} | } | ||||
setAlterMe(int sessionId){ | |||||
isHaveAlterme[sessionId] = true; | |||||
setAlterMe(int sessionId, int time) { | |||||
isHaveAlterme[sessionId] = time; | |||||
} | } | ||||
clear() { | clear() { | ||||
@@ -45,7 +45,7 @@ class UnreadCountProvider { | |||||
print('消除未读标记:$sessionId'); | print('消除未读标记:$sessionId'); | ||||
int count = getUnreadCount(sessionId); | int count = getUnreadCount(sessionId); | ||||
isHaveAlterme[sessionId] = false; | |||||
isHaveAlterme[sessionId] = null; | |||||
if (count > 0) { | if (count > 0) { | ||||
unreadCountMap[sessionId] = 0; | unreadCountMap[sessionId] = 0; | ||||
@@ -509,9 +509,9 @@ class MsgHandler { | |||||
var myId = UserData().basicInfo.userId; | var myId = UserData().basicInfo.userId; | ||||
for (var i = 0; i < msgModel.altUsers.length; i++) { | for (var i = 0; i < msgModel.altUsers.length; i++) { | ||||
if (msgModel.altUsers[i] == myId) { | |||||
if (msgModel.altUsers[i] == myId && curActiveSession != sessionId) { | |||||
print('有人@了你'); | print('有人@了你'); | ||||
ChatDataMgr().groupUnreadProvider.setAlterMe(sessionId); | |||||
ChatDataMgr().groupUnreadProvider.setAlterMe(sessionId,msgModel.time); | |||||
//to do | //to do | ||||
} | } | ||||
} | } | ||||