|
|
|
@ -1,3 +1,5 @@
@@ -1,3 +1,5 @@
|
|
|
|
|
import 'dart:ui' show ImageFilter; |
|
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
|
import 'package:provider/provider.dart'; |
|
|
|
|
|
|
|
|
@ -20,19 +22,9 @@ import 'package:esse/apps/chat/provider.dart';
@@ -20,19 +22,9 @@ import 'package:esse/apps/chat/provider.dart';
|
|
|
|
|
import 'package:esse/apps/group_chat/models.dart'; |
|
|
|
|
import 'package:esse/apps/group_chat/provider.dart'; |
|
|
|
|
|
|
|
|
|
class GroupChatPage extends StatelessWidget { |
|
|
|
|
const GroupChatPage({Key key}) : super(key: key); |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
Widget build(BuildContext context) { |
|
|
|
|
return Scaffold( |
|
|
|
|
body: SafeArea( |
|
|
|
|
child: GroupChatDetail(), |
|
|
|
|
)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class GroupChatDetail extends StatefulWidget { |
|
|
|
|
static GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); |
|
|
|
|
|
|
|
|
|
const GroupChatDetail({Key key}) : super(key: key); |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
@ -200,6 +192,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -200,6 +192,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
final isDesktop = isDisplayDesktop(context); |
|
|
|
|
|
|
|
|
|
final provider = context.watch<GroupChatProvider>(); |
|
|
|
|
final members = provider.activedMembers; |
|
|
|
|
final recentMessages = provider.activedMessages; |
|
|
|
|
final recentMessageKeys = recentMessages.keys.toList().reversed.toList(); |
|
|
|
|
|
|
|
|
@ -219,7 +212,12 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -219,7 +212,12 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
final meName = accountProvider.activedAccount.name; |
|
|
|
|
final isOnline = session.isActive(); |
|
|
|
|
|
|
|
|
|
return Column( |
|
|
|
|
return Scaffold( |
|
|
|
|
key: GroupChatDetail._scaffoldKey, |
|
|
|
|
endDrawer: _MemberDrawerWidget(title: lang.members), |
|
|
|
|
drawerScrimColor: color.background, |
|
|
|
|
body: SafeArea( |
|
|
|
|
child: Column( |
|
|
|
|
children: [ |
|
|
|
|
Container( |
|
|
|
|
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), |
|
|
|
@ -272,6 +270,15 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -272,6 +270,15 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
color: Color(0x26ADB0BB))), |
|
|
|
|
), |
|
|
|
|
SizedBox(width: 20.0), |
|
|
|
|
GestureDetector( |
|
|
|
|
onTap: () { |
|
|
|
|
GroupChatDetail._scaffoldKey.currentState.openEndDrawer(); |
|
|
|
|
}, |
|
|
|
|
child: Container( |
|
|
|
|
width: 20.0, |
|
|
|
|
child: Icon(Icons.group_rounded, color: color.primary)), |
|
|
|
|
), |
|
|
|
|
SizedBox(width: 20.0), |
|
|
|
|
PopupMenuButton<int>( |
|
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
|
borderRadius: BorderRadius.circular(15) |
|
|
|
@ -279,69 +286,38 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -279,69 +286,38 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
color: const Color(0xFFEDEDED), |
|
|
|
|
child: Icon(Icons.more_vert_rounded, color: color.primary), |
|
|
|
|
onSelected: (int value) { |
|
|
|
|
if (value == 2) { |
|
|
|
|
showShadowDialog( |
|
|
|
|
context, |
|
|
|
|
Icons.info, |
|
|
|
|
lang.groupChat, |
|
|
|
|
if (value == 1) { |
|
|
|
|
showShadowDialog(context, Icons.info, lang.groupChat, |
|
|
|
|
UserInfo( |
|
|
|
|
id: 'EG' + this.group.gid.toUpperCase(), |
|
|
|
|
name: this.group.name, |
|
|
|
|
addr: '0x' + this.group.addr) |
|
|
|
|
); |
|
|
|
|
} else if (value == 3) { |
|
|
|
|
final memberWidgets = provider.activedMembers.values.map((m) { |
|
|
|
|
return MemberAvatar( |
|
|
|
|
member: m, title: lang.members, |
|
|
|
|
isGroupManager: isGroupManager, isGroupOwner: isGroupOwner, |
|
|
|
|
); |
|
|
|
|
}).toList(); |
|
|
|
|
|
|
|
|
|
showShadowDialog( |
|
|
|
|
context, |
|
|
|
|
Icons.group_rounded, |
|
|
|
|
lang.members, |
|
|
|
|
Wrap( |
|
|
|
|
spacing: 10.0, |
|
|
|
|
runSpacing: 10.0, |
|
|
|
|
children: memberWidgets, |
|
|
|
|
), |
|
|
|
|
10.0, //height |
|
|
|
|
addr: '0x' + this.group.addr |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
} else if (value == 4) { |
|
|
|
|
} else if (value == 2) { |
|
|
|
|
showDialog( |
|
|
|
|
context: context, |
|
|
|
|
builder: (BuildContext context) { |
|
|
|
|
context: context, builder: (BuildContext context) { |
|
|
|
|
return AlertDialog( |
|
|
|
|
title: Text(lang.unfriend), |
|
|
|
|
title: Text(lang.exit), |
|
|
|
|
content: Text(this.group.name, |
|
|
|
|
style: TextStyle(color: color.primary)), |
|
|
|
|
actions: [ |
|
|
|
|
TextButton( |
|
|
|
|
child: Text(lang.cancel), |
|
|
|
|
TextButton(child: Text(lang.cancel), |
|
|
|
|
onPressed: () => Navigator.pop(context), |
|
|
|
|
), |
|
|
|
|
TextButton( |
|
|
|
|
child: Text(lang.ok), |
|
|
|
|
TextButton(child: Text(lang.ok), |
|
|
|
|
onPressed: () { |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
//Provider.of<GroupChatProvider>(context, listen: false).groupClose(this.group.id); |
|
|
|
|
if (!isDesktop) { |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
} |
|
|
|
|
provider.close(this.group.id); |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
] |
|
|
|
|
); |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
} else if (value == 5) { |
|
|
|
|
// Provider.of<GroupChatProvider>(context, listen: false).requestCreate( |
|
|
|
|
// Request(this.group.gid, this.group.addr, this.group.name, lang.fromContactCard(meName))); |
|
|
|
|
} else if (value == 6) { |
|
|
|
|
} else if (value == 3) { |
|
|
|
|
showDialog( |
|
|
|
|
context: context, |
|
|
|
|
builder: (BuildContext context) { |
|
|
|
|
context: context, builder: (BuildContext context) { |
|
|
|
|
return AlertDialog( |
|
|
|
|
title: Text(lang.delete + ' ' + lang.groupChat), |
|
|
|
|
content: Text(this.group.name, |
|
|
|
@ -355,28 +331,24 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -355,28 +331,24 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
child: Text(lang.ok), |
|
|
|
|
onPressed: () { |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
//Provider.of<GroupChatProvider>(context, listen: false).groupDelete(this.group.id); |
|
|
|
|
if (!isDesktop) { |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
} |
|
|
|
|
provider.delete(this.group.id); |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
] |
|
|
|
|
); |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
} else if (value == 4) { |
|
|
|
|
provider.reAdd(this.group.id); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
itemBuilder: (context) { |
|
|
|
|
return <PopupMenuEntry<int>>[ |
|
|
|
|
_menuItem(Color(0xFF6174FF), 2, Icons.qr_code_rounded, lang.info), |
|
|
|
|
_menuItem(Color(0xFF6174FF), 3, Icons.group_rounded, lang.members), |
|
|
|
|
// _menuItem(color.primary, 3, Icons.turned_in_rounded, lang.remark), |
|
|
|
|
// this.group.isClosed |
|
|
|
|
// ? _menuItem(Color(0xFF6174FF), 5, Icons.send_rounded, lang.addGroup) |
|
|
|
|
// : _menuItem(Color(0xFF6174FF), 4, Icons.block_rounded, lang.unfriend), |
|
|
|
|
_menuItem(Colors.orange, 6, Icons.block_rounded, lang.exit), |
|
|
|
|
_menuItem(Colors.red, 6, Icons.delete_rounded, lang.delete), |
|
|
|
|
_menuItem(Color(0xFF6174FF), 1, Icons.qr_code_rounded, lang.info), |
|
|
|
|
this.group.isClosed |
|
|
|
|
? _menuItem(Color(0xFF6174FF), 4, Icons.send_rounded, lang.addGroup) |
|
|
|
|
: _menuItem(Colors.orange, 2, Icons.block_rounded, lang.exit), |
|
|
|
|
_menuItem(Colors.red, 3, Icons.delete_rounded, lang.delete), |
|
|
|
|
]; |
|
|
|
|
}, |
|
|
|
|
) |
|
|
|
@ -389,10 +361,15 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -389,10 +361,15 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
padding: EdgeInsets.symmetric(horizontal: 20.0), |
|
|
|
|
itemCount: recentMessageKeys.length, |
|
|
|
|
reverse: true, |
|
|
|
|
itemBuilder: (BuildContext context, index) => ChatMessage( |
|
|
|
|
name: this.group.name, |
|
|
|
|
message: recentMessages[recentMessageKeys[index]], |
|
|
|
|
) |
|
|
|
|
itemBuilder: (BuildContext context, index) { |
|
|
|
|
final message = recentMessages[recentMessageKeys[index]]; |
|
|
|
|
final member = members[message.fid]; |
|
|
|
|
return ChatMessage( |
|
|
|
|
avatar: member.showAvatar(), |
|
|
|
|
name: member.name, |
|
|
|
|
message: message, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
)), |
|
|
|
|
if (!this.group.isClosed) |
|
|
|
|
Container( |
|
|
|
@ -550,6 +527,8 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
@@ -550,6 +527,8 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
|
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
], |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -607,39 +586,62 @@ Widget _menuItem(Color color, int value, IconData icon, String text) {
@@ -607,39 +586,62 @@ Widget _menuItem(Color color, int value, IconData icon, String text) {
|
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class MemberAvatar extends StatelessWidget { |
|
|
|
|
class _MemberDrawerWidget extends StatelessWidget { |
|
|
|
|
final String title; |
|
|
|
|
final Member member; |
|
|
|
|
final bool isGroupManager; |
|
|
|
|
final bool isGroupOwner; |
|
|
|
|
|
|
|
|
|
const MemberAvatar({Key key, this.title, this.member, this.isGroupManager, this.isGroupOwner}) : super(key: key); |
|
|
|
|
const _MemberDrawerWidget({Key key, this.title}) : super(key: key); |
|
|
|
|
|
|
|
|
|
Widget _item(context, Member member, bool isOwner, Color color) { |
|
|
|
|
return ListTile( |
|
|
|
|
leading: member.showAvatar(), |
|
|
|
|
title: Text(member.name, textAlign: TextAlign.left, style: TextStyle(fontSize: 16.0)), |
|
|
|
|
trailing: Text(isOwner ? 'Owner' : (member.isManager ? 'Manager' : ''), |
|
|
|
|
style: TextStyle(color: color)), |
|
|
|
|
onTap: () { |
|
|
|
|
Navigator.pop(context); |
|
|
|
|
showShadowDialog(context, Icons.group_rounded, title, |
|
|
|
|
MemberDetail(member: member, isGroupOwner: isOwner, isGroupManager: member.isManager), |
|
|
|
|
10.0, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
Widget build(BuildContext context) { |
|
|
|
|
return InkWell( |
|
|
|
|
onTap: () => showShadowDialog( |
|
|
|
|
context, |
|
|
|
|
Icons.group_rounded, |
|
|
|
|
title, |
|
|
|
|
MemberDetail(member: member, isGroupOwner: isGroupOwner, isGroupManager: isGroupManager), |
|
|
|
|
10.0, |
|
|
|
|
), |
|
|
|
|
hoverColor: Colors.transparent, |
|
|
|
|
final color = Theme.of(context).colorScheme; |
|
|
|
|
final lang = AppLocalizations.of(context); |
|
|
|
|
final isLight = color.brightness == Brightness.light; |
|
|
|
|
final isDesktop = isDisplayDesktop(context); |
|
|
|
|
|
|
|
|
|
final provider = context.watch<GroupChatProvider>(); |
|
|
|
|
final members = provider.activedMembers; |
|
|
|
|
final allKeys = provider.activedMemberOrder; |
|
|
|
|
|
|
|
|
|
return Drawer( |
|
|
|
|
child: BackdropFilter( |
|
|
|
|
filter: ImageFilter.blur(sigmaX: 4.0, sigmaY: 4.0), |
|
|
|
|
child: SafeArea( |
|
|
|
|
child: Container( |
|
|
|
|
decoration: BoxDecoration(color: color.surface), |
|
|
|
|
padding: const EdgeInsets.symmetric(vertical: 20.0), |
|
|
|
|
child: Column( |
|
|
|
|
children: [ |
|
|
|
|
member.showAvatar(), |
|
|
|
|
SizedBox(height: 4.0), |
|
|
|
|
Container( |
|
|
|
|
alignment: Alignment.center, |
|
|
|
|
width: 60.0, |
|
|
|
|
child: Text( |
|
|
|
|
member.name, |
|
|
|
|
maxLines: 1, |
|
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
|
style: TextStyle(fontSize: 14.0)), |
|
|
|
|
Text(lang.members, style: Theme.of(context).textTheme.title), |
|
|
|
|
const SizedBox(height: 10.0), |
|
|
|
|
const Divider(height: 1.0, color: Color(0x40ADB0BB)), |
|
|
|
|
const SizedBox(height: 10.0), |
|
|
|
|
Expanded( |
|
|
|
|
child: ListView.builder( |
|
|
|
|
itemCount: allKeys.length, |
|
|
|
|
itemBuilder: (BuildContext ctx, int index) => _item( |
|
|
|
|
context, members[allKeys[index]], index == 0, color.primary |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
] |
|
|
|
|
), |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
@ -685,7 +687,7 @@ class _MemberDetailState extends State<MemberDetail> {
@@ -685,7 +687,7 @@ class _MemberDetailState extends State<MemberDetail> {
|
|
|
|
|
return Column( |
|
|
|
|
mainAxisSize: MainAxisSize.max, |
|
|
|
|
children: [ |
|
|
|
|
widget.member.showAvatar(width: 100.0), |
|
|
|
|
widget.member.showAvatar(width: 100.0, colorSurface: true), |
|
|
|
|
const SizedBox(height: 10.0), |
|
|
|
|
Text(widget.member.name), |
|
|
|
|
const SizedBox(height: 10.0), |
|
|
|
|