Browse Source

apply new session style

pull/18/head
Sun 4 years ago
parent
commit
cd432ad4a0
  1. 6
      lib/account.dart
  2. 13
      lib/apps/assistant/message.dart
  3. 2
      lib/apps/assistant/page.dart
  4. 67
      lib/apps/chat/detail.dart
  5. 8
      lib/apps/chat/list.dart
  6. 11
      lib/apps/chat/models.dart
  7. 24
      lib/apps/chat/provider.dart
  8. 4
      lib/apps/device/page.dart
  9. 2
      lib/apps/file/page.dart
  10. 9
      lib/apps/group_chat/detail.dart
  11. 16
      lib/apps/group_chat/models.dart
  12. 9
      lib/apps/group_chat/page.dart
  13. 4
      lib/apps/service/list.dart
  14. 6
      lib/apps/service/models.dart
  15. 6
      lib/l10n/localizations.dart
  16. 8
      lib/l10n/localizations_en.dart
  17. 8
      lib/l10n/localizations_zh.dart
  18. 43
      lib/pages/home.dart
  19. 45
      lib/provider.dart
  20. 35
      lib/session.dart
  21. 56
      lib/widgets/avatar.dart
  22. 13
      lib/widgets/chat_message.dart
  23. 13
      lib/widgets/default_home_show.dart
  24. 18
      src/apps/chat/layer.rs
  25. 10
      src/apps/chat/rpc.rs
  26. 11
      src/event.rs

6
lib/account.dart

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
@ -63,8 +65,8 @@ class Account {
width: width, width: width,
name: this.name, name: this.name,
avatar: this.avatar, avatar: this.avatar,
online: online, online: true,
needOnline: needOnline, onlineColor: this.online ? const Color(0xFF0EE50A) : const Color(0xFFEDEDED),
hasNew: this.hasNew, hasNew: this.hasNew,
); );
} }

13
lib/apps/assistant/message.dart

