|
|
|
@ -138,7 +138,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
queryUser() async { |
|
|
|
|
sharedPre = await SharedPreferences.getInstance(); |
|
|
|
|
if (apiService == null) |
|
|
|
|
apiService = ApiService(Dio(), context: context, token: sharedPre.getString("token")); |
|
|
|
|
apiService = ApiService(Dio(), |
|
|
|
|
context: context, token: sharedPre.getString("token")); |
|
|
|
|
if (sharedPre.containsKey('user') && |
|
|
|
|
sharedPre.getString('user') != null && |
|
|
|
|
sharedPre.getString('user') != "") { |
|
|
|
@ -179,8 +180,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
|
|
|
|
|
void jumpToBottom() { |
|
|
|
|
Future.delayed(const Duration(milliseconds: 100), () { |
|
|
|
|
scrollController.position |
|
|
|
|
.jumpTo(0); |
|
|
|
|
scrollController.position.jumpTo(0); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -319,7 +319,10 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
List<String> filePath = mediaPaths.map((e) => e.path).toList(); |
|
|
|
|
Future.forEach(filePath.toSet(), (path) async { |
|
|
|
|
String fileUrl = await qiniu.uploadFile(apiService, path); |
|
|
|
|
socketClient.sendMessage(_toUser.mid, fileUrl, attach: path, msgType: galleryMode == GalleryMode.image ? 2 : 4).then((value) { |
|
|
|
|
socketClient |
|
|
|
|
.sendMessage(_toUser.mid, fileUrl, |
|
|
|
|
attach: path, msgType: galleryMode == GalleryMode.image ? 2 : 4) |
|
|
|
|
.then((value) { |
|
|
|
|
Message message = value; |
|
|
|
|
messages.insert(0, message); |
|
|
|
|
chatController.clear(); |
|
|
|
@ -329,7 +332,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
setState(() {}); |
|
|
|
|
} |
|
|
|
@ -353,7 +355,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
heightRatioWithWidth: 0.82, |
|
|
|
|
); |
|
|
|
|
}); |
|
|
|
|
}else if (await Permission.camera.isGranted) { |
|
|
|
|
} else if (await Permission.camera.isGranted) { |
|
|
|
|
if (await Permission.storage.isPermanentlyDenied) { |
|
|
|
|
showCupertinoDialog( |
|
|
|
|
context: context, |
|
|
|
@ -370,7 +372,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
}, |
|
|
|
|
heightRatioWithWidth: 0.82, |
|
|
|
|
); |
|
|
|
|
});}else if(await Permission.storage.isGranted){ |
|
|
|
|
}); |
|
|
|
|
} else if (await Permission.storage.isGranted) { |
|
|
|
|
Media medias = await ImagePickers.openCamera( |
|
|
|
|
cameraMimeType: CameraMimeType.photo, |
|
|
|
|
cropConfig: CropConfig( |
|
|
|
@ -383,7 +386,9 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
if (medias == null) return; |
|
|
|
|
String path = medias.path; |
|
|
|
|
String fileUrl = await qiniu.uploadFile(apiService, path); |
|
|
|
|
socketClient.sendMessage(_toUser.mid, fileUrl, attach: path, msgType: 2).then((value) { |
|
|
|
|
socketClient |
|
|
|
|
.sendMessage(_toUser.mid, fileUrl, attach: path, msgType: 2) |
|
|
|
|
.then((value) { |
|
|
|
|
Message message = value; |
|
|
|
|
messages.insert(0, message); |
|
|
|
|
chatController.clear(); |
|
|
|
@ -392,7 +397,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
jumpToBottom(); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
}else{ |
|
|
|
|
} else { |
|
|
|
|
showCameraTipsAlertDialog(context); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
@ -423,7 +428,10 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
child: Row( |
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
children: [ |
|
|
|
|
Padding(padding:EdgeInsets.only(right: 10.w,), |
|
|
|
|
Padding( |
|
|
|
|
padding: EdgeInsets.only( |
|
|
|
|
right: 10.w, |
|
|
|
|
), |
|
|
|
|
child: Icon( |
|
|
|
|
Icons.add_photo_alternate_outlined, |
|
|
|
|
color: Colors.black, |
|
|
|
@ -467,7 +475,7 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
); |
|
|
|
|
await Permission.camera.request(); |
|
|
|
|
Navigator.of(context).pop(); |
|
|
|
|
if(await Permission.camera.isGranted){ |
|
|
|
|
if (await Permission.camera.isGranted) { |
|
|
|
|
openCamera(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -635,7 +643,6 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
// height: 16.h, |
|
|
|
|
// ), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// not self |
|
|
|
|
if (!isSelf && isText) |
|
|
|
|
SizedBox( |
|
|
|
@ -675,10 +682,12 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
Expanded( |
|
|
|
|
child: Container( |
|
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
|
child:GestureDetector( |
|
|
|
|
child: GestureDetector( |
|
|
|
|
onLongPress: () { |
|
|
|
|
RenderBox renderBox = _buttonKey.currentContext.findRenderObject() as RenderBox; |
|
|
|
|
Offset buttonPosition = renderBox.localToGlobal(Offset.zero); |
|
|
|
|
RenderBox renderBox = _buttonKey.currentContext |
|
|
|
|
.findRenderObject() as RenderBox; |
|
|
|
|
Offset buttonPosition = |
|
|
|
|
renderBox.localToGlobal(Offset.zero); |
|
|
|
|
Size buttonSize = renderBox.size; |
|
|
|
|
|
|
|
|
|
showMenu( |
|
|
|
@ -687,16 +696,18 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
elevation: 0, |
|
|
|
|
color: Colors.transparent, |
|
|
|
|
position: RelativeRect.fromLTRB( |
|
|
|
|
buttonPosition.dx + (buttonSize.width - 180.w) / 2, // 居中对齐 |
|
|
|
|
buttonPosition.dx + |
|
|
|
|
(buttonSize.width - 180.w) / 2, // 居中对齐 |
|
|
|
|
buttonPosition.dy - 68, |
|
|
|
|
buttonPosition.dx + buttonSize.width, |
|
|
|
|
buttonPosition.dy |
|
|
|
|
), /// 设置弹出菜单的显示位置 |
|
|
|
|
buttonPosition.dy), |
|
|
|
|
|
|
|
|
|
/// 设置弹出菜单的显示位置 |
|
|
|
|
items: [ |
|
|
|
|
PopupMenuItem( |
|
|
|
|
value: 1, |
|
|
|
|
padding: EdgeInsets.zero, |
|
|
|
|
child:Stack( |
|
|
|
|
child: Stack( |
|
|
|
|
alignment: Alignment.bottomCenter, |
|
|
|
|
children: [ |
|
|
|
|
Container( |
|
|
|
@ -705,18 +716,22 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
width: 180.w, |
|
|
|
|
decoration: BoxDecoration( |
|
|
|
|
color: Color(0xFF2A2A2A), |
|
|
|
|
borderRadius: BorderRadius.circular(6), |
|
|
|
|
borderRadius: |
|
|
|
|
BorderRadius.circular(6), |
|
|
|
|
), |
|
|
|
|
padding: |
|
|
|
|
EdgeInsets.symmetric(horizontal: 32.w, vertical: 7.5.h), |
|
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
|
horizontal: 32.w, vertical: 7.5.h), |
|
|
|
|
child: Row( |
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
|
|
|
mainAxisAlignment: |
|
|
|
|
MainAxisAlignment.spaceBetween, |
|
|
|
|
crossAxisAlignment: |
|
|
|
|
CrossAxisAlignment.center, |
|
|
|
|
children: [ |
|
|
|
|
GestureDetector( |
|
|
|
|
onTap: () { |
|
|
|
|
setState(() { |
|
|
|
|
this.copy(messages[position].content); |
|
|
|
|
this.copy(messages[position] |
|
|
|
|
.content); |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
@ -736,15 +751,19 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
style: TextStyle( |
|
|
|
|
color: Colors.white, |
|
|
|
|
fontSize: 12.sp, |
|
|
|
|
fontWeight: MyFontWeight.regular, |
|
|
|
|
fontWeight: |
|
|
|
|
MyFontWeight.regular, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
GestureDetector( |
|
|
|
|
onTap: () async{ |
|
|
|
|
await hxDatabase.deleteByMsgId(messages[position].id.toString()); |
|
|
|
|
onTap: () async { |
|
|
|
|
await hxDatabase.deleteByMsgId( |
|
|
|
|
messages[position] |
|
|
|
|
.id |
|
|
|
|
.toString()); |
|
|
|
|
messages.removeAt(position); |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
}, |
|
|
|
@ -764,7 +783,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
style: TextStyle( |
|
|
|
|
color: Colors.white, |
|
|
|
|
fontSize: 12.sp, |
|
|
|
|
fontWeight: MyFontWeight.regular, |
|
|
|
|
fontWeight: |
|
|
|
|
MyFontWeight.regular, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
@ -861,8 +881,10 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
alignment: Alignment.centerRight, |
|
|
|
|
child: InkWell( |
|
|
|
|
onLongPress: () { |
|
|
|
|
RenderBox renderBox = _buttonKey.currentContext.findRenderObject() as RenderBox; |
|
|
|
|
Offset buttonPosition = renderBox.localToGlobal(Offset.zero); |
|
|
|
|
RenderBox renderBox = _buttonKey.currentContext |
|
|
|
|
.findRenderObject() as RenderBox; |
|
|
|
|
Offset buttonPosition = |
|
|
|
|
renderBox.localToGlobal(Offset.zero); |
|
|
|
|
Size buttonSize = renderBox.size; |
|
|
|
|
|
|
|
|
|
showMenu( |
|
|
|
@ -871,16 +893,18 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
elevation: 0, |
|
|
|
|
color: Colors.transparent, |
|
|
|
|
position: RelativeRect.fromLTRB( |
|
|
|
|
buttonPosition.dx + (buttonSize.width - 180.w) / 2, // 居中对齐 |
|
|
|
|
buttonPosition.dx + |
|
|
|
|
(buttonSize.width - 180.w) / 2, // 居中对齐 |
|
|
|
|
buttonPosition.dy - 68, |
|
|
|
|
buttonPosition.dx + buttonSize.width, |
|
|
|
|
buttonPosition.dy |
|
|
|
|
), /// 设置弹出菜单的显示位置 |
|
|
|
|
buttonPosition.dy), |
|
|
|
|
|
|
|
|
|
/// 设置弹出菜单的显示位置 |
|
|
|
|
items: [ |
|
|
|
|
PopupMenuItem( |
|
|
|
|
value: 1, |
|
|
|
|
padding: EdgeInsets.zero, |
|
|
|
|
child:Stack( |
|
|
|
|
child: Stack( |
|
|
|
|
alignment: Alignment.bottomCenter, |
|
|
|
|
children: [ |
|
|
|
|
Container( |
|
|
|
@ -889,18 +913,23 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
width: 180.w, |
|
|
|
|
decoration: BoxDecoration( |
|
|
|
|
color: Color(0xFF2A2A2A), |
|
|
|
|
borderRadius: BorderRadius.circular(6), |
|
|
|
|
borderRadius: |
|
|
|
|
BorderRadius.circular(6), |
|
|
|
|
), |
|
|
|
|
padding: |
|
|
|
|
EdgeInsets.symmetric(horizontal: 32.w, vertical: 7.5.h), |
|
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
|
horizontal: 32.w, |
|
|
|
|
vertical: 7.5.h), |
|
|
|
|
child: Row( |
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
|
|
|
mainAxisAlignment: |
|
|
|
|
MainAxisAlignment.spaceBetween, |
|
|
|
|
crossAxisAlignment: |
|
|
|
|
CrossAxisAlignment.center, |
|
|
|
|
children: [ |
|
|
|
|
GestureDetector( |
|
|
|
|
onTap: () { |
|
|
|
|
setState(() { |
|
|
|
|
this.copy(messages[position].content); |
|
|
|
|
this.copy(messages[position] |
|
|
|
|
.content); |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
@ -916,19 +945,25 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
), |
|
|
|
|
Text( |
|
|
|
|
"复制", |
|
|
|
|
textAlign: TextAlign.center, |
|
|
|
|
textAlign: |
|
|
|
|
TextAlign.center, |
|
|
|
|
style: TextStyle( |
|
|
|
|
color: Colors.white, |
|
|
|
|
fontSize: 12.sp, |
|
|
|
|
fontWeight: MyFontWeight.regular, |
|
|
|
|
fontWeight: MyFontWeight |
|
|
|
|
.regular, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
GestureDetector( |
|
|
|
|
onTap: () async{ |
|
|
|
|
await hxDatabase.deleteByMsgId(messages[position].id.toString()); |
|
|
|
|
onTap: () async { |
|
|
|
|
await hxDatabase |
|
|
|
|
.deleteByMsgId( |
|
|
|
|
messages[position] |
|
|
|
|
.id |
|
|
|
|
.toString()); |
|
|
|
|
messages.removeAt(position); |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
}, |
|
|
|
@ -944,11 +979,13 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
), |
|
|
|
|
Text( |
|
|
|
|
S.of(context).shanchu, |
|
|
|
|
textAlign: TextAlign.center, |
|
|
|
|
textAlign: |
|
|
|
|
TextAlign.center, |
|
|
|
|
style: TextStyle( |
|
|
|
|
color: Colors.white, |
|
|
|
|
fontSize: 12.sp, |
|
|
|
|
fontWeight: MyFontWeight.regular, |
|
|
|
|
fontWeight: MyFontWeight |
|
|
|
|
.regular, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
@ -1050,11 +1087,13 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
onLongPress: () { |
|
|
|
|
setState(() {}); |
|
|
|
|
}, |
|
|
|
|
onTap:(){}, |
|
|
|
|
onTap: () {}, |
|
|
|
|
child: FutureBuilder( |
|
|
|
|
future: fetchImageSize(messages[position]), |
|
|
|
|
builder: (BuildContext context, AsyncSnapshot snapshot) { |
|
|
|
|
if (snapshot.connectionState == ConnectionState.waiting || snapshot.hasError) { |
|
|
|
|
if (snapshot.connectionState == |
|
|
|
|
ConnectionState.waiting || |
|
|
|
|
snapshot.hasError) { |
|
|
|
|
return Image.file( |
|
|
|
|
File(messages[position].attach), |
|
|
|
|
width: 180.w, |
|
|
|
@ -1088,11 +1127,13 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
onLongPress: () { |
|
|
|
|
setState(() {}); |
|
|
|
|
}, |
|
|
|
|
onTap:(){}, |
|
|
|
|
onTap: () {}, |
|
|
|
|
child: FutureBuilder( |
|
|
|
|
future: fetchImageSize(messages[position]), |
|
|
|
|
builder: (BuildContext context, AsyncSnapshot snapshot) { |
|
|
|
|
if (snapshot.connectionState == ConnectionState.waiting || snapshot.hasError) { |
|
|
|
|
if (snapshot.connectionState == |
|
|
|
|
ConnectionState.waiting || |
|
|
|
|
snapshot.hasError) { |
|
|
|
|
return Image.file( |
|
|
|
|
File(messages[position].attach), |
|
|
|
|
width: 180.w, |
|
|
|
@ -1168,9 +1209,12 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Completer<Size> completer = Completer(); |
|
|
|
|
Image.file(file).image.resolve(ImageConfiguration()) |
|
|
|
|
Image.file(file) |
|
|
|
|
.image |
|
|
|
|
.resolve(ImageConfiguration()) |
|
|
|
|
.addListener(ImageStreamListener((image, synchronousCall) { |
|
|
|
|
size = Size((image.image.width ?? 0).toDouble(), (image.image.height ?? 0).toDouble()); |
|
|
|
|
size = Size((image.image.width ?? 0).toDouble(), |
|
|
|
|
(image.image.height ?? 0).toDouble()); |
|
|
|
|
size = resizeImage(size); |
|
|
|
|
Map<String, double> sizeMap = { |
|
|
|
|
"width": size.width, |
|
|
|
@ -1229,7 +1273,8 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
if (commentText.trim() == "") { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
socketClient.sendMessage(_toUser.mid, commentText) |
|
|
|
|
socketClient |
|
|
|
|
.sendMessage(_toUser.mid, commentText) |
|
|
|
|
.then((value) { |
|
|
|
|
Message message = value; |
|
|
|
|
messages.insert(0, message); |
|
|
|
@ -1448,5 +1493,4 @@ class _ChatDetailsPage extends State<ChatDetailsPage>
|
|
|
|
|
print(tex); |
|
|
|
|
Clipboard.setData(ClipboardData(text: tex)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|