From c8f6ee63ba6a3d226f4a574dfccf7d561b09c767 Mon Sep 17 00:00:00 2001 From: Sun Date: Sat, 29 May 2021 14:40:38 +0800 Subject: [PATCH] update group chat UI --- lib/apps/assistant/page.dart | 454 +++++++++--------- lib/apps/chat/detail.dart | 648 +++++++++++++------------- lib/apps/chat/list.dart | 10 +- lib/apps/group_chat/detail.dart | 718 +++++++++++++++-------------- lib/apps/group_chat/models.dart | 19 +- lib/apps/group_chat/page.dart | 14 +- lib/apps/group_chat/provider.dart | 30 ++ lib/apps/service/models.dart | 45 +- lib/session.dart | 2 + lib/widgets/avatar.dart | 12 +- lib/widgets/chat_message.dart | 89 ++-- lib/widgets/default_home_show.dart | 49 +- 12 files changed, 1049 insertions(+), 1041 deletions(-) diff --git a/lib/apps/assistant/page.dart b/lib/apps/assistant/page.dart index 1f92ed9..358c5b8 100644 --- a/lib/apps/assistant/page.dart +++ b/lib/apps/assistant/page.dart @@ -19,18 +19,6 @@ import 'package:esse/apps/assistant/provider.dart'; import 'package:esse/apps/assistant/message.dart'; import 'package:esse/apps/assistant/answer.dart'; -class AssistantPage extends StatelessWidget { - const AssistantPage({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: AssistantDetail(), - )); - } -} - class AssistantDetail extends StatefulWidget { const AssistantDetail({Key key}) : super(key: key); @@ -211,237 +199,241 @@ class _AssistantDetailState extends State { final recentMessages = context.watch().messages; final recentMessageKeys = recentMessages.keys.toList().reversed.toList(); - return Column( - children: [ - Container( - padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), - child: Row( - children: [ - if (!isDesktop) - GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: Container( - width: 20.0, - child: - Icon(Icons.arrow_back, color: color.primary)), - ), - SizedBox(width: 15.0), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Jarvis', - style: TextStyle(fontWeight: FontWeight.bold), + return Scaffold( + body: SafeArea( + child: Column( + children: [ + Container( + padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), + child: Row( + children: [ + if (!isDesktop) + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + width: 20.0, + child: + Icon(Icons.arrow_back, color: color.primary)), + ), + SizedBox(width: 15.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Jarvis', + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(height: 6.0), + Text(lang.onlineActive, + style: TextStyle(color: color.onPrimary.withOpacity(0.5), fontSize: 14.0)) + ], ), - SizedBox(height: 6.0), - Text(lang.onlineActive, - style: TextStyle(color: color.onPrimary.withOpacity(0.5), fontSize: 14.0)) - ], - ), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.phone_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.videocam_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - // PopupMenuButton( - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(15) - // ), - // color: const Color(0xFFEDEDED), - // child: Icon(Icons.more_vert_rounded, color: color.primary), - // onSelected: (int value) { - // if (value == 1) { - // // TODO set top - // } - // }, - // itemBuilder: (context) { - // return >[ - // _menuItem(Color(0xFF6174FF), 1, Icons.vertical_align_top_rounded, lang.cancelTop), - // ]; - // }, - // ) - ] - ), - ), - const Divider(height: 1.0, color: Color(0x40ADB0BB)), - Expanded( - child: ListView.builder( - padding: EdgeInsets.symmetric(horizontal: 20.0), - itemCount: recentMessageKeys.length, - reverse: true, - itemBuilder: (BuildContext context, index) => AssistantMessage( - name: 'Jarvis', - message: recentMessages[recentMessageKeys[index]], - answers: this.answers, - ) - )), - Container( - padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), - child: Row( - children: [ - GestureDetector( - onTap: () async { - if (recordShow) { - recordShow = false; - textFocus.requestFocus(); - } else { - _generateRecordPath(); - setState(() { - menuShow = false; - emojiShow = false; - recordShow = true; - textFocus.unfocus(); - }); - } - }, - child: Container(width: 20.0, - child: Icon(Icons.mic_rounded, color: color.primary)), + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.phone_rounded, + color: Color(0x26ADB0BB))), + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.videocam_rounded, + color: Color(0x26ADB0BB))), + ), + SizedBox(width: 20.0), + // PopupMenuButton( + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(15) + // ), + // color: const Color(0xFFEDEDED), + // child: Icon(Icons.more_vert_rounded, color: color.primary), + // onSelected: (int value) { + // if (value == 1) { + // // TODO set top + // } + // }, + // itemBuilder: (context) { + // return >[ + // _menuItem(Color(0xFF6174FF), 1, Icons.vertical_align_top_rounded, lang.cancelTop), + // ]; + // }, + // ) + ] ), - SizedBox(width: 10.0), - Expanded( - child: Container( - height: 40, - decoration: BoxDecoration( - color: color.surface, - borderRadius: BorderRadius.circular(15.0), + ), + const Divider(height: 1.0, color: Color(0x40ADB0BB)), + Expanded( + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 20.0), + itemCount: recentMessageKeys.length, + reverse: true, + itemBuilder: (BuildContext context, index) => AssistantMessage( + name: 'Jarvis', + message: recentMessages[recentMessageKeys[index]], + answers: this.answers, + ) + )), + Container( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + child: Row( + children: [ + GestureDetector( + onTap: () async { + if (recordShow) { + recordShow = false; + textFocus.requestFocus(); + } else { + _generateRecordPath(); + setState(() { + menuShow = false; + emojiShow = false; + recordShow = true; + textFocus.unfocus(); + }); + } + }, + child: Container(width: 20.0, + child: Icon(Icons.mic_rounded, color: color.primary)), + ), + SizedBox(width: 10.0), + Expanded( + child: Container( + height: 40, + decoration: BoxDecoration( + color: color.surface, + borderRadius: BorderRadius.circular(15.0), + ), + child: TextField( + style: TextStyle(fontSize: 14.0), + textInputAction: TextInputAction.send, + onChanged: (value) { + if (value.length == 0 && sendShow) { + setState(() { + sendShow = false; + }); + } else { + if (!sendShow) { + setState(() { + sendShow = true; + }); + } + } + }, + onSubmitted: (_v) => _sendMessage(), + decoration: InputDecoration( + hintText: 'Aa', + border: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15.0, right: 15.0, bottom: 7.0), + ), + controller: textController, + focusNode: textFocus, + ), + ), ), - child: TextField( - style: TextStyle(fontSize: 14.0), - textInputAction: TextInputAction.send, - onChanged: (value) { - if (value.length == 0 && sendShow) { + SizedBox(width: 10.0), + GestureDetector( + onTap: () { + if (emojiShow) { + textFocus.requestFocus(); + } else { setState(() { - sendShow = false; + menuShow = false; + recordShow = false; + emojiShow = true; + textFocus.unfocus(); }); + } + }, + child: Container( + width: 20.0, + child: Icon( + emojiShow + ? Icons.keyboard_rounded + : Icons.emoji_emotions_rounded, + color: color.primary)), + ), + SizedBox(width: 10.0), + sendShow + ? GestureDetector( + onTap: _sendMessage, + child: Container( + width: 50.0, + height: 30.0, + decoration: BoxDecoration( + color: Color(0xFF6174FF), + borderRadius: BorderRadius.circular(10.0), + ), + child: Center( + child: Icon(Icons.send, color: Colors.white, size: 20.0))), + ) + : GestureDetector( + onTap: () { + if (menuShow) { + textFocus.requestFocus(); } else { - if (!sendShow) { - setState(() { - sendShow = true; - }); - } + setState(() { + emojiShow = false; + recordShow = false; + menuShow = true; + textFocus.unfocus(); + }); } }, - onSubmitted: (_v) => _sendMessage(), - decoration: InputDecoration( - hintText: 'Aa', - border: InputBorder.none, - contentPadding: EdgeInsets.only( - left: 15.0, right: 15.0, bottom: 7.0), - ), - controller: textController, - focusNode: textFocus, + child: Container( + width: 20.0, + child: Icon(Icons.add_circle_rounded, color: color.primary)), ), - ), + ], ), - SizedBox(width: 10.0), - GestureDetector( - onTap: () { - if (emojiShow) { - textFocus.requestFocus(); - } else { - setState(() { - menuShow = false; - recordShow = false; - emojiShow = true; - textFocus.unfocus(); - }); - } - }, - child: Container( - width: 20.0, - child: Icon( - emojiShow - ? Icons.keyboard_rounded - : Icons.emoji_emotions_rounded, - color: color.primary)), - ), - SizedBox(width: 10.0), - sendShow - ? GestureDetector( - onTap: _sendMessage, - child: Container( - width: 50.0, - height: 30.0, - decoration: BoxDecoration( - color: Color(0xFF6174FF), - borderRadius: BorderRadius.circular(10.0), - ), - child: Center( - child: Icon(Icons.send, color: Colors.white, size: 20.0))), - ) - : GestureDetector( - onTap: () { - if (menuShow) { - textFocus.requestFocus(); - } else { - setState(() { - emojiShow = false; - recordShow = false; - menuShow = true; - textFocus.unfocus(); - }); - } - }, - child: Container( - width: 20.0, - child: Icon(Icons.add_circle_rounded, color: color.primary)), + ), + if (emojiShow) Emoji(action: _selectEmoji), + if (recordShow) + Container( + height: 100.0, + child: AudioRecorder( + path: Global.recordPath + _recordName, onStop: _sendRecord), + ), + if (menuShow) + Container( + height: 100.0, + child: Wrap( + spacing: 20.0, + runSpacing: 20.0, + alignment: WrapAlignment.center, + children: [ + ExtensionButton( + icon: Icons.image_rounded, + text: lang.album, + action: _sendImage, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.folder_rounded, + text: lang.file, + action: _sendFile, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.person_rounded, + text: lang.contact, + action: () => _sendContact(color, lang, + context.read().friends.values), + bgColor: color.surface, + iconColor: color.primary), + ], ), - ], - ), - ), - if (emojiShow) Emoji(action: _selectEmoji), - if (recordShow) - Container( - height: 100.0, - child: AudioRecorder( - path: Global.recordPath + _recordName, onStop: _sendRecord), - ), - if (menuShow) - Container( - height: 100.0, - child: Wrap( - spacing: 20.0, - runSpacing: 20.0, - alignment: WrapAlignment.center, - children: [ - ExtensionButton( - icon: Icons.image_rounded, - text: lang.album, - action: _sendImage, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.folder_rounded, - text: lang.file, - action: _sendFile, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.person_rounded, - text: lang.contact, - action: () => _sendContact(color, lang, - context.read().friends.values), - bgColor: color.surface, - iconColor: color.primary), - ], - ), + ) + ], ) - ], + ) ); } } diff --git a/lib/apps/chat/detail.dart b/lib/apps/chat/detail.dart index e15db9a..c405ac5 100644 --- a/lib/apps/chat/detail.dart +++ b/lib/apps/chat/detail.dart @@ -19,18 +19,6 @@ import 'package:esse/apps/primitives.dart'; import 'package:esse/apps/chat/models.dart'; import 'package:esse/apps/chat/provider.dart'; -class ChatPage extends StatelessWidget { - const ChatPage({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: ChatDetail(), - )); - } -} - class ChatDetail extends StatefulWidget { const ChatDetail({Key key}) : super(key: key); @@ -217,336 +205,340 @@ class _ChatDetailState extends State { ); } - return Column( - children: [ - Container( - padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), - child: Row( - children: [ - if (!isDesktop) - GestureDetector( - onTap: () { - context.read().clearActivedFriend(); - Navigator.pop(context); - }, - child: Container( - width: 20.0, - child: - Icon(Icons.arrow_back, color: color.primary)), - ), - SizedBox(width: 15.0), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - friend.name, - style: TextStyle(fontWeight: FontWeight.bold), + return Scaffold( + body: SafeArea( + child: Column( + children: [ + Container( + padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), + child: Row( + children: [ + if (!isDesktop) + GestureDetector( + onTap: () { + context.read().clearActivedFriend(); + Navigator.pop(context); + }, + child: Container( + width: 20.0, + child: + Icon(Icons.arrow_back, color: color.primary)), + ), + SizedBox(width: 15.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + friend.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(height: 6.0), + Text(friend.isClosed + ? lang.unfriended + : session.onlineLang(lang), + style: TextStyle( + color: color.onPrimary.withOpacity(0.5), + fontSize: 14.0)) + ], ), - SizedBox(height: 6.0), - Text(friend.isClosed - ? lang.unfriended - : session.onlineLang(lang), - style: TextStyle( - color: color.onPrimary.withOpacity(0.5), - fontSize: 14.0)) - ], - ), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.phone_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.videocam_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - PopupMenuButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15) - ), - color: const Color(0xFFEDEDED), - child: Icon(Icons.more_vert_rounded, color: color.primary), - onSelected: (int value) { - if (value == 2) { - showShadowDialog( - context, - Icons.info, - lang.friendInfo, - UserInfo( - id: 'EH' + friend.gid.toUpperCase(), - name: friend.name, - addr: '0x' + friend.addr) - ); - } else if (value == 3) { - print('TODO remark'); - } else if (value == 4) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(lang.unfriend), - content: Text(friend.name, - style: TextStyle(color: color.primary)), - actions: [ - TextButton( - child: Text(lang.cancel), - onPressed: () => Navigator.pop(context), - ), - TextButton( - child: Text(lang.ok), - onPressed: () { - Navigator.pop(context); - Provider.of( - context, listen: false).friendClose(friend.id); - if (!isDesktop) { - Navigator.pop(context); - } - }, - ), - ] + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.phone_rounded, + color: Color(0x26ADB0BB))), + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.videocam_rounded, + color: Color(0x26ADB0BB))), + ), + SizedBox(width: 20.0), + PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15) + ), + color: const Color(0xFFEDEDED), + child: Icon(Icons.more_vert_rounded, color: color.primary), + onSelected: (int value) { + if (value == 2) { + showShadowDialog( + context, + Icons.info, + lang.friendInfo, + UserInfo( + id: 'EH' + friend.gid.toUpperCase(), + name: friend.name, + addr: '0x' + friend.addr) + ); + } else if (value == 3) { + print('TODO remark'); + } else if (value == 4) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(lang.unfriend), + content: Text(friend.name, + style: TextStyle(color: color.primary)), + actions: [ + TextButton( + child: Text(lang.cancel), + onPressed: () => Navigator.pop(context), + ), + TextButton( + child: Text(lang.ok), + onPressed: () { + Navigator.pop(context); + Provider.of( + context, listen: false).friendClose(friend.id); + if (!isDesktop) { + Navigator.pop(context); + } + }, + ), + ] + ); + }, ); - }, - ); - } else if (value == 5) { - Provider.of(context, listen: false).requestCreate( - Request(friend.gid, friend.addr, friend.name, lang.fromContactCard(meName))); - } else if (value == 6) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(lang.delete + " " + lang.friend), - content: Text(friend.name, - style: TextStyle(color: Colors.red)), - actions: [ - TextButton( - child: Text(lang.cancel), - onPressed: () => Navigator.pop(context), - ), - TextButton( - child: Text(lang.ok), - onPressed: () { - Navigator.pop(context); - Provider.of( - context, listen: false).friendDelete(friend.id); - if (!isDesktop) { - Navigator.pop(context); - } - }, - ), - ] + } else if (value == 5) { + Provider.of(context, listen: false).requestCreate( + Request(friend.gid, friend.addr, friend.name, lang.fromContactCard(meName))); + } else if (value == 6) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(lang.delete + " " + lang.friend), + content: Text(friend.name, + style: TextStyle(color: Colors.red)), + actions: [ + TextButton( + child: Text(lang.cancel), + onPressed: () => Navigator.pop(context), + ), + TextButton( + child: Text(lang.ok), + onPressed: () { + Navigator.pop(context); + Provider.of( + context, listen: false).friendDelete(friend.id); + if (!isDesktop) { + Navigator.pop(context); + } + }, + ), + ] + ); + }, ); - }, - ); - } - }, - itemBuilder: (context) { - return >[ - _menuItem(Color(0xFF6174FF), 2, Icons.qr_code_rounded, lang.friendInfo), - //_menuItem(color.primary, 3, Icons.turned_in_rounded, lang.remark), - friend.isClosed - ? _menuItem(Color(0xFF6174FF), 5, Icons.send_rounded, lang.addFriend) - : _menuItem(Color(0xFF6174FF), 4, Icons.block_rounded, lang.unfriend), - _menuItem(Colors.red, 6, Icons.delete_rounded, lang.delete), - ]; - }, + } + }, + itemBuilder: (context) { + return >[ + _menuItem(Color(0xFF6174FF), 2, Icons.qr_code_rounded, lang.friendInfo), + //_menuItem(color.primary, 3, Icons.turned_in_rounded, lang.remark), + friend.isClosed + ? _menuItem(Color(0xFF6174FF), 5, Icons.send_rounded, lang.addFriend) + : _menuItem(Color(0xFF6174FF), 4, Icons.block_rounded, lang.unfriend), + _menuItem(Colors.red, 6, Icons.delete_rounded, lang.delete), + ]; + }, + ) + ] + ), + ), + const Divider(height: 1.0, color: Color(0x40ADB0BB)), + Expanded( + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 20.0), + itemCount: recentMessageKeys.length, + reverse: true, + itemBuilder: (BuildContext context, index) => ChatMessage( + name: friend.name, + message: recentMessages[recentMessageKeys[index]], + ) + )), + if (session.online == OnlineType.Lost) + InkWell( + onTap: () { + context.read().updateActivedSession(session.id); + }, + hoverColor: Colors.transparent, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 8.0), + margin: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + border: Border.all(color: color.primary), + borderRadius: BorderRadius.circular(10.0) + ), + child: Center(child: Text(lang.reconnect, style: TextStyle(color: color.primary))), ) - ] - ), - ), - const Divider(height: 1.0, color: Color(0x40ADB0BB)), - Expanded( - child: ListView.builder( - padding: EdgeInsets.symmetric(horizontal: 20.0), - itemCount: recentMessageKeys.length, - reverse: true, - itemBuilder: (BuildContext context, index) => ChatMessage( - name: friend.name, - message: recentMessages[recentMessageKeys[index]], - ) - )), - if (session.online == OnlineType.Lost) - InkWell( - onTap: () { - context.read().updateActivedSession(session.id); - }, - hoverColor: Colors.transparent, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 8.0), - margin: const EdgeInsets.all(10.0), - decoration: BoxDecoration( - border: Border.all(color: color.primary), - borderRadius: BorderRadius.circular(10.0) ), - child: Center(child: Text(lang.reconnect, style: TextStyle(color: color.primary))), - ) - ), - if (!friend.isClosed && session.online != OnlineType.Lost) - Container( - padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), - child: Row( - children: [ - GestureDetector( - onTap: isOnline ? () async { - if (recordShow) { - recordShow = false; - textFocus.requestFocus(); - } else { - _generateRecordPath(); - setState(() { - menuShow = false; - emojiShow = false; - recordShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon(Icons.mic_rounded, color: isOnline ? color.primary : Color(0xFFADB0BB))), - ), - SizedBox(width: 10.0), - Expanded( - child: Container( - height: 40, - decoration: BoxDecoration( - color: color.surface, - borderRadius: BorderRadius.circular(15.0), + if (!friend.isClosed && session.online != OnlineType.Lost) + Container( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + child: Row( + children: [ + GestureDetector( + onTap: isOnline ? () async { + if (recordShow) { + recordShow = false; + textFocus.requestFocus(); + } else { + _generateRecordPath(); + setState(() { + menuShow = false; + emojiShow = false; + recordShow = true; + textFocus.unfocus(); + }); + } + } : null, + child: Container( + width: 20.0, + child: Icon(Icons.mic_rounded, color: isOnline ? color.primary : Color(0xFFADB0BB))), ), - child: TextField( - enabled: isOnline, - style: TextStyle(fontSize: 14.0), - textInputAction: TextInputAction.send, - onChanged: (value) { - if (value.length == 0 && sendShow) { + SizedBox(width: 10.0), + Expanded( + child: Container( + height: 40, + decoration: BoxDecoration( + color: color.surface, + borderRadius: BorderRadius.circular(15.0), + ), + child: TextField( + enabled: isOnline, + style: TextStyle(fontSize: 14.0), + textInputAction: TextInputAction.send, + onChanged: (value) { + if (value.length == 0 && sendShow) { + setState(() { + sendShow = false; + }); + } else { + if (!sendShow) { + setState(() { + sendShow = true; + }); + } + } + }, + onSubmitted: (_v) => _sendMessage(), + decoration: InputDecoration( + hintText: 'Aa', + border: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15.0, right: 15.0, bottom: 7.0), + ), + controller: textController, + focusNode: textFocus, + ), + ), + ), + SizedBox(width: 10.0), + GestureDetector( + onTap: isOnline ? () { + if (emojiShow) { + textFocus.requestFocus(); + } else { setState(() { - sendShow = false; + menuShow = false; + recordShow = false; + emojiShow = true; + textFocus.unfocus(); }); + } + } : null, + child: Container( + width: 20.0, + child: Icon( + emojiShow + ? Icons.keyboard_rounded + : Icons.emoji_emotions_rounded, + color: isOnline ? color.primary : Color(0xFFADB0BB))), + ), + SizedBox(width: 10.0), + sendShow + ? GestureDetector( + onTap: isOnline ? _sendMessage : null, + child: Container( + width: 50.0, + height: 30.0, + decoration: BoxDecoration( + color: Color(0xFF6174FF), + borderRadius: BorderRadius.circular(10.0), + ), + child: Center( + child: Icon(Icons.send, + color: Colors.white, size: 20.0))), + ) + : GestureDetector( + onTap: isOnline ? () { + if (menuShow) { + textFocus.requestFocus(); } else { - if (!sendShow) { - setState(() { - sendShow = true; - }); - } + setState(() { + emojiShow = false; + recordShow = false; + menuShow = true; + textFocus.unfocus(); + }); } - }, - onSubmitted: (_v) => _sendMessage(), - decoration: InputDecoration( - hintText: 'Aa', - border: InputBorder.none, - contentPadding: EdgeInsets.only( - left: 15.0, right: 15.0, bottom: 7.0), - ), - controller: textController, - focusNode: textFocus, + } : null, + child: Container( + width: 20.0, + child: Icon(Icons.add_circle_rounded, + color: isOnline ? color.primary : Color(0xFFADB0BB))), ), - ), - ), - SizedBox(width: 10.0), - GestureDetector( - onTap: isOnline ? () { - if (emojiShow) { - textFocus.requestFocus(); - } else { - setState(() { - menuShow = false; - recordShow = false; - emojiShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon( - emojiShow - ? Icons.keyboard_rounded - : Icons.emoji_emotions_rounded, - color: isOnline ? color.primary : Color(0xFFADB0BB))), + ], ), - SizedBox(width: 10.0), - sendShow - ? GestureDetector( - onTap: isOnline ? _sendMessage : null, - child: Container( - width: 50.0, - height: 30.0, - decoration: BoxDecoration( - color: Color(0xFF6174FF), - borderRadius: BorderRadius.circular(10.0), - ), - child: Center( - child: Icon(Icons.send, - color: Colors.white, size: 20.0))), - ) - : GestureDetector( - onTap: isOnline ? () { - if (menuShow) { - textFocus.requestFocus(); - } else { - setState(() { - emojiShow = false; - recordShow = false; - menuShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon(Icons.add_circle_rounded, - color: isOnline ? color.primary : Color(0xFFADB0BB))), + ), + if (emojiShow && isOnline) Emoji(action: _selectEmoji), + if (recordShow && isOnline) + Container( + height: 100.0, + child: AudioRecorder( + path: Global.recordPath + _recordName, onStop: _sendRecord), + ), + if (menuShow && isOnline) + Container( + height: 100.0, + child: Wrap( + spacing: 20.0, + runSpacing: 20.0, + alignment: WrapAlignment.center, + children: [ + ExtensionButton( + icon: Icons.image_rounded, + text: lang.album, + action: _sendImage, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.folder_rounded, + text: lang.file, + action: _sendFile, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.person_rounded, + text: lang.contact, + action: () => _sendContact(color, lang, context.read().friends.values), + bgColor: color.surface, + iconColor: color.primary), + ], ), - ], - ), - ), - if (emojiShow && isOnline) Emoji(action: _selectEmoji), - if (recordShow && isOnline) - Container( - height: 100.0, - child: AudioRecorder( - path: Global.recordPath + _recordName, onStop: _sendRecord), - ), - if (menuShow && isOnline) - Container( - height: 100.0, - child: Wrap( - spacing: 20.0, - runSpacing: 20.0, - alignment: WrapAlignment.center, - children: [ - ExtensionButton( - icon: Icons.image_rounded, - text: lang.album, - action: _sendImage, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.folder_rounded, - text: lang.file, - action: _sendFile, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.person_rounded, - text: lang.contact, - action: () => _sendContact(color, lang, context.read().friends.values), - bgColor: color.surface, - iconColor: color.primary), - ], - ), + ) + ], ) - ], + ) ); } } diff --git a/lib/apps/chat/list.dart b/lib/apps/chat/list.dart index 3024a0f..af854ac 100644 --- a/lib/apps/chat/list.dart +++ b/lib/apps/chat/list.dart @@ -63,15 +63,11 @@ class ListChat extends StatelessWidget { onTap: () { context.read().updateActivedSession(0, SessionType.Chat, friend.id); context.read().updateActivedFriend(friend.id); + final widget = ChatDetail(); if (!isDesktop) { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => ChatPage(), - ), - ); + Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); } else { - context.read().updateActivedWidget(ChatDetail()); + context.read().updateActivedWidget(widget); } }, child: Container( diff --git a/lib/apps/group_chat/detail.dart b/lib/apps/group_chat/detail.dart index 4d78339..e1cd5f4 100644 --- a/lib/apps/group_chat/detail.dart +++ b/lib/apps/group_chat/detail.dart @@ -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'; 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 _scaffoldKey = new GlobalKey(); + const GroupChatDetail({Key key}) : super(key: key); @override @@ -200,6 +192,7 @@ class _GroupChatDetailState extends State { final isDesktop = isDisplayDesktop(context); final provider = context.watch(); + final members = provider.activedMembers; final recentMessages = provider.activedMessages; final recentMessageKeys = recentMessages.keys.toList().reversed.toList(); @@ -219,337 +212,323 @@ class _GroupChatDetailState extends State { final meName = accountProvider.activedAccount.name; final isOnline = session.isActive(); - return Column( - children: [ - Container( - padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), - child: Row( - children: [ - if (!isDesktop) - GestureDetector( - onTap: () { - context.read().clearActivedGroup(); - Navigator.pop(context); - }, - child: Container( - width: 20.0, - child: - Icon(Icons.arrow_back, color: color.primary)), - ), - SizedBox(width: 15.0), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - this.group.name, - style: TextStyle(fontWeight: FontWeight.bold), + 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), + child: Row( + children: [ + if (!isDesktop) + GestureDetector( + onTap: () { + context.read().clearActivedGroup(); + Navigator.pop(context); + }, + child: Container( + width: 20.0, + child: + Icon(Icons.arrow_back, color: color.primary)), + ), + SizedBox(width: 15.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + this.group.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(height: 6.0), + Text(this.group.isClosed + ? lang.unfriended + : session.onlineLang(lang), + style: TextStyle( + color: color.onPrimary.withOpacity(0.5), + fontSize: 14.0)) + ], ), - SizedBox(height: 6.0), - Text(this.group.isClosed - ? lang.unfriended - : session.onlineLang(lang), - style: TextStyle( - color: color.onPrimary.withOpacity(0.5), - fontSize: 14.0)) - ], - ), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.phone_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - GestureDetector( - onTap: () {}, - child: Container( - width: 20.0, - child: Icon(Icons.videocam_rounded, - color: Color(0x26ADB0BB))), - ), - SizedBox(width: 20.0), - PopupMenuButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15) - ), - 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, - 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, + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.phone_rounded, + color: Color(0x26ADB0BB))), + ), + SizedBox(width: 20.0), + GestureDetector( + onTap: () {}, + child: Container( + width: 20.0, + child: Icon(Icons.videocam_rounded, + 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( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15) + ), + color: const Color(0xFFEDEDED), + child: Icon(Icons.more_vert_rounded, color: color.primary), + onSelected: (int value) { + 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 + ) ); - }).toList(); - - showShadowDialog( - context, - Icons.group_rounded, - lang.members, - Wrap( - spacing: 10.0, - runSpacing: 10.0, - children: memberWidgets, - ), - 10.0, //height - ); - } else if (value == 4) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(lang.unfriend), - content: Text(this.group.name, - style: TextStyle(color: color.primary)), - actions: [ - TextButton( - child: Text(lang.cancel), - onPressed: () => Navigator.pop(context), - ), - TextButton( - child: Text(lang.ok), - onPressed: () { - Navigator.pop(context); - //Provider.of(context, listen: false).groupClose(this.group.id); - if (!isDesktop) { - Navigator.pop(context); - } - }, - ), - ] + } else if (value == 2) { + showDialog( + context: context, builder: (BuildContext context) { + return AlertDialog( + title: Text(lang.exit), + content: Text(this.group.name, + style: TextStyle(color: color.primary)), + actions: [ + TextButton(child: Text(lang.cancel), + onPressed: () => Navigator.pop(context), + ), + TextButton(child: Text(lang.ok), + onPressed: () { + Navigator.pop(context); + provider.close(this.group.id); + }, + ), + ] + ); + }, ); - }, - ); - } else if (value == 5) { - // Provider.of(context, listen: false).requestCreate( - // Request(this.group.gid, this.group.addr, this.group.name, lang.fromContactCard(meName))); - } else if (value == 6) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(lang.delete + ' ' + lang.groupChat), - content: Text(this.group.name, - style: TextStyle(color: Colors.red)), - actions: [ - TextButton( - child: Text(lang.cancel), - onPressed: () => Navigator.pop(context), - ), - TextButton( - child: Text(lang.ok), - onPressed: () { - Navigator.pop(context); - //Provider.of(context, listen: false).groupDelete(this.group.id); - if (!isDesktop) { - Navigator.pop(context); - } - }, - ), - ] + } else if (value == 3) { + showDialog( + context: context, builder: (BuildContext context) { + return AlertDialog( + title: Text(lang.delete + ' ' + lang.groupChat), + content: Text(this.group.name, + style: TextStyle(color: Colors.red)), + actions: [ + TextButton( + child: Text(lang.cancel), + onPressed: () => Navigator.pop(context), + ), + TextButton( + child: Text(lang.ok), + onPressed: () { + Navigator.pop(context); + provider.delete(this.group.id); + }, + ), + ] + ); + }, ); - }, - ); - } - }, - itemBuilder: (context) { - return >[ - _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), - ]; - }, - ) - ] - ), - ), - const Divider(height: 1.0, color: Color(0x40ADB0BB)), - Expanded( - child: ListView.builder( - padding: EdgeInsets.symmetric(horizontal: 20.0), - itemCount: recentMessageKeys.length, - reverse: true, - itemBuilder: (BuildContext context, index) => ChatMessage( - name: this.group.name, - message: recentMessages[recentMessageKeys[index]], - ) - )), - if (!this.group.isClosed) - Container( - padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), - child: Row( - children: [ - GestureDetector( - onTap: isOnline ? () async { - if (recordShow) { - recordShow = false; - textFocus.requestFocus(); - } else { - _generateRecordPath(); - setState(() { - menuShow = false; - emojiShow = false; - recordShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon(Icons.mic_rounded, color: isOnline ? color.primary : Color(0xFFADB0BB))), + } else if (value == 4) { + provider.reAdd(this.group.id); + } + }, + itemBuilder: (context) { + return >[ + _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), + ]; + }, + ) + ] ), - SizedBox(width: 10.0), - Expanded( - child: Container( - height: 40, - decoration: BoxDecoration( - color: color.surface, - borderRadius: BorderRadius.circular(15.0), + ), + const Divider(height: 1.0, color: Color(0x40ADB0BB)), + Expanded( + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 20.0), + itemCount: recentMessageKeys.length, + reverse: true, + 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( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + child: Row( + children: [ + GestureDetector( + onTap: isOnline ? () async { + if (recordShow) { + recordShow = false; + textFocus.requestFocus(); + } else { + _generateRecordPath(); + setState(() { + menuShow = false; + emojiShow = false; + recordShow = true; + textFocus.unfocus(); + }); + } + } : null, + child: Container( + width: 20.0, + child: Icon(Icons.mic_rounded, color: isOnline ? color.primary : Color(0xFFADB0BB))), + ), + SizedBox(width: 10.0), + Expanded( + child: Container( + height: 40, + decoration: BoxDecoration( + color: color.surface, + borderRadius: BorderRadius.circular(15.0), + ), + child: TextField( + enabled: isOnline, + style: TextStyle(fontSize: 14.0), + textInputAction: TextInputAction.send, + onChanged: (value) { + if (value.length == 0 && sendShow) { + setState(() { + sendShow = false; + }); + } else { + if (!sendShow) { + setState(() { + sendShow = true; + }); + } + } + }, + onSubmitted: (_v) => _sendMessage(), + decoration: InputDecoration( + hintText: 'Aa', + border: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15.0, right: 15.0, bottom: 7.0), + ), + controller: textController, + focusNode: textFocus, + ), + ), ), - child: TextField( - enabled: isOnline, - style: TextStyle(fontSize: 14.0), - textInputAction: TextInputAction.send, - onChanged: (value) { - if (value.length == 0 && sendShow) { + SizedBox(width: 10.0), + GestureDetector( + onTap: isOnline ? () { + if (emojiShow) { + textFocus.requestFocus(); + } else { setState(() { - sendShow = false; + menuShow = false; + recordShow = false; + emojiShow = true; + textFocus.unfocus(); }); + } + } : null, + child: Container( + width: 20.0, + child: Icon( + emojiShow + ? Icons.keyboard_rounded + : Icons.emoji_emotions_rounded, + color: isOnline ? color.primary : Color(0xFFADB0BB))), + ), + SizedBox(width: 10.0), + sendShow + ? GestureDetector( + onTap: isOnline ? _sendMessage : null, + child: Container( + width: 50.0, + height: 30.0, + decoration: BoxDecoration( + color: Color(0xFF6174FF), + borderRadius: BorderRadius.circular(10.0), + ), + child: Center( + child: Icon(Icons.send, + color: Colors.white, size: 20.0))), + ) + : GestureDetector( + onTap: isOnline ? () { + if (menuShow) { + textFocus.requestFocus(); } else { - if (!sendShow) { - setState(() { - sendShow = true; - }); - } + setState(() { + emojiShow = false; + recordShow = false; + menuShow = true; + textFocus.unfocus(); + }); } - }, - onSubmitted: (_v) => _sendMessage(), - decoration: InputDecoration( - hintText: 'Aa', - border: InputBorder.none, - contentPadding: EdgeInsets.only( - left: 15.0, right: 15.0, bottom: 7.0), - ), - controller: textController, - focusNode: textFocus, + } : null, + child: Container( + width: 20.0, + child: Icon(Icons.add_circle_rounded, + color: isOnline ? color.primary : Color(0xFFADB0BB))), ), - ), + ], ), - SizedBox(width: 10.0), - GestureDetector( - onTap: isOnline ? () { - if (emojiShow) { - textFocus.requestFocus(); - } else { - setState(() { - menuShow = false; - recordShow = false; - emojiShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon( - emojiShow - ? Icons.keyboard_rounded - : Icons.emoji_emotions_rounded, - color: isOnline ? color.primary : Color(0xFFADB0BB))), - ), - SizedBox(width: 10.0), - sendShow - ? GestureDetector( - onTap: isOnline ? _sendMessage : null, - child: Container( - width: 50.0, - height: 30.0, - decoration: BoxDecoration( - color: Color(0xFF6174FF), - borderRadius: BorderRadius.circular(10.0), - ), - child: Center( - child: Icon(Icons.send, - color: Colors.white, size: 20.0))), - ) - : GestureDetector( - onTap: isOnline ? () { - if (menuShow) { - textFocus.requestFocus(); - } else { - setState(() { - emojiShow = false; - recordShow = false; - menuShow = true; - textFocus.unfocus(); - }); - } - } : null, - child: Container( - width: 20.0, - child: Icon(Icons.add_circle_rounded, - color: isOnline ? color.primary : Color(0xFFADB0BB))), + ), + if (emojiShow && isOnline) Emoji(action: _selectEmoji), + if (recordShow && isOnline) + Container( + height: 100.0, + child: AudioRecorder( + path: Global.recordPath + _recordName, onStop: _sendRecord), + ), + if (menuShow && isOnline) + Container( + height: 100.0, + child: Wrap( + spacing: 20.0, + runSpacing: 20.0, + alignment: WrapAlignment.center, + children: [ + ExtensionButton( + icon: Icons.image_rounded, + text: lang.album, + action: _sendImage, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.folder_rounded, + text: lang.file, + action: _sendFile, + bgColor: color.surface, + iconColor: color.primary), + ExtensionButton( + icon: Icons.person_rounded, + text: lang.contact, + action: () => _sendContact(color, lang, context.read().friends.values), + bgColor: color.surface, + iconColor: color.primary), + ], ), - ], - ), - ), - if (emojiShow && isOnline) Emoji(action: _selectEmoji), - if (recordShow && isOnline) - Container( - height: 100.0, - child: AudioRecorder( - path: Global.recordPath + _recordName, onStop: _sendRecord), - ), - if (menuShow && isOnline) - Container( - height: 100.0, - child: Wrap( - spacing: 20.0, - runSpacing: 20.0, - alignment: WrapAlignment.center, - children: [ - ExtensionButton( - icon: Icons.image_rounded, - text: lang.album, - action: _sendImage, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.folder_rounded, - text: lang.file, - action: _sendFile, - bgColor: color.surface, - iconColor: color.primary), - ExtensionButton( - icon: Icons.person_rounded, - text: lang.contact, - action: () => _sendContact(color, lang, context.read().friends.values), - bgColor: color.surface, - iconColor: color.primary), - ], - ), + ) + ], ) - ], + ) ); } } @@ -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, - 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)), + 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(); + 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: [ + 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 { 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), diff --git a/lib/apps/group_chat/models.dart b/lib/apps/group_chat/models.dart index e150bf4..7ff8032 100644 --- a/lib/apps/group_chat/models.dart +++ b/lib/apps/group_chat/models.dart @@ -155,16 +155,7 @@ class Member { String addr; String name; bool isManager; - - // MOCK need deleted. - Member(String name, bool isManager) { - this.id = 0; - this.fid = 0; - this.mid = 'EH0000000000000000000000000000000000000000000000000000000000000000'; - this.addr = '0x0000000000000000000000000000000000000000000000000000000000000000'; - this.name = name; - this.isManager = isManager; - } + bool online = false; Member.fromList(List params) { this.id = params[0]; @@ -175,15 +166,15 @@ class Member { this.isManager = params[5]; } - Avatar showAvatar({double width = 45.0}) { + Avatar showAvatar({double width = 45.0, colorSurface = false}) { final avatar = Global.avatarPath + this.mid + '.png'; return Avatar( width: width, name: this.name, avatarPath: avatar, - online: false, - hasNew: this.isManager, - hasNewColor: Color(0xFF6174FF), + online: this.online, + onlineColor: Color(0xFF0EE50A), + colorSurface: colorSurface, ); } } diff --git a/lib/apps/group_chat/page.dart b/lib/apps/group_chat/page.dart index 711e4d9..2083a2b 100644 --- a/lib/apps/group_chat/page.dart +++ b/lib/apps/group_chat/page.dart @@ -60,19 +60,13 @@ class ListChat extends StatelessWidget { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - context.read().updateActivedGroup(group.id); - context.read().updateActivedSession(0, SessionType.Group, group.id); - + context.read().updateActivedGroup(group.id); + final widget = GroupChatDetail(); if (!isDesktop) { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => GroupChatPage(), - ), - ); + Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); } else { - context.read().updateActivedWidget(GroupChatDetail()); + context.read().updateActivedWidget(widget); } }, child: Container( diff --git a/lib/apps/group_chat/provider.dart b/lib/apps/group_chat/provider.dart index f24228b..1ff6069 100644 --- a/lib/apps/group_chat/provider.dart +++ b/lib/apps/group_chat/provider.dart @@ -33,6 +33,24 @@ class GroupChatProvider extends ChangeNotifier { return false; } + List get activedMemberOrder { + List allKeys = []; + List managers = []; + List commons = []; + this.activedMembers.forEach((i, m) { + if (m.isManager) { + if (m.mid == this.activedGroup.owner) { + allKeys.add(i); + } else { + managers.add(i); + } + } else { + commons.add(i); + } + }); + return allKeys + managers + commons; + } + GroupChatProvider() { // rpc. rpc.addListener('group-chat-list', _list, false); @@ -108,6 +126,18 @@ class GroupChatProvider extends ChangeNotifier { rpc.send('group-chat-request-list', [all]); } + close(int id) { + // rpc.send('group-chat-close', [id]); + } + + delete(int id) { + // rpc.send('group-chat-delete', [id]); + } + + reAdd(int id) { + // rpc.send('group-chat-readd', [id]); + } + _list(List params) { this.clear(); params.forEach((params) { diff --git a/lib/apps/service/models.dart b/lib/apps/service/models.dart index 506d13c..639a6af 100644 --- a/lib/apps/service/models.dart +++ b/lib/apps/service/models.dart @@ -32,33 +32,26 @@ extension InnerServiceExtension on InnerService { String listTitle = null; Widget listHome = null; - if (isDesktop) { - switch (this) { - case InnerService.Files: - listTitle = lang.files; - listHome = FolderList(); - break; - case InnerService.Assistant: - coreWidget = AssistantDetail(); - break; - case InnerService.GroupChat: - listTitle = lang.groupChat; - listHome = GroupChatList(); - break; - } - Provider.of(context, listen: false).updateActivedWidget(coreWidget, listTitle, listHome); + switch (this) { + case InnerService.Files: + listTitle = lang.files; + listHome = FolderList(); + break; + case InnerService.Assistant: + coreWidget = AssistantDetail(); + break; + case InnerService.GroupChat: + listTitle = lang.groupChat; + listHome = GroupChatList(); + break; + } + + if (this == InnerService.Assistant) { + Navigator.push(context, MaterialPageRoute(builder: (_) => coreWidget)); } else { - switch (this) { - case InnerService.Files: - Provider.of(context, listen: false).updateActivedWidget(null, lang.files, FolderList()); - break; - case InnerService.Assistant: - Navigator.push(context, MaterialPageRoute(builder: (_) => AssistantPage())); - break; - case InnerService.GroupChat: - Provider.of(context, listen: false).updateActivedWidget(null, lang.groupChat, GroupChatList()); - break; - } + Provider.of(context, listen: false).updateActivedWidget( + coreWidget, listTitle, listHome + ); } } } diff --git a/lib/session.dart b/lib/session.dart index 81d2654..1f64936 100644 --- a/lib/session.dart +++ b/lib/session.dart @@ -97,6 +97,8 @@ class Session { switch (this.type) { case SessionType.Chat: return [showAvatar(), this.name, this.lastContent, this.lastTime.toString()]; + case SessionType.Group: + return [showAvatar(), this.name, this.lastContent, this.lastTime.toString()]; case SessionType.Assistant: final params = Session.innerService(InnerService.Assistant, lang); return [params[0], params[1], params[2], '']; diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 181a3bb..0f80e4f 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -14,6 +14,7 @@ class Avatar extends StatelessWidget { final bool hasNew; final Color hasNewColor; final bool loading; + final bool colorSurface; const Avatar( {Key key, @@ -26,6 +27,7 @@ class Avatar extends StatelessWidget { this.hasNew = false, this.hasNewColor = Colors.red, this.loading = false, + this.colorSurface = true, }) : super(key: key); @@ -46,8 +48,14 @@ class Avatar extends StatelessWidget { width: this.width, height: this.width, decoration: showAvatar != null - ? BoxDecoration(image: DecorationImage(image: showAvatar, fit: BoxFit.cover), borderRadius: BorderRadius.circular(15.0)) - : BoxDecoration(color: color.surface, borderRadius: BorderRadius.circular(15.0)), + ? BoxDecoration( + image: DecorationImage(image: showAvatar, fit: BoxFit.cover), + borderRadius: BorderRadius.circular(15.0) + ) + : BoxDecoration( + color: this.colorSurface ? color.surface : color.background, + borderRadius: BorderRadius.circular(15.0) + ), child: Stack( alignment: Alignment.center, children: [ diff --git a/lib/widgets/chat_message.dart b/lib/widgets/chat_message.dart index f0c5ca8..8db4e4d 100644 --- a/lib/widgets/chat_message.dart +++ b/lib/widgets/chat_message.dart @@ -20,10 +20,11 @@ import 'package:esse/apps/chat/models.dart' show Request; import 'package:esse/apps/chat/provider.dart'; class ChatMessage extends StatelessWidget { + final Widget avatar; final String name; final BaseMessage message; - const ChatMessage({Key key, this.name, this.message}): super(key: key); + const ChatMessage({Key key, this.name, this.message, this.avatar}): super(key: key); Widget _showText(context, color, isDesktop) { final width = MediaQuery.of(context).size.width * 0.6; @@ -347,36 +348,66 @@ class ChatMessage extends StatelessWidget { final lang = AppLocalizations.of(context); final isDesktop = isDisplayDesktop(context); final messageShow = _show(context, color, lang, isDesktop); + final isAvatar = avatar != null && !message.isMe; - return Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: Column(children: [ - Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Align( - alignment: - message.isMe ? Alignment.topRight : Alignment.topLeft, - child: messageShow, - ), - ), - ]), + final timeWidget = Container( + padding: EdgeInsets.only(top: 6.0), + child: Row(children: [ + if (message.isMe) Spacer(), + if (isAvatar) Container( - padding: EdgeInsets.only(top: 10.0), - child: Row(children: [ - if (message.isMe) Spacer(), - Text(message.time.toString(), - style: TextStyle( - color: color.onPrimary.withOpacity(0.5), - fontSize: 12.0)), - SizedBox(width: 4.0), - Icon( - message.isDelivery == null ? Icons.hourglass_top - : (message.isDelivery ? Icons.done : Icons.error), - size: 12.0, - color: message.isDelivery == null ? color.primaryVariant - : (message.isDelivery ? color.primary : Colors.red) - ), - ])) + width: 50.0, + child: Text(name, maxLines: 1, overflow: TextOverflow.ellipsis, + style: TextStyle(color: color.onPrimary.withOpacity(0.5), fontSize: 12.0) + )), + const SizedBox(width: 4.0), + Text(message.time.toString(), style: TextStyle( + color: color.onPrimary.withOpacity(0.5), + fontSize: 12.0)), + const SizedBox(width: 4.0), + Icon( + message.isDelivery == null ? Icons.hourglass_top + : (message.isDelivery ? Icons.done : Icons.error), + size: 12.0, + color: message.isDelivery == null ? color.primaryVariant + : (message.isDelivery ? color.primary : Colors.red) + ), ])); + + final mainWidget = Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Expanded( + child: Align( + alignment: message.isMe ? Alignment.topRight : Alignment.topLeft, + child: messageShow, + ), + ), + ]); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: + isAvatar + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + avatar, + const SizedBox(width: 4.0), + Expanded( + child: Column( + children: [ + mainWidget, + timeWidget, + ] + ) + ) + ] + ) + : Column( + children: [ + mainWidget, + timeWidget, + ] + ) + ); } } diff --git a/lib/widgets/default_home_show.dart b/lib/widgets/default_home_show.dart index 089b0b1..4a590f9 100644 --- a/lib/widgets/default_home_show.dart +++ b/lib/widgets/default_home_show.dart @@ -10,6 +10,8 @@ import 'package:esse/session.dart'; import 'package:esse/apps/chat/detail.dart'; import 'package:esse/apps/chat/provider.dart'; +import 'package:esse/apps/group_chat/detail.dart'; +import 'package:esse/apps/group_chat/provider.dart'; import 'package:esse/apps/assistant/page.dart'; import 'package:esse/apps/file/page.dart'; @@ -24,23 +26,11 @@ class DefaultHomeShow extends StatelessWidget { final allKeys = provider.topKeys + provider.orderKeys; final sessions = provider.sessions; - return Scaffold( - body: ListView.builder( - itemCount: allKeys.length, - itemBuilder: (BuildContext ctx, int index) => _SessionWidget(session: sessions[allKeys[index]]), + return ListView.builder( + itemCount: allKeys.length, + itemBuilder: (BuildContext ctx, int index) => _SessionWidget( + session: sessions[allKeys[index]] ), - // floatingActionButton: FloatingActionButton( - // onPressed: () { - // final widget = Text(''); - // if (isDesktop) { - // Provider.of(context, listen: false).updateActivedSession(0, widget); - // } else { - // Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); - // } - // }, - // child: const Icon(Icons.add, color: Colors.white), - // backgroundColor: Color(0xFF6174FF), - // ), ); } } @@ -66,20 +56,14 @@ class _SessionWidget extends StatelessWidget { switch (session.type) { case SessionType.Chat: context.read().updateActivedFriend(session.fid); - if (!isDesktop) { - coreWidget = ChatPage(); - } else { - coreWidget = ChatDetail(); - } + coreWidget = ChatDetail(); break; case SessionType.Group: + context.read().updateActivedGroup(session.fid); + coreWidget = GroupChatDetail(); break; case SessionType.Assistant: - if (!isDesktop) { - coreWidget = AssistantPage(); - } else { - coreWidget = AssistantDetail(); - } + coreWidget = AssistantDetail(); break; case SessionType.Files: listTitle = lang.files; @@ -89,17 +73,10 @@ class _SessionWidget extends StatelessWidget { context.read().updateActivedSession(session.id); - if (!isDesktop) { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => coreWidget, - ), - ); + if (!isDesktop && coreWidget != null) { + Navigator.push(context, MaterialPageRoute(builder: (_) => coreWidget)); } else { - context.read().updateActivedWidget( - coreWidget, listTitle, listWidget - ); + context.read().updateActivedWidget(coreWidget, listTitle, listWidget); } }, child: Container(