@ -192,12 +192,7 @@ class AssistantMessage extends StatelessWidget {
Icons.person_rounded, Icons.person_rounded,
lang.contact, lang.contact,
Column(children: [ Column(children: [
Avatar( Avatar(width: 100.0, name: infos[0], avatarPath: infos[3]),
width: 100.0,
name: infos[0],
avatarPath: infos[3],
needOnline: false
),
const SizedBox(height: 10.0), const SizedBox(height: 10.0),
Text(infos[0]), Text(infos[0]),
const SizedBox(height: 10.0), const SizedBox(height: 10.0),
@ -245,11 +240,7 @@ class AssistantMessage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row(children: [ Row(children: [
Avatar( Avatar(width: 40.0, name: infos[0], avatarPath: infos[3]),
width: 40.0,
name: infos[0],
avatarPath: infos[3],
needOnline: false),
Container( Container(
width: 135.0, width: 135.0,
padding: const EdgeInsets.only(left: 10.0), padding: const EdgeInsets.only(left: 10.0),

2
lib/apps/assistant/page.dart

@ -236,7 +236,7 @@ class _AssistantDetailState extends State<AssistantDetail> {
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
SizedBox(height: 6.0), SizedBox(height: 6.0),
Text(lang.online, Text(lang.onlineActive,
style: TextStyle(color: color.onPrimary.withOpacity(0.5), fontSize: 14.0)) style: TextStyle(color: color.onPrimary.withOpacity(0.5), fontSize: 14.0))
], ],
), ),

67
lib/apps/chat/detail.dart

@ -48,11 +48,10 @@ class _ChatDetailState extends State<ChatDetail> {
String _recordName; String _recordName;
int _actived; int _actived;
Friend _friend;
String _meName;
@override @override
initState() { initState() {
print("Chat detail initState...");
super.initState(); super.initState();
textFocus.addListener(() { textFocus.addListener(() {
if (textFocus.hasFocus) { if (textFocus.hasFocus) {
@ -63,15 +62,6 @@ class _ChatDetailState extends State<ChatDetail> {
}); });
} }
}); });
new Future.delayed(Duration.zero, () {
final accountProvider = context.read<AccountProvider>();
final chatProvider = context.read<ChatProvider>();
this._actived = accountProvider.activedSession.fid;
this._meName = accountProvider.activedAccount.name;
this._friend = chatProvider.friends[this._actived];
chatProvider.updateActivedFriend(this._actived);
setState(() {});
});
} }
_generateRecordPath() { _generateRecordPath() {
@ -212,18 +202,21 @@ class _ChatDetailState extends State<ChatDetail> {
final provider = context.watch<ChatProvider>(); final provider = context.watch<ChatProvider>();
final recentMessages = provider.activedMessages; final recentMessages = provider.activedMessages;
final recentMessageKeys = recentMessages.keys.toList().reversed.toList(); final recentMessageKeys = recentMessages.keys.toList().reversed.toList();
final friend = provider.activedFriend;
this._actived = friend.id;
final session = context.watch<AccountProvider>().activedSession; final accountProvider = context.watch<AccountProvider>();
final session = accountProvider.activedSession;
final meName = accountProvider.activedAccount.name;
final isOnline = session.isActive();
if (this._friend == null) { if (friend == null) {
return Container( return Container(
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0), padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0),
child: Text('Waiting...') child: Text('Waiting...')
); );
} }
final isOnline = session.online == OnlineType.Active;
return Column( return Column(
children: [ children: [
Container( Container(
@ -247,13 +240,13 @@ class _ChatDetailState extends State<ChatDetail> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
this._friend.name, friend.name,
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
SizedBox(height: 6.0), SizedBox(height: 6.0),
Text(this._friend.isClosed Text(friend.isClosed
? lang.unfriended ? lang.unfriended
: (isOnline ? lang.online : lang.offline), : session.onlineLang(lang),
style: TextStyle( style: TextStyle(
color: color.onPrimary.withOpacity(0.5), color: color.onPrimary.withOpacity(0.5),
fontSize: 14.0)) fontSize: 14.0))
@ -290,9 +283,9 @@ class _ChatDetailState extends State<ChatDetail> {
Icons.info, Icons.info,
lang.friendInfo, lang.friendInfo,
UserInfo( UserInfo(
id: 'EH' + this._friend.gid.toUpperCase(), id: 'EH' + friend.gid.toUpperCase(),
name: this._friend.name, name: friend.name,
addr: '0x' + this._friend.addr) addr: '0x' + friend.addr)
); );
} else if (value == 3) { } else if (value == 3) {
print('TODO remark'); print('TODO remark');
@ -302,7 +295,7 @@ class _ChatDetailState extends State<ChatDetail> {
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text(lang.unfriend), title: Text(lang.unfriend),
content: Text(this._friend.name, content: Text(friend.name,
style: TextStyle(color: color.primary)), style: TextStyle(color: color.primary)),
actions: [ actions: [
TextButton( TextButton(
@ -314,7 +307,7 @@ class _ChatDetailState extends State<ChatDetail> {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
Provider.of<ChatProvider>( Provider.of<ChatProvider>(
context, listen: false).friendClose(this._friend.id); context, listen: false).friendClose(friend.id);
if (!isDesktop) { if (!isDesktop) {
Navigator.pop(context); Navigator.pop(context);
} }
@ -326,14 +319,14 @@ class _ChatDetailState extends State<ChatDetail> {
); );
} else if (value == 5) { } else if (value == 5) {
Provider.of<ChatProvider>(context, listen: false).requestCreate( Provider.of<ChatProvider>(context, listen: false).requestCreate(
Request(this._friend.gid, this._friend.addr, this._friend.name, lang.fromContactCard(this._meName))); Request(friend.gid, friend.addr, friend.name, lang.fromContactCard(meName)));
} else if (value == 6) { } else if (value == 6) {
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text(lang.delete + " " + lang.friend), title: Text(lang.delete + " " + lang.friend),
content: Text(this._friend.name, content: Text(friend.name,
style: TextStyle(color: Colors.red)), style: TextStyle(color: Colors.red)),
actions: [ actions: [
TextButton( TextButton(
@ -345,7 +338,7 @@ class _ChatDetailState extends State<ChatDetail> {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
Provider.of<ChatProvider>( Provider.of<ChatProvider>(
context, listen: false).friendDelete(this._friend.id); context, listen: false).friendDelete(friend.id);
if (!isDesktop) { if (!isDesktop) {
Navigator.pop(context); Navigator.pop(context);
} }
@ -361,7 +354,7 @@ class _ChatDetailState extends State<ChatDetail> {
return <PopupMenuEntry<int>>[ return <PopupMenuEntry<int>>[
_menuItem(Color(0xFF6174FF), 2, Icons.qr_code_rounded, lang.friendInfo), _menuItem(Color(0xFF6174FF), 2, Icons.qr_code_rounded, lang.friendInfo),
//_menuItem(color.primary, 3, Icons.turned_in_rounded, lang.remark), //_menuItem(color.primary, 3, Icons.turned_in_rounded, lang.remark),
this._friend.isClosed friend.isClosed
? _menuItem(Color(0xFF6174FF), 5, Icons.send_rounded, lang.addFriend) ? _menuItem(Color(0xFF6174FF), 5, Icons.send_rounded, lang.addFriend)
: _menuItem(Color(0xFF6174FF), 4, Icons.block_rounded, lang.unfriend), : _menuItem(Color(0xFF6174FF), 4, Icons.block_rounded, lang.unfriend),
_menuItem(Colors.red, 6, Icons.delete_rounded, lang.delete), _menuItem(Colors.red, 6, Icons.delete_rounded, lang.delete),
@ -378,11 +371,27 @@ class _ChatDetailState extends State<ChatDetail> {
itemCount: recentMessageKeys.length, itemCount: recentMessageKeys.length,
reverse: true, reverse: true,
itemBuilder: (BuildContext context, index) => ChatMessage( itemBuilder: (BuildContext context, index) => ChatMessage(
name: this._friend.name, name: friend.name,
message: recentMessages[recentMessageKeys[index]], message: recentMessages[recentMessageKeys[index]],
) )
)), )),
if (!this._friend.isClosed) if (session.online == OnlineType.Lost)
InkWell(
onTap: () {
context.read<AccountProvider>().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( Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: Row( child: Row(

8
lib/apps/chat/list.dart

@ -35,7 +35,7 @@ class _ChatListState extends State<ChatList> {
onPressed: () { onPressed: () {
final widget = ChatAddPage(); final widget = ChatAddPage();
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, widget); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(widget);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); Navigator.push(context, MaterialPageRoute(builder: (_) => widget));
} }
@ -61,6 +61,8 @@ class ListChat extends StatelessWidget {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
context.read<AccountProvider>().updateActivedSession(0, SessionType.Chat, friend.id);
context.read<ChatProvider>().updateActivedFriend(friend.id);
if (!isDesktop) { if (!isDesktop) {
Navigator.push( Navigator.push(
context, context,
@ -69,9 +71,7 @@ class ListChat extends StatelessWidget {
), ),
); );
} else { } else {
context.read<AccountProvider>().updateActivedSessionFromList( context.read<AccountProvider>().updateActivedWidget(ChatDetail());
friend.id, SessionType.Chat, ChatDetail()
);
} }
}, },
child: Container( child: Container(

11
lib/apps/chat/models.dart

@ -12,7 +12,6 @@ class Friend {
String remark; String remark;
bool isClosed; bool isClosed;
RelativeTime time; RelativeTime time;
bool online = false;
// new friend from network // new friend from network
Friend(this.gid, this.name, this.addr) { Friend(this.gid, this.name, this.addr) {
@ -21,12 +20,7 @@ class Friend {
Avatar showAvatar({double width = 45.0}) { Avatar showAvatar({double width = 45.0}) {
final avatar = Global.avatarPath + this.gid + '.png'; final avatar = Global.avatarPath + this.gid + '.png';
return Avatar( return Avatar(width: width, name: this.name, avatarPath: avatar);
width: width,
name: this.name,
avatarPath: avatar,
needOnline: false,
);
} }
Friend.fromList(List params) { Friend.fromList(List params) {
@ -65,8 +59,7 @@ class Request {
Avatar showAvatar([double width = 45.0]) { Avatar showAvatar([double width = 45.0]) {
final avatar = Global.avatarPath + this.gid + '.png'; final avatar = Global.avatarPath + this.gid + '.png';
return Avatar( return Avatar(width: width, name: this.name, avatarPath: avatar);
width: width, name: this.name, avatarPath: avatar, needOnline: false);
} }
Request.fromList(List params) { Request.fromList(List params) {

24
lib/apps/chat/provider.dart

@ -34,8 +34,6 @@ class ChatProvider extends ChangeNotifier {
ChatProvider() { ChatProvider() {
// rpc // rpc
rpc.addListener('chat-friend-list', _friendList, false); rpc.addListener('chat-friend-list', _friendList, false);
rpc.addListener('chat-friend-online', _friendOnline, false);
rpc.addListener('chat-friend-offline', _friendOffline, false);
rpc.addListener('chat-friend-info', _friendInfo, false); rpc.addListener('chat-friend-info', _friendInfo, false);
rpc.addListener('chat-friend-update', _friendUpdate, false); rpc.addListener('chat-friend-update', _friendUpdate, false);
rpc.addListener('chat-friend-close', _friendClose, false); rpc.addListener('chat-friend-close', _friendClose, false);
@ -90,7 +88,6 @@ class ChatProvider extends ChangeNotifier {
/// delete a friend. /// delete a friend.
friendClose(int id) { friendClose(int id) {
this.friends[id].isClosed = true; this.friends[id].isClosed = true;
this.friends[id].online = false;
rpc.send('chat-friend-close', [id]); rpc.send('chat-friend-close', [id]);
notifyListeners(); notifyListeners();
@ -182,25 +179,6 @@ class ChatProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
_friendOnline(List params) {
final id = params[0];
if (this.friends.containsKey(id)) {
this.friends[id].online = true;
this.friends[id].addr = params[1];
notifyListeners();
}
}
_friendOffline(List params) {
final id = params[0];
if (this.friends.containsKey(id)) {
if (this.friends[id].gid == params[1]) {
this.friends[id].online = false;
notifyListeners();
}
}
}
_friendInfo(List params) { _friendInfo(List params) {
final id = params[0]; final id = params[0];
this.friends[id] = Friend.fromList(params); this.friends[id] = Friend.fromList(params);
@ -219,7 +197,6 @@ class ChatProvider extends ChangeNotifier {
final id = params[0]; final id = params[0];
if (this.friends.containsKey(id)) { if (this.friends.containsKey(id)) {
this.friends[id].isClosed = true; this.friends[id].isClosed = true;
this.friends[id].online = false;
notifyListeners(); notifyListeners();
} }
} }
@ -295,7 +272,6 @@ class ChatProvider extends ChangeNotifier {
msg.isDelivery = null; // When message create, set is is none; msg.isDelivery = null; // When message create, set is is none;
} }
this.activedMessages[msg.id] = msg; this.activedMessages[msg.id] = msg;
rpc.send('chat-friend-readed', [this.activedFriendId]);
} }
orderFriends(msg.fid); orderFriends(msg.fid);
notifyListeners(); notifyListeners();

4
lib/apps/device/page.dart

@ -152,7 +152,7 @@ class _DevicesPageState extends State<DevicesPage> {
Provider.of<DeviceProvider>(context, listen: false).updateActivedDevice(device.id); Provider.of<DeviceProvider>(context, listen: false).updateActivedDevice(device.id);
final widget = DeviceListenPage(); final widget = DeviceListenPage();
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, widget); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(widget);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); Navigator.push(context, MaterialPageRoute(builder: (_) => widget));
} }
@ -355,7 +355,7 @@ class _DeviceListenPageState extends State<DeviceListenPage> {
onTap: () { onTap: () {
Provider.of<DeviceProvider>(context, listen: false).clear(); Provider.of<DeviceProvider>(context, listen: false).clear();
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, DevicesPage()); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(DevicesPage());
} else { } else {
Navigator.pop(context); Navigator.pop(context);
} }

2
lib/apps/file/page.dart

@ -39,7 +39,7 @@ class _FolderListState extends State<FolderList> {
loadFolder(bool isDesktop, int index) async { loadFolder(bool isDesktop, int index) async {
final widget = FilePage(title: FILE_DIRECTORY[index][0]); final widget = FilePage(title: FILE_DIRECTORY[index][0]);
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, widget); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(widget);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); Navigator.push(context, MaterialPageRoute(builder: (_) => widget));
} }

9
lib/apps/group_chat/detail.dart

@ -203,7 +203,6 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
final recentMessages = provider.activedMessages; final recentMessages = provider.activedMessages;
final recentMessageKeys = recentMessages.keys.toList().reversed.toList(); final recentMessageKeys = recentMessages.keys.toList().reversed.toList();
final meName = context.read<AccountProvider>().activedAccount.name;
this.group = provider.activedGroup; this.group = provider.activedGroup;
final isGroupOwner = provider.isActivedGroupOwner; final isGroupOwner = provider.isActivedGroupOwner;
final isGroupManager = provider.isActivedGroupManager; final isGroupManager = provider.isActivedGroupManager;
@ -214,7 +213,11 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
child: Text('Waiting...') child: Text('Waiting...')
); );
} }
final isOnline = provider.activedOnline;
final accountProvider = context.watch<AccountProvider>();
final session = accountProvider.activedSession;
final meName = accountProvider.activedAccount.name;
final isOnline = session.isActive();
return Column( return Column(
children: [ children: [
@ -245,7 +248,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
SizedBox(height: 6.0), SizedBox(height: 6.0),
Text(this.group.isClosed Text(this.group.isClosed
? lang.unfriended ? lang.unfriended
: (isOnline ? lang.online : lang.offline), : session.onlineLang(lang),
style: TextStyle( style: TextStyle(
color: color.onPrimary.withOpacity(0.5), color: color.onPrimary.withOpacity(0.5),
fontSize: 14.0)) fontSize: 14.0))

16
lib/apps/group_chat/models.dart

@ -108,12 +108,7 @@ class GroupChat {
Avatar showAvatar({double width = 45.0}) { Avatar showAvatar({double width = 45.0}) {
final avatar = Global.avatarPath + this.gid + '.png'; final avatar = Global.avatarPath + this.gid + '.png';
return Avatar( return Avatar(width: width, name: this.name, avatarPath: avatar);
width: width,
name: this.name,
avatarPath: avatar,
needOnline: false,
);
} }
} }
@ -137,12 +132,7 @@ class Request {
Avatar showAvatar([double width = 45.0]) { Avatar showAvatar([double width = 45.0]) {
final avatar = Global.avatarPath + this.gid + '.png'; final avatar = Global.avatarPath + this.gid + '.png';
return Avatar( return Avatar(width: width, name: this.name, avatarPath: avatar);
width: width,
name: this.name,
avatarPath: avatar,
needOnline: false,
);
} }
Request.fromList(List params) { Request.fromList(List params) {
@ -191,7 +181,7 @@ class Member {
width: width, width: width,
name: this.name, name: this.name,
avatarPath: avatar, avatarPath: avatar,
needOnline: false, online: false,
hasNew: this.isManager, hasNew: this.isManager,
hasNewColor: Color(0xFF6174FF), hasNewColor: Color(0xFF6174FF),
); );

9
lib/apps/group_chat/page.dart

@ -35,7 +35,7 @@ class _GroupChatListState extends State<GroupChatList> {
onPressed: () { onPressed: () {
final widget = GroupAddPage(); final widget = GroupAddPage();
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, widget); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(widget);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); Navigator.push(context, MaterialPageRoute(builder: (_) => widget));
} }
@ -61,6 +61,9 @@ class ListChat extends StatelessWidget {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
context.read<GroupChatProvider>().updateActivedGroup(group.id); context.read<GroupChatProvider>().updateActivedGroup(group.id);
context.read<AccountProvider>().updateActivedSession(0, SessionType.Group, group.id);
if (!isDesktop) { if (!isDesktop) {
Navigator.push( Navigator.push(
context, context,
@ -69,9 +72,7 @@ class ListChat extends StatelessWidget {
), ),
); );
} else { } else {
context.read<AccountProvider>().updateActivedSessionFromList( context.read<AccountProvider>().updateActivedWidget(GroupChatDetail());
group.id, SessionType.Group, GroupChatDetail()
);
} }
}, },
child: Container( child: Container(

4
lib/apps/service/list.dart

@ -73,10 +73,10 @@ class ListInnerService extends StatelessWidget {
final widgets = this.callback(); final widgets = this.callback();
if (widgets != null) { if (widgets != null) {
if (this.isDesktop) { if (this.isDesktop) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, widgets[0], widgets[1], widgets[2]); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(widgets[0], widgets[1], widgets[2]);
} else { } else {
if (widgets[2] != null) { if (widgets[2] != null) {
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, null, widgets[1], widgets[2]); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(null, widgets[1], widgets[2]);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widgets[0])); Navigator.push(context, MaterialPageRoute(builder: (_) => widgets[0]));
} }

6
lib/apps/service/models.dart

@ -46,17 +46,17 @@ extension InnerServiceExtension on InnerService {
listHome = GroupChatList(); listHome = GroupChatList();
break; break;
} }
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, coreWidget, listTitle, listHome); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(coreWidget, listTitle, listHome);
} else { } else {
switch (this) { switch (this) {
case InnerService.Files: case InnerService.Files:
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, null, lang.files, FolderList()); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(null, lang.files, FolderList());
break; break;
case InnerService.Assistant: case InnerService.Assistant:
Navigator.push(context, MaterialPageRoute(builder: (_) => AssistantPage())); Navigator.push(context, MaterialPageRoute(builder: (_) => AssistantPage()));
break; break;
case InnerService.GroupChat: case InnerService.GroupChat:
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, null, lang.groupChat, GroupChatList()); Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(null, lang.groupChat, GroupChatList());
break; break;
} }
} }

6
lib/l10n/localizations.dart

@ -51,8 +51,10 @@ abstract class AppLocalizations {
String get contact; String get contact;
String get friend; String get friend;
String get logout; String get logout;
String get online; String get onlineWaiting;
String get offline; String get onlineActive;
String get onlineSuspend;
String get onlineLost;
String get nickname; String get nickname;
String get id; String get id;
String get address; String get address;

8
lib/l10n/localizations_en.dart

@ -27,9 +27,13 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get logout => 'Logout'; String get logout => 'Logout';
@override @override
String get online => 'Online'; String get onlineWaiting => 'Waiting...';
@override @override
String get offline => 'Offline'; String get onlineActive => 'Active';
@override
String get onlineSuspend => 'Suspend';
@override
String get onlineLost => 'Offline';
@override @override
String get nickname => 'Name'; String get nickname => 'Name';
@override @override

8
lib/l10n/localizations_zh.dart

@ -27,9 +27,13 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get logout => '退出'; String get logout => '退出';
@override @override
String get online => '在线'; String get onlineWaiting => '连接中...';
@override @override
String get offline => '离线'; String get onlineActive => '在线';
@override
String get onlineSuspend => '挂起';
@override
String get onlineLost => '离线';
@override @override
String get nickname => '昵称'; String get nickname => '昵称';
@override @override

43
lib/pages/home.dart

@ -96,30 +96,7 @@ class HomeList extends StatefulWidget {
_HomeListState createState() => _HomeListState(); _HomeListState createState() => _HomeListState();
} }
class _HomeListState extends State<HomeList> with SingleTickerProviderStateMixin { class _HomeListState extends State<HomeList> {
bool isProcess = true;
AnimationController controller;
@override
void initState() {
controller = AnimationController(
vsync: this, duration: const Duration(seconds: 8)
)..addListener(() {
if (controller.value == 1.0) {
isProcess = false;
}
setState(() {});
});
controller.forward();
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
_scanQr(bool isDesktop) { _scanQr(bool isDesktop) {
Navigator.push( Navigator.push(
context, context,
@ -135,7 +112,7 @@ class _HomeListState extends State<HomeList> with SingleTickerProviderStateMixin
.systemAppFriendAddNew = false; .systemAppFriendAddNew = false;
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false) Provider.of<AccountProvider>(context, listen: false)
.updateActivedSession(0, widget); .updateActivedWidget(widget);
} else { } else {
Navigator.push( Navigator.push(
context, MaterialPageRoute(builder: (_) => widget)); context, MaterialPageRoute(builder: (_) => widget));
@ -199,7 +176,7 @@ class _HomeListState extends State<HomeList> with SingleTickerProviderStateMixin
} else if (value == 1) { } else if (value == 1) {
final widget = ChatAddPage(); final widget = ChatAddPage();
if (isDesktop) { if (isDesktop) {
provider.updateActivedSession(0, widget); provider.updateActivedWidget(widget);
} else { } else {
provider.systemAppFriendAddNew = false; provider.systemAppFriendAddNew = false;
setState(() {}); setState(() {});
@ -245,13 +222,7 @@ class _HomeListState extends State<HomeList> with SingleTickerProviderStateMixin
), ),
), ),
const SizedBox(height: 10.0), const SizedBox(height: 10.0),
isProcess const Divider(height: 1.0, color: Color(0x40ADB0BB)),
? LinearProgressIndicator(
backgroundColor: Color(0x40ADB0BB),
valueColor: AlwaysStoppedAnimation(color.primary),
value: controller.value,
)
: const Divider(height: 1.0, color: Color(0x40ADB0BB)),
const SizedBox(height: 5.0), const SizedBox(height: 5.0),
Expanded( Expanded(
child: provider.homeShowWidget, child: provider.homeShowWidget,
@ -319,7 +290,7 @@ class DrawerWidget extends StatelessWidget {
final widget = DevicesPage(); final widget = DevicesPage();
if (isDesktop) { if (isDesktop) {
Provider.of<AccountProvider>(context, listen: false) Provider.of<AccountProvider>(context, listen: false)
.updateActivedSession(0, widget); .updateActivedWidget(widget);
} else { } else {
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); Navigator.push(context, MaterialPageRoute(builder: (_) => widget));
} }
@ -387,7 +358,7 @@ class DrawerWidget extends StatelessWidget {
style: TextStyle(fontSize: 16.0)), style: TextStyle(fontSize: 16.0)),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(
null, lang.contact, ChatList() null, lang.contact, ChatList()
); );
}), }),
@ -397,7 +368,7 @@ class DrawerWidget extends StatelessWidget {
style: TextStyle(fontSize: 16.0)), style: TextStyle(fontSize: 16.0)),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
Provider.of<AccountProvider>(context, listen: false).updateActivedSession(0, Provider.of<AccountProvider>(context, listen: false).updateActivedWidget(
null, lang.groups, ServiceList() null, lang.groups, ServiceList()
); );
}), }),

45
lib/provider.dart

@ -207,39 +207,42 @@ class AccountProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
updateActivedSessionFromList(int fid, SessionType type, Widget coreWidget) { updateActivedSession(int id, [SessionType type, int fid]) {
int id = 0; if (fid != null && fid > 0) {
for (int k in this.sessions.keys) {
for (int k in this.sessions.keys) { final v = this.sessions[k];
final v = this.sessions[k]; if (v.type == type && v.fid == fid) {
if (v.type == type && v.fid == fid) { id = k;
id = k; break;
break; }
} }
} }
print("New session: ${id}");
if (id > 0) { if (id > 0) {
if (this.actived > 0) { if (this.actived != id && this.actived > 0) {
rpc.send('session-suspend', [this.actived, this.activedSession.gid]); rpc.send('session-suspend', [this.actived, this.activedSession.gid]);
} }
this.actived = id; this.actived = id;
if (this.activedSession.online == OnlineType.Lost) { final online = this.activedSession.online;
if (online == OnlineType.Lost || online == OnlineType.Suspend) {
if (online == OnlineType.Lost) {
this.activedSession.online = OnlineType.Waiting;
Timer(Duration(seconds: 10), () {
if (this.sessions[id].online == OnlineType.Waiting) {
this.sessions[id].online = OnlineType.Lost;
notifyListeners();
}
});
}
rpc.send('session-connect', [id, this.activedSession.gid]); rpc.send('session-connect', [id, this.activedSession.gid]);
notifyListeners();
} }
} }
} }
updateActivedSession(int id, [Widget coreWidget, String title, Widget homeWidget]) { updateActivedWidget([Widget coreWidget, String title, Widget homeWidget]) {
if (id > 0) { print("update actived widget");
if (this.actived > 0) {
rpc.send('session-suspend', [this.actived, this.activedSession.gid]);
}
this.actived = id;
if (this.activedSession.online == OnlineType.Lost) {
rpc.send('session-connect', [id, this.activedSession.gid]);
}
}
if (homeWidget != null && title != null) { if (homeWidget != null && title != null) {
this.homeShowTitle = title; this.homeShowTitle = title;
this.currentListShow = homeWidget; this.currentListShow = homeWidget;

35
lib/session.dart

@ -76,6 +76,23 @@ class Session {
return [avatar, name, bio]; return [avatar, name, bio];
} }
String onlineLang(AppLocalizations lang) {
switch (this.online) {
case OnlineType.Waiting:
return lang.onlineWaiting;
case OnlineType.Active:
return lang.onlineActive;
case OnlineType.Suspend:
return lang.onlineSuspend;
case OnlineType.Lost:
return lang.onlineLost;
}
}
bool isActive() {
return this.online == OnlineType.Active || this.online == OnlineType.Suspend;
}
List parse(AppLocalizations lang) { List parse(AppLocalizations lang) {
switch (this.type) { switch (this.type) {
case SessionType.Chat: case SessionType.Chat:
@ -89,15 +106,27 @@ class Session {
} }
} }
Avatar showAvatar({double width = 45.0, bool needOnline = true}) { Avatar showAvatar({double width = 45.0}) {
final avatar = Global.avatarPath + this.gid + '.png'; final avatar = Global.avatarPath + this.gid + '.png';
Color color;
switch (this.online) {
case OnlineType.Active:
color = Color(0xFF0EE50A);
break;
case OnlineType.Suspend:
color = Colors.blue;
break;
}
return Avatar( return Avatar(
width: width, width: width,
name: this.name, name: this.name,
avatarPath: avatar, avatarPath: avatar,
online: true, online: this.online != OnlineType.Lost,
needOnline: needOnline, onlineColor: color,
hasNew: !this.lastReaded, hasNew: !this.lastReaded,
loading: this.online == OnlineType.Waiting,
); );
} }

56
lib/widgets/avatar.dart

@ -2,6 +2,7 @@ import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart' show CupertinoActivityIndicator;
class Avatar extends StatelessWidget { class Avatar extends StatelessWidget {
final double width; final double width;
@ -9,9 +10,10 @@ class Avatar extends StatelessWidget {
final Uint8List avatar; final Uint8List avatar;
final String avatarPath; final String avatarPath;
final bool online; final bool online;
final bool needOnline; final Color onlineColor;
final bool hasNew; final bool hasNew;
final Color hasNewColor; final Color hasNewColor;
final bool loading;
const Avatar( const Avatar(
{Key key, {Key key,
@ -20,9 +22,10 @@ class Avatar extends StatelessWidget {
this.avatar, this.avatar,
this.avatarPath, this.avatarPath,
this.online = false, this.online = false,
this.needOnline = true, this.onlineColor = Colors.grey,
this.hasNew = false, this.hasNew = false,
this.hasNewColor = Colors.red, this.hasNewColor = Colors.red,
this.loading = false,
}) })
: super(key: key); : super(key: key);
@ -40,52 +43,31 @@ class Avatar extends StatelessWidget {
} }
return Container( return Container(
width: width, width: this.width,
height: width, height: this.width,
decoration: showAvatar != null decoration: showAvatar != null
? BoxDecoration( ? BoxDecoration(image: DecorationImage(image: showAvatar, fit: BoxFit.cover), borderRadius: BorderRadius.circular(15.0))
image: DecorationImage( : BoxDecoration(color: color.surface, borderRadius: BorderRadius.circular(15.0)),
image: showAvatar,
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(15.0))
: BoxDecoration(
color: color.surface, borderRadius: BorderRadius.circular(15.0)),
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
if (showAvatar == null) if (showAvatar == null)
Text(this.name.length > 0 ? this.name[0].toUpperCase() : "A"), Text(this.name.length > 0 ? this.name[0].toUpperCase() : "A"),
if (this.hasNew) if (this.hasNew)
Positioned( Positioned(top: 0.0, right: 0.0,
top: 0.0, child: Container(width: 9.0, height: 9.0,
right: 0.0, decoration: BoxDecoration(color: this.hasNewColor, shape: BoxShape.circle),
child: Container(
width: 9.0,
height: 9.0,
decoration: BoxDecoration(
color: this.hasNewColor,
shape: BoxShape.circle,
),
), ),
), ),
if (this.needOnline) if (this.online)
Positioned( Positioned(bottom: 0.0, right: 0.0,
bottom: 0.0,
right: 0.0,
child: Container( child: Container(
padding: const EdgeInsets.all(2.0), padding: const EdgeInsets.all(2.0),
decoration: const ShapeDecoration( decoration: ShapeDecoration(color: color.background, shape: CircleBorder()),
color: Colors.white, child: this.loading
shape: CircleBorder(), ? CupertinoActivityIndicator(radius: 5.0, animating: true)
), : Container(width: 9.0, height: 9.0,
child: Container( decoration: BoxDecoration(color: this.onlineColor, shape: BoxShape.circle),
width: 9.0,
height: 9.0,
decoration: BoxDecoration(
color: online ? const Color(0xFF0EE50A) : const Color(0xFFEDEDED),
shape: BoxShape.circle,
),
), ),
), ),
), ),

13
lib/widgets/chat_message.dart

@ -193,12 +193,7 @@ class ChatMessage extends StatelessWidget {
Icons.person_rounded, Icons.person_rounded,
lang.contact, lang.contact,
Column(children: [ Column(children: [
Avatar( Avatar(width: 100.0, name: infos[0], avatarPath: infos[3]),
width: 100.0,
name: infos[0],
avatarPath: infos[3],
needOnline: false
),
const SizedBox(height: 10.0), const SizedBox(height: 10.0),
Text(infos[0]), Text(infos[0]),
const SizedBox(height: 10.0), const SizedBox(height: 10.0),
@ -251,11 +246,7 @@ class ChatMessage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row(children: [ Row(children: [
Avatar( Avatar(width: 40.0, name: infos[0], avatarPath: infos[3]),
width: 40.0,
name: infos[0],
avatarPath: infos[3],
needOnline: false),
Container( Container(
width: 135.0, width: 135.0,
padding: const EdgeInsets.only(left: 10.0), padding: const EdgeInsets.only(left: 10.0),

13
lib/widgets/default_home_show.dart

@ -9,7 +9,9 @@ import 'package:esse/provider.dart';
import 'package:esse/session.dart'; import 'package:esse/session.dart';
import 'package:esse/apps/chat/detail.dart'; import 'package:esse/apps/chat/detail.dart';
import 'package:esse/apps/chat/provider.dart';
import 'package:esse/apps/assistant/page.dart'; import 'package:esse/apps/assistant/page.dart';
import 'package:esse/apps/file/page.dart';
class DefaultHomeShow extends StatelessWidget { class DefaultHomeShow extends StatelessWidget {
const DefaultHomeShow({Key key}): super(key: key); const DefaultHomeShow({Key key}): super(key: key);
@ -63,6 +65,7 @@ class _SessionWidget extends StatelessWidget {
switch (session.type) { switch (session.type) {
case SessionType.Chat: case SessionType.Chat:
context.read<ChatProvider>().updateActivedFriend(session.fid);
if (!isDesktop) { if (!isDesktop) {
coreWidget = ChatPage(); coreWidget = ChatPage();
} else { } else {
@ -78,8 +81,14 @@ class _SessionWidget extends StatelessWidget {
coreWidget = AssistantDetail(); coreWidget = AssistantDetail();
} }
break; break;
case SessionType.Files:
listTitle = lang.files;
listWidget = FolderList();
break;
} }
context.read<AccountProvider>().updateActivedSession(session.id);
if (!isDesktop) { if (!isDesktop) {
Navigator.push( Navigator.push(
context, context,
@ -88,8 +97,8 @@ class _SessionWidget extends StatelessWidget {
), ),
); );
} else { } else {
context.read<AccountProvider>().updateActivedSession( context.read<AccountProvider>().updateActivedWidget(
session.id, coreWidget, listTitle, listWidget coreWidget, listTitle, listWidget
); );
} }
}, },

18
src/apps/chat/layer.rs

@ -117,8 +117,8 @@ pub(crate) async fn handle(
let _ = Friend::addr_update(&db, f.id, &addr); let _ = Friend::addr_update(&db, f.id, &addr);
drop(db); drop(db);
} }
// 4. online to UI. // 4. online to UI. TODO
results.rpcs.push(rpc::friend_online(mgid, f.id, addr));
// 5. connected. // 5. connected.
let msg = conn_res_message(&layer, &mgid, addr).await?; let msg = conn_res_message(&layer, &mgid, addr).await?;
results.layers.push((mgid, fgid, msg)); results.layers.push((mgid, fgid, msg));
@ -206,7 +206,6 @@ pub(crate) async fn handle(
for (mgid, running) in &mut layer.runnings { for (mgid, running) in &mut layer.runnings {
let peers = running.peer_leave(&addr); let peers = running.peer_leave(&addr);
for (fgid, fid) in peers { for (fgid, fid) in peers {
results.rpcs.push(rpc::friend_offline(*mgid, fid, &fgid));
results results
.rpcs .rpcs
.push(crate::apps::group_chat::rpc::group_offline( .push(crate::apps::group_chat::rpc::group_offline(
@ -288,8 +287,9 @@ pub(crate) async fn handle(
let db = chat_db(&layer.base, &mgid)?; let db = chat_db(&layer.base, &mgid)?;
Friend::addr_update(&db, fid, &addr)?; Friend::addr_update(&db, fid, &addr)?;
drop(db); drop(db);
// 5. online to UI. // 5. online to UI.
results.rpcs.push(rpc::friend_online(mgid, fid, addr));
layer.group.write().await.status( layer.group.write().await.status(
&mgid, &mgid,
StatusEvent::SessionFriendOnline(fgid), StatusEvent::SessionFriendOnline(fgid),
@ -310,7 +310,7 @@ pub(crate) async fn handle(
sid, sid,
friend.id, friend.id,
)?; )?;
results.rpcs.push(rpc::friend_online(mgid, friend.id, addr));
layer.group.write().await.status( layer.group.write().await.status(
&mgid, &mgid,
StatusEvent::SessionFriendOnline(fgid), StatusEvent::SessionFriendOnline(fgid),
@ -393,8 +393,8 @@ pub(crate) async fn handle(
let db = chat_db(&layer.base, &mgid)?; let db = chat_db(&layer.base, &mgid)?;
Friend::addr_update(&db, fid, &addr)?; Friend::addr_update(&db, fid, &addr)?;
drop(db); drop(db);
// 5. online to UI. // 5. online to UI. TODO
results.rpcs.push(rpc::friend_online(mgid, fid, addr));
// 6. connected. // 6. connected.
let msg = conn_res_message(&layer, &mgid, addr).await?; let msg = conn_res_message(&layer, &mgid, addr).await?;
results.layers.push((mgid, fgid, msg)); results.layers.push((mgid, fgid, msg));
@ -418,7 +418,6 @@ pub(crate) async fn handle(
sid, sid,
friend.id, friend.id,
)?; )?;
results.rpcs.push(rpc::friend_online(mgid, friend.id, addr));
layer.group.write().await.status( layer.group.write().await.status(
&mgid, &mgid,
StatusEvent::SessionFriendOnline(fgid), StatusEvent::SessionFriendOnline(fgid),
@ -629,7 +628,7 @@ impl LayerEvent {
layer layer
.running_mut(&mgid)? .running_mut(&mgid)?
.check_add_online(fgid, Online::Direct(addr), sid, fid)?; .check_add_online(fgid, Online::Direct(addr), sid, fid)?;
results.rpcs.push(rpc::friend_online(mgid, fid, addr));
let data = postcard::to_allocvec(&LayerEvent::OnlinePong).unwrap_or(vec![]); let data = postcard::to_allocvec(&LayerEvent::OnlinePong).unwrap_or(vec![]);
let msg = SendType::Event(0, addr, data); let msg = SendType::Event(0, addr, data);
results.layers.push((mgid, fgid, msg)); results.layers.push((mgid, fgid, msg));
@ -643,7 +642,6 @@ impl LayerEvent {
layer layer
.running_mut(&mgid)? .running_mut(&mgid)?
.check_add_online(fgid, Online::Direct(addr), sid, fid)?; .check_add_online(fgid, Online::Direct(addr), sid, fid)?;
results.rpcs.push(rpc::friend_online(mgid, fid, addr));
} }
LayerEvent::Close => { LayerEvent::Close => {
layer.group.write().await.broadcast( layer.group.write().await.broadcast(

10
src/apps/chat/rpc.rs

@ -17,16 +17,6 @@ use crate::storage::{chat_db, delete_avatar, session_db};
use super::layer::LayerEvent; use super::layer::LayerEvent;
use super::{Friend, Message, MessageType, Request}; use super::{Friend, Message, MessageType, Request};
#[inline]
pub(crate) fn friend_online(mgid: GroupId, fid: i64, addr: PeerAddr) -> RpcParam {
rpc_response(0, "chat-friend-online", json!([fid, addr.to_hex()]), mgid)
}
#[inline]
pub(crate) fn friend_offline(mgid: GroupId, fid: i64, gid: &GroupId) -> RpcParam {
rpc_response(0, "chat-friend-offline", json!([fid, gid.to_hex()]), mgid)
}
#[inline] #[inline]
pub(crate) fn friend_info(mgid: GroupId, friend: &Friend) -> RpcParam { pub(crate) fn friend_info(mgid: GroupId, friend: &Friend) -> RpcParam {
rpc_response(0, "chat-friend-info", json!(friend.to_rpc()), mgid) rpc_response(0, "chat-friend-info", json!(friend.to_rpc()), mgid)

11
src/event.rs

@ -487,9 +487,7 @@ impl StatusEvent {
StatusEvent::SessionFriendOnline(rgid) => { StatusEvent::SessionFriendOnline(rgid) => {
let db = chat_db(group.base(), &gid)?; let db = chat_db(group.base(), &gid)?;
if let Some(f) = Friend::get_it(&db, &rgid)? { if let Some(f) = Friend::get_it(&db, &rgid)? {
results // TODO
.rpcs
.push(chat_rpc::friend_online(gid, f.id, f.addr));
} }
} }
StatusEvent::SessionFriendOffline(rgid) => { StatusEvent::SessionFriendOffline(rgid) => {
@ -503,12 +501,7 @@ impl StatusEvent {
tdn::smol::spawn(async move { tdn::smol::spawn(async move {
if let Ok(running) = layer_lock.write().await.running_mut(&ggid) { if let Ok(running) = layer_lock.write().await.running_mut(&ggid) {
if running.check_offline(&rgid, &addr) { if running.check_offline(&rgid, &addr) {
let msg = SendMessage::Rpc( // TODO
uid,
chat_rpc::friend_offline(ggid, rid, &rgid),
true,
);
let _ = sender.send(msg).await;
} }
} }
}) })

Loading…
Cancel
Save