From dbf2c722f321c50b923109b70e5969e23360abb4 Mon Sep 17 00:00:00 2001 From: Sun Date: Tue, 1 Jun 2021 14:47:02 +0800 Subject: [PATCH] add group chat card UI and add session type show --- lib/apps/chat/detail.dart | 6 ++- lib/apps/group_chat/add.dart | 12 +++-- lib/apps/group_chat/detail.dart | 14 +++-- lib/apps/group_chat/models.dart | 11 ++++ lib/apps/group_chat/provider.dart | 22 -------- lib/apps/primitives.dart | 35 +++++++++++++ lib/l10n/localizations_en.dart | 2 +- lib/l10n/localizations_zh.dart | 2 +- lib/session.dart | 8 +-- lib/widgets/chat_message.dart | 82 ++++++++++++++++++++++++------ lib/widgets/default_home_show.dart | 24 ++++++--- lib/widgets/user_info.dart | 46 +++++++++++++++-- 12 files changed, 197 insertions(+), 67 deletions(-) diff --git a/lib/apps/chat/detail.dart b/lib/apps/chat/detail.dart index 5a78d96..c7bad58 100644 --- a/lib/apps/chat/detail.dart +++ b/lib/apps/chat/detail.dart @@ -276,7 +276,11 @@ class _ChatDetailState extends State { app: 'add-friend', id: 'EH' + friend.gid.toUpperCase(), name: friend.name, - addr: '0x' + friend.addr) + addr: '0x' + friend.addr, + title: lang.qrFriend, + remark: friend.remark, + ), + 0.0, ); } else if (value == 3) { print('TODO remark'); diff --git a/lib/apps/group_chat/add.dart b/lib/apps/group_chat/add.dart index 4a55c3b..d0486c5 100644 --- a/lib/apps/group_chat/add.dart +++ b/lib/apps/group_chat/add.dart @@ -14,6 +14,7 @@ import 'package:esse/widgets/shadow_button.dart'; import 'package:esse/widgets/shadow_dialog.dart'; import 'package:esse/widgets/qr_scan.dart'; import 'package:esse/global.dart'; +import 'package:esse/rpc.dart'; import 'package:esse/provider.dart'; import 'package:esse/apps/group_chat/models.dart'; @@ -113,7 +114,7 @@ class _GroupAddPageState extends State { if (addr.substring(0, 2) == '0x') { addr = addr.substring(2); } - context.read().check(addr); + rpc.send('group-chat-check', [addr]); } _scanCallback(bool isOk, String app, List params) { @@ -160,7 +161,7 @@ class _GroupAddPageState extends State { } final name = _createNameController.text.trim(); final bio = _createBioController.text.trim(); - context.read().create(_groupType, _myName, addr, name, bio, _groupNeedAgree); + rpc.send('group-chat-create', [_groupType, _myName, addr, name, bio, _groupNeedAgree]); setState(() { _createNameController.text = ''; _createBioController.text = ''; @@ -195,8 +196,9 @@ class _GroupAddPageState extends State { _createKeyFocus.addListener(() { setState(() {}); }); + + rpc.send('group-chat-request-list', [false]); new Future.delayed(Duration.zero, () { - context.read().requestList(false); _myName = context.read().activedAccount.name; }); } @@ -301,7 +303,7 @@ class _GroupAddPageState extends State { if (_requestsLoadMore) TextButton( onPressed: () { - provider.requestList(true); + rpc.send('group-chat-request-list', [true]); setState(() { _requestsLoadMore = false; }); @@ -799,7 +801,7 @@ class _CreateItem extends StatelessWidget { style: TextStyle(color: Color(0xFFADB0BB), fontSize: 14.0), )) : InkWell( - onTap: () => context.read().reSend(group.id, name), + onTap: () => rpc.send('group-chat-resend', [group.id, name]), hoverColor: Colors.transparent, child: Container( height: 35.0, diff --git a/lib/apps/group_chat/detail.dart b/lib/apps/group_chat/detail.dart index ca90ba8..803dcad 100644 --- a/lib/apps/group_chat/detail.dart +++ b/lib/apps/group_chat/detail.dart @@ -216,7 +216,7 @@ class _GroupChatDetailState extends State { return Scaffold( key: GroupChatDetail._scaffoldKey, - endDrawer: _MemberDrawerWidget(gid: this.group.gid, title: lang.members), + endDrawer: _MemberDrawerWidget(id: this.group.id, gid: this.group.gid, title: lang.members), drawerScrimColor: color.background, body: SafeArea( child: Column( @@ -294,8 +294,11 @@ class _GroupChatDetailState extends State { app: 'add-group', id: 'EG' + this.group.gid.toUpperCase(), name: this.group.name, - addr: '0x' + this.group.addr - ) + addr: '0x' + this.group.addr, + title: this.group.type.lang(lang) + ' ' + lang.groupChat, + bio: this.group.bio, + ), + 0.0, ); } else if (value == 2) { showDialog( @@ -590,9 +593,10 @@ Widget _menuItem(Color color, int value, IconData icon, String text) { } class _MemberDrawerWidget extends StatelessWidget { + final int id; final String gid; final String title; - const _MemberDrawerWidget({Key key, this.gid, this.title}) : super(key: key); + const _MemberDrawerWidget({Key key, this.id, this.gid, this.title}) : super(key: key); Widget _meItem(Member member, bool meOwner, bool meManager, Color color, lang) { return Container( @@ -630,7 +634,7 @@ class _MemberDrawerWidget extends StatelessWidget { } _action(List ids) { - rpc.send('group-chat-invite', [gid, ids]); + rpc.send('group-chat-invite', [id, gid, ids]); } _invite(context, String title) { diff --git a/lib/apps/group_chat/models.dart b/lib/apps/group_chat/models.dart index 7bcac1d..713bcc1 100644 --- a/lib/apps/group_chat/models.dart +++ b/lib/apps/group_chat/models.dart @@ -35,6 +35,17 @@ extension GroupTypeExtension on GroupType { } } + String lang(AppLocalizations lang) { + switch (this) { + case GroupType.Encrypted: + return lang.groupTypeEncrypted; + case GroupType.Private: + return lang.groupTypePrivate; + case GroupType.Open: + return lang.groupTypeOpen; + } + } + static GroupType fromInt(int s) { switch (s) { case 0: diff --git a/lib/apps/group_chat/provider.dart b/lib/apps/group_chat/provider.dart index 930ee28..ff47a71 100644 --- a/lib/apps/group_chat/provider.dart +++ b/lib/apps/group_chat/provider.dart @@ -118,18 +118,6 @@ class GroupChatProvider extends ChangeNotifier { this.activedMembers.clear(); } - check(String addr) { - rpc.send('group-chat-check', [addr]); - } - - create(int gtype, String myName, String addr, String name, String bio, bool needAgree) { - rpc.send('group-chat-create', [gtype, myName, addr, name, bio, needAgree]); - } - - reSend(int id, String myName) { - rpc.send('group-chat-resend', [id, myName]); - } - join(GroupType gtype, String gid, String gaddr, String name, String remark, [String proof = '', String key = '']) { rpc.send('group-chat-join', [gtype.toInt(), gid, gaddr, name, remark, proof, key]); } @@ -147,10 +135,6 @@ class GroupChatProvider extends ChangeNotifier { rpc.send('group-chat-message-create', [gid, mtype.toInt(), content]); } - requestList(bool all) { - rpc.send('group-chat-request-list', [all]); - } - close(int id) { // rpc.send('group-chat-close', [id]); } @@ -163,12 +147,6 @@ class GroupChatProvider extends ChangeNotifier { // rpc.send('group-chat-readd', [id]); } - invite(String gid, List ids) { - print(gid); - print(ids); - rpc.send('group-chat-invite', [ids]); - } - memberUpdate(int id, bool isBlock) { rpc.send('group-chat-member-update', [id, isBlock]); } diff --git a/lib/apps/primitives.dart b/lib/apps/primitives.dart index 610de8a..5696da0 100644 --- a/lib/apps/primitives.dart +++ b/lib/apps/primitives.dart @@ -1,6 +1,7 @@ import 'package:esse/utils/relative_time.dart'; import 'package:esse/widgets/avatar.dart'; import 'package:esse/global.dart'; +import 'package:esse/apps/group_chat/models.dart' show GroupType, GroupTypeExtension; enum MessageType { String, @@ -94,6 +95,40 @@ class BaseMessage { return [name, did, addr, Global.avatarPath + did + '.png']; } + List showInvite() { + var type = GroupType.Open; + var gid = ''; + var addr = ''; + var name = ''; + var proof = ''; + + final i_type = this.content.indexOf(';;'); + if (i_type > 0) { + type = GroupTypeExtension.fromInt(int.parse(this.content.substring(0, i_type))); + } + + final raw_0 = this.content.substring(i_type + 2); + final i_gid = raw_0.indexOf(';;'); + if (i_gid > 0) { + gid = raw_0.substring(0, i_gid); + } + + final raw_1 = raw_0.substring(i_gid + 2); + final i_addr = raw_1.indexOf(';;'); + if (i_addr > 0) { + addr = raw_1.substring(0, i_addr); + } + + final raw_2 = raw_1.substring(i_addr + 2); + final i_name = raw_2.indexOf(';;'); + if (i_name > 0) { + name = raw_2.substring(0, i_name).replaceAll('-;', ';'); + } + proof = raw_2.substring(i_name + 2); + + return [type, gid, addr, name, proof]; + } + static String rawRecordName(int time, String name) { return time.toString() + '-' + name; } diff --git a/lib/l10n/localizations_en.dart b/lib/l10n/localizations_en.dart index e969b00..e46c3c5 100644 --- a/lib/l10n/localizations_en.dart +++ b/lib/l10n/localizations_en.dart @@ -155,7 +155,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get myQrcode => 'My QRCode'; @override - String get qrFriend => 'Scan for Add'; + String get qrFriend => 'Scan for Add Friend'; @override String get friendInfo => 'Friend Info'; @override diff --git a/lib/l10n/localizations_zh.dart b/lib/l10n/localizations_zh.dart index 2f65be3..a826be4 100644 --- a/lib/l10n/localizations_zh.dart +++ b/lib/l10n/localizations_zh.dart @@ -155,7 +155,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String get myQrcode => '我的二维码'; @override - String get qrFriend => '扫二维码添加'; + String get qrFriend => '扫二维码添加好友'; @override String get friendInfo => '好友信息'; @override diff --git a/lib/session.dart b/lib/session.dart index 1f64936..83937ee 100644 --- a/lib/session.dart +++ b/lib/session.dart @@ -96,15 +96,15 @@ class Session { List parse(AppLocalizations lang) { switch (this.type) { case SessionType.Chat: - return [showAvatar(), this.name, this.lastContent, this.lastTime.toString()]; + return [showAvatar(), this.name, this.lastContent, this.lastTime.toString(), null]; case SessionType.Group: - return [showAvatar(), this.name, this.lastContent, this.lastTime.toString()]; + return [showAvatar(), this.name, this.lastContent, this.lastTime.toString(), Icons.groups]; case SessionType.Assistant: final params = Session.innerService(InnerService.Assistant, lang); - return [params[0], params[1], params[2], '']; + return [params[0], params[1], params[2], '', Icons.campaign]; case SessionType.Files: final params = Session.innerService(InnerService.Files, lang); - return [params[0], params[1], params[2], '']; + return [params[0], params[1], params[2], '', Icons.campaign]; } } diff --git a/lib/widgets/chat_message.dart b/lib/widgets/chat_message.dart index a82b90b..9bc41e4 100644 --- a/lib/widgets/chat_message.dart +++ b/lib/widgets/chat_message.dart @@ -309,23 +309,73 @@ class ChatMessage extends StatelessWidget { } Widget _showInvite(context, lang, color) { - // contact [name, gid, addr, avatar] - //final infos = message.showContact(); - //final gid = 'EG' + infos[1].toUpperCase(); + // contact [type, gid, addr, name, proof] + final infos = message.showInvite(); + print(infos); + final gid = 'EG' + infos[1].toUpperCase(); - final width = MediaQuery.of(context).size.width * 0.6; - // text - return Container( - constraints: BoxConstraints(minWidth: 50, maxWidth: width), - padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 14.0), - decoration: BoxDecoration( - color: message.isMe ? Color(0xFF6174FF) : color.primaryVariant, - borderRadius: BorderRadius.circular(15.0), - ), - child: Text(message.content, - style: TextStyle( - color: message.isMe ? Colors.white : Color(0xFF1C1939), - fontSize: 14.0))); + if (infos != null) { + return GestureDetector( + onTap: () => showShadowDialog( + context, + Icons.groups_rounded, + lang.groupChat, + Text(infos[3]), + ), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), + width: 200.0, + decoration: BoxDecoration( + color: const Color(0x40ADB0BB), + borderRadius: BorderRadius.circular(15.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 40.0, + height: 40.0, + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: color.surface, + borderRadius: BorderRadius.circular(15.0), + ), + child: Icon(Icons.groups_rounded, color: color.primary), + ), + Container( + width: 135.0, + padding: const EdgeInsets.only(left: 10.0), + child: Column(children: [ + Text(infos[3], maxLines: 1, overflow: TextOverflow.ellipsis, + style: TextStyle(color: color.onPrimary, fontSize: 16.0)), + const SizedBox(height: 5.0), + Text(betterPrint(gid), style: TextStyle(color: Colors.grey, fontSize: 12.0)), + ])), + ]), + const SizedBox(height: 5.0), + const Divider(height: 1.0, color: Color(0x40ADB0BB)), + const SizedBox(height: 3.0), + Text(lang.groupChat, style: TextStyle(color: Colors.grey, fontSize: 10.0)), + ]))); + } else { + final width = MediaQuery.of(context).size.width * 0.6; + + // text + return Container( + constraints: BoxConstraints(minWidth: 50, maxWidth: width), + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 14.0), + decoration: BoxDecoration( + color: message.isMe ? Color(0xFF6174FF) : color.primaryVariant, + borderRadius: BorderRadius.circular(15.0), + ), + child: Text(message.content, + style: TextStyle( + color: message.isMe ? Colors.white : Color(0xFF1C1939), + fontSize: 14.0)) + ); + } } Widget _infoListTooltip(icon, color, text) { diff --git a/lib/widgets/default_home_show.dart b/lib/widgets/default_home_show.dart index ae57b98..63cfdaa 100644 --- a/lib/widgets/default_home_show.dart +++ b/lib/widgets/default_home_show.dart @@ -107,19 +107,29 @@ class _SessionWidget extends StatelessWidget { ), Container( margin: const EdgeInsets.only(left: 15.0, right: 20.0), - child: Text(params[3], - style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0), - ), + child: Text(params[3], style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0)), ) ]), const SizedBox(height: 4.0), Row( children: [ Expanded( - child: Text(params[2], - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0)), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (params[4] != null) + Container( + margin: const EdgeInsets.only(right: 6.0), + child: Icon(params[4], size: 16.0, color: Color(0xFFADB0BB)), + ), + Expanded( + child: Text(params[2], + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0)), + ) + ] + ), ), Container(width: 8.0, height: 8.0, margin: const EdgeInsets.only(left: 15.0, right: 20.0), diff --git a/lib/widgets/user_info.dart b/lib/widgets/user_info.dart index 7644a8f..d9555ac 100644 --- a/lib/widgets/user_info.dart +++ b/lib/widgets/user_info.dart @@ -12,9 +12,12 @@ class UserInfo extends StatefulWidget { final String id; final String name; final String addr; + final String title; + final String remark; + final String bio; Map qrInfo; - UserInfo({Key key, this.id, this.name, this.addr, this.app}) : super(key: key) { + UserInfo({Key key, this.id, this.name, this.addr, this.app, this.title, this.remark, this.bio}) : super(key: key) { this.qrInfo = { "app": this.app, "params": [this.id, this.addr, this.name], @@ -39,7 +42,11 @@ class _UserInfoState extends State { Color addrColor = addrCopy ? color.primary : color.onPrimary; return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ + Text(widget.name, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)), + const SizedBox(height: 10), Container( width: 200.0, padding: const EdgeInsets.all(2.0), @@ -77,9 +84,9 @@ class _UserInfoState extends State { ] ) ), - const SizedBox(height: 20), - Center(child: Text(lang.qrFriend, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold))), - const SizedBox(height: 20), + const SizedBox(height: 8), + Text(widget.title, style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.italic)), + const SizedBox(height: 10), const Divider(height: 1.0, color: Color(0x40ADB0BB)), const SizedBox(height: 20), InkWell( @@ -103,7 +110,7 @@ class _UserInfoState extends State { ), ) ), - const SizedBox(height: 20), + const SizedBox(height: 16), InkWell( onTap: () { Clipboard.setData(ClipboardData(text: widget.addr)); @@ -125,6 +132,35 @@ class _UserInfoState extends State { ), ) ), + if (widget.remark != null) + Container( + width: 250.0, + padding: const EdgeInsets.only(top: 16.0), + child: Row( + children: [ + Icon(Icons.turned_in, size: 20.0, color: color.primary), + const SizedBox(width: 16.0), + Expanded( + child: Center(child: Text(widget.remark, style: TextStyle(fontSize: 14))), + ) + ] + ), + ), + if (widget.bio != null) + Container( + width: 250.0, + padding: const EdgeInsets.only(top: 16.0), + child: Row( + children: [ + Icon(Icons.campaign, size: 20.0, color: color.primary), + const SizedBox(width: 16.0), + Expanded( + child: Center(child: Text(widget.bio, style: TextStyle(fontSize: 14))), + ) + ] + ), + ), + const SizedBox(height: 16), ] ); }