mirror of https://github.com/CympleTech/ESSE.git
43 changed files with 1891 additions and 1567 deletions
@ -0,0 +1,481 @@
@@ -0,0 +1,481 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
import 'package:esse/utils/adaptive.dart'; |
||||
import 'package:esse/utils/toast.dart'; |
||||
import 'package:esse/utils/pick_image.dart'; |
||||
import 'package:esse/utils/pick_file.dart'; |
||||
import 'package:esse/l10n/localizations.dart'; |
||||
import 'package:esse/models/friend.dart'; |
||||
import 'package:esse/models/message.dart'; |
||||
import 'package:esse/widgets/emoji.dart'; |
||||
import 'package:esse/widgets/shadow_dialog.dart'; |
||||
import 'package:esse/widgets/audio_recorder.dart'; |
||||
import 'package:esse/widgets/user_info.dart'; |
||||
import 'package:esse/widgets/chat_message.dart'; |
||||
import 'package:esse/provider/account.dart'; |
||||
import 'package:esse/global.dart'; |
||||
|
||||
class AssistantPage extends StatefulWidget { |
||||
const AssistantPage({Key key}) : super(key: key); |
||||
|
||||
@override |
||||
_AssistantPageState createState() => _AssistantPageState(); |
||||
} |
||||
|
||||
class _AssistantPageState extends State<AssistantPage> { |
||||
TextEditingController textController = TextEditingController(); |
||||
FocusNode textFocus = FocusNode(); |
||||
bool emojiShow = false; |
||||
bool sendShow = false; |
||||
bool menuShow = false; |
||||
bool recordShow = false; |
||||
String _recordName; |
||||
|
||||
@override |
||||
initState() { |
||||
super.initState(); |
||||
textFocus.addListener(() { |
||||
if (textFocus.hasFocus) { |
||||
setState(() { |
||||
emojiShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
_generateRecordPath() { |
||||
this._recordName = DateTime.now().millisecondsSinceEpoch.toString() + '_assistant.m4a'; |
||||
} |
||||
|
||||
void _sendMessage() async { |
||||
if (textController.text.length < 1) { |
||||
return; |
||||
} |
||||
|
||||
// TODO send |
||||
|
||||
setState(() { |
||||
textController.text = ''; |
||||
textFocus.requestFocus(); |
||||
|
||||
emojiShow = false; |
||||
sendShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
} |
||||
|
||||
void _selectEmoji(value) { |
||||
textController.text += value; |
||||
} |
||||
|
||||
void _sendImage() async { |
||||
final image = await pickImage(); |
||||
if (image != null) { |
||||
// TODO send |
||||
} |
||||
setState(() { |
||||
textFocus.requestFocus(); |
||||
emojiShow = false; |
||||
sendShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
} |
||||
|
||||
void _sendFile() async { |
||||
final file = await pickFile(); |
||||
if (file != null) { |
||||
// TODO send |
||||
} |
||||
setState(() { |
||||
textFocus.requestFocus(); |
||||
emojiShow = false; |
||||
sendShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
} |
||||
|
||||
void _sendRecord(int time) async { |
||||
final raw = Message.rawRecordName(time, _recordName); |
||||
// TODO send |
||||
|
||||
setState(() { |
||||
textFocus.requestFocus(); |
||||
emojiShow = false; |
||||
sendShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
} |
||||
|
||||
void _sendContact(ColorScheme color, AppLocalizations lang, friends) { |
||||
showShadowDialog( |
||||
context, |
||||
Icons.person_rounded, |
||||
'Contact', |
||||
Column(children: [ |
||||
Container( |
||||
height: 40.0, |
||||
decoration: BoxDecoration( |
||||
color: color.surface, |
||||
borderRadius: BorderRadius.circular(15.0)), |
||||
child: TextField( |
||||
autofocus: false, |
||||
textInputAction: TextInputAction.search, |
||||
textAlignVertical: TextAlignVertical.center, |
||||
style: TextStyle(fontSize: 14.0), |
||||
onSubmitted: (value) { |
||||
toast(context, 'WIP...'); |
||||
}, |
||||
decoration: InputDecoration( |
||||
hintText: lang.search, |
||||
hintStyle: TextStyle(color: color.onPrimary.withOpacity(0.5)), |
||||
border: InputBorder.none, |
||||
contentPadding: |
||||
EdgeInsets.only(left: 15.0, right: 15.0, bottom: 15.0), |
||||
), |
||||
), |
||||
), |
||||
SizedBox(height: 15.0), |
||||
Column( |
||||
children: friends.map<Widget>((contact) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () async { |
||||
// TODO send |
||||
Navigator.of(context).pop(); |
||||
setState(() { |
||||
textFocus.requestFocus(); |
||||
emojiShow = false; |
||||
sendShow = false; |
||||
menuShow = false; |
||||
recordShow = false; |
||||
}); |
||||
}, |
||||
child: Padding( |
||||
padding: const EdgeInsets.symmetric( |
||||
horizontal: 20.0, vertical: 14.0), |
||||
child: Row( |
||||
children: [ |
||||
contact.showAvatar(), |
||||
SizedBox(width: 15.0), |
||||
Text(contact.name, style: TextStyle(fontSize: 16.0)), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}).toList()) |
||||
])); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final color = Theme.of(context).colorScheme; |
||||
final lang = AppLocalizations.of(context); |
||||
final isDesktop = isDisplayDesktop(context); |
||||
|
||||
final recentMessages = {}; |
||||
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('esse', |
||||
style: TextStyle(fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 6.0), |
||||
Text(lang.online, |
||||
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<int>( |
||||
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 |
||||
} else if (value == 2) { |
||||
showShadowDialog( |
||||
context, |
||||
Icons.info, |
||||
lang.friendInfo, |
||||
UserInfo( |
||||
id: 'ES0000000000000000000000000000000000000000000000000000000000000000', |
||||
name: 'esse', |
||||
addr: '0x0000000000000000000000000000000000000000000000000000000000000000') |
||||
); |
||||
} |
||||
}, |
||||
itemBuilder: (context) { |
||||
return <PopupMenuEntry<int>>[ |
||||
_menuItem(color.primary, 1, Icons.vertical_align_top_rounded, lang.cancelTop), |
||||
_menuItem(color.primary, 2, Icons.qr_code_rounded, lang.friendInfo), |
||||
]; |
||||
}, |
||||
) |
||||
] |
||||
), |
||||
), |
||||
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: 'esse', |
||||
message: recentMessages[recentMessageKeys[index]], |
||||
) |
||||
)), |
||||
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, |
||||
), |
||||
), |
||||
), |
||||
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.primary, |
||||
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: <Widget>[ |
||||
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<AccountProvider>().friends.values), |
||||
bgColor: color.surface, |
||||
iconColor: color.primary), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class ExtensionButton extends StatelessWidget { |
||||
final String text; |
||||
final IconData icon; |
||||
final Function action; |
||||
final Color bgColor; |
||||
final Color iconColor; |
||||
|
||||
const ExtensionButton({ |
||||
Key key, |
||||
this.icon, |
||||
this.text, |
||||
this.action, |
||||
this.bgColor, |
||||
this.iconColor, |
||||
}) : super(key: key); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
onTap: action, |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Container( |
||||
padding: const EdgeInsets.all(10.0), |
||||
decoration: BoxDecoration( |
||||
color: bgColor, |
||||
borderRadius: BorderRadius.circular(15.0), |
||||
), |
||||
child: Icon(icon, color: iconColor, size: 36.0)), |
||||
SizedBox(height: 5.0), |
||||
Text(text, style: TextStyle(fontSize: 14.0)), |
||||
], |
||||
)); |
||||
} |
||||
} |
||||
|
||||
Widget _menuItem(Color color, int value, IconData icon, String text) { |
||||
return PopupMenuItem<int>( |
||||
value: value, |
||||
child: Row( |
||||
children: [ |
||||
Icon(icon, color: color), |
||||
Padding( |
||||
padding: const EdgeInsets.only(left: 20.0, right: 10.0), |
||||
child: Text(text, style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
) |
||||
] |
||||
), |
||||
); |
||||
} |
@ -1,6 +1,117 @@
@@ -1,6 +1,117 @@
|
||||
import 'package:esse/utils/relative_time.dart'; |
||||
import 'package:esse/widgets/avatar.dart'; |
||||
import 'package:esse/global.dart'; |
||||
|
||||
class Friend { |
||||
int id; |
||||
String gid; |
||||
String name; |
||||
String addr; |
||||
String remark; |
||||
bool isTop; |
||||
bool isClosed; |
||||
RelativeTime lastMessageTime; |
||||
String lastMessageContent; |
||||
bool lastMessageReaded; |
||||
bool online = false; |
||||
|
||||
// new friend from network |
||||
Friend(this.gid, this.name, this.addr) { |
||||
this.isTop = false; |
||||
this.isClosed = false; |
||||
this.lastMessageTime = RelativeTime(); |
||||
this.lastMessageContent = ''; |
||||
this.lastMessageReaded = true; |
||||
} |
||||
|
||||
Avatar showAvatar({double width = 45.0, bool needOnline = true}) { |
||||
final avatar = Global.avatarPath + this.gid + '.png'; |
||||
return Avatar( |
||||
width: width, |
||||
name: this.name, |
||||
avatarPath: avatar, |
||||
online: this.online, |
||||
needOnline: needOnline, |
||||
hasNew: !this.lastMessageReaded, |
||||
); |
||||
} |
||||
|
||||
updateLastMessage(Message msg, bool isReaded) { |
||||
this.lastMessageTime = msg.time; |
||||
this.lastMessageContent = msg.shortShow(); |
||||
this.lastMessageReaded = isReaded; |
||||
} |
||||
|
||||
static String betterPrint(String info) { |
||||
if (info == null) { |
||||
return ''; |
||||
} |
||||
final len = info.length; |
||||
if (len > 8) { |
||||
return info.substring(0, 8) + '...' + info.substring(len - 6, len); |
||||
} else { |
||||
return info; |
||||
} |
||||
} |
||||
|
||||
Friend.fromList(List params) { |
||||
this.id = params[0]; |
||||
this.gid = params[1]; |
||||
this.addr = params[2]; |
||||
this.name = params[3]; |
||||
this.remark = params[4]; |
||||
this.isTop = params[5] == "1"; |
||||
this.isClosed = params[6] == "1"; |
||||
this.lastMessageTime = RelativeTime.fromInt(params[7]); |
||||
this.lastMessageContent = params[8]; |
||||
this.lastMessageReaded = params[9]; |
||||
this.online = params[10] == "1"; |
||||
} |
||||
} |
||||
|
||||
class Request { |
||||
int id; |
||||
String gid; |
||||
String addr; |
||||
String name; |
||||
String remark; |
||||
bool isMe = true; |
||||
bool ok = false; |
||||
bool over = false; |
||||
bool isDelivery = false; |
||||
RelativeTime time = RelativeTime(); |
||||
|
||||
Request(this.gid, this.addr, this.name, this.remark); |
||||
|
||||
overIt(bool isOk) { |
||||
this.over = true; |
||||
this.ok = isOk; |
||||
} |
||||
|
||||
Friend toFriend(String gid) { |
||||
return Friend(gid, this.name, this.addr); |
||||
} |
||||
|
||||
Avatar showAvatar([double width = 45.0]) { |
||||
final avatar = Global.avatarPath + this.gid + '.png'; |
||||
return Avatar( |
||||
width: width, name: this.name, avatarPath: avatar, needOnline: false); |
||||
} |
||||
|
||||
Request.fromList(List params) { |
||||
this.id = params[0]; |
||||
this.gid = params[1]; |
||||
this.addr = params[2]; |
||||
this.name = params[3]; |
||||
this.remark = params[4]; |
||||
this.isMe = params[5]; |
||||
this.ok = params[6]; |
||||
this.over = params[7]; |
||||
this.isDelivery = params[8]; |
||||
this.time = RelativeTime.fromInt(params[9]); |
||||
} |
||||
} |
||||
|
||||
enum MessageType { |
||||
String, |
||||
Image, |
@ -0,0 +1,348 @@
@@ -0,0 +1,348 @@
|
||||
import 'dart:async'; |
||||
import "dart:collection"; |
||||
import 'dart:typed_data'; |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'package:esse/utils/relative_time.dart'; |
||||
import 'package:esse/global.dart'; |
||||
import 'package:esse/rpc.dart'; |
||||
|
||||
import 'package:esse/apps/chat/models.dart'; |
||||
import 'package:esse/apps/chat/detail.dart'; |
||||
|
||||
class ChatProvider extends ChangeNotifier { |
||||
Map<int, Friend> friends = {}; // all friends. friends need Re-order. |
||||
|
||||
int activedFriendId; // actived friend's id. |
||||
Friend get activedFriend => this.friends[this.activedFriendId]; |
||||
|
||||
List<int> orderKeys = []; // ordered chat friends with last message. |
||||
|
||||
Map<int, RelativeTime> topKeys = {}; // Set toped friends. |
||||
|
||||
/// all requests. request have order. |
||||
SplayTreeMap<int, Request> requests = SplayTreeMap(); |
||||
|
||||
/// current show messages. init number is 100, message have order. |
||||
SplayTreeMap<int, Message> activedMessages = SplayTreeMap(); |
||||
|
||||
void orderFriends(int id) { |
||||
if (this.orderKeys.length == 0 || this.orderKeys[0] != id) { |
||||
this.orderKeys.remove(id); |
||||
this.orderKeys.insert(0, id); |
||||
} |
||||
} |
||||
|
||||
ChatProvider() { |
||||
// rpc |
||||
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-update', _friendUpdate, false); |
||||
rpc.addListener('chat-friend-close', _friendClose, false); |
||||
rpc.addListener('chat-request-list', _requestList, false); |
||||
rpc.addListener('chat-request-create', _requestCreate, true); |
||||
rpc.addListener('chat-request-delivery', _requestDelivery, false); |
||||
rpc.addListener('chat-request-agree', _requestAgree, false); |
||||
rpc.addListener('chat-request-reject', _requestReject, false); |
||||
rpc.addListener('chat-request-delete', _requestDelete, false); |
||||
rpc.addListener('chat-message-list', _messageList, false); |
||||
rpc.addListener('chat-message-create', _messageCreate, true); |
||||
rpc.addListener('chat-message-delete', _messageDelete, false); |
||||
rpc.addListener('chat-message-delivery', _messageDelivery, false); |
||||
} |
||||
|
||||
clear() { |
||||
this.activedFriendId = null; |
||||
this.friends.clear(); |
||||
this.orderKeys.clear(); |
||||
this.requests.clear(); |
||||
this.activedMessages.clear(); |
||||
} |
||||
|
||||
updateActived() { |
||||
this.clear(); |
||||
|
||||
// load friends. |
||||
rpc.send('chat-friend-list', []); |
||||
} |
||||
|
||||
updateActivedFriend(int id) { |
||||
this.activedFriendId = id; |
||||
this.activedMessages.clear(); |
||||
this.friends[id].lastMessageReaded = true; |
||||
|
||||
rpc.send('chat-message-list', [this.activedFriendId]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
clearActivedFriend() { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendUpdate(int id, {String remark, bool isTop}) { |
||||
if (remark != null) { |
||||
this.friends[id].remark = remark; |
||||
} |
||||
|
||||
if (isTop != null) { |
||||
this.friends[id].isTop = isTop; |
||||
if (isTop) { |
||||
this.topKeys[id] = this.friends[id].lastMessageTime; |
||||
} else { |
||||
this.topKeys.remove(id); |
||||
} |
||||
} |
||||
|
||||
final friend = this.friends[id]; |
||||
rpc.send('chat-friend-update', [id, friend.remark, friend.isTop]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendClose(int id) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
|
||||
rpc.send('chat-friend-close', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendDelete(int id) { |
||||
if (id == this.activedFriendId) { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
} |
||||
|
||||
this.friends.remove(id); |
||||
this.orderKeys.remove(id); |
||||
this.topKeys.remove(id); |
||||
|
||||
rpc.send('chat-friend-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list all request. |
||||
requestList() { |
||||
rpc.send('chat-request-list', []); |
||||
} |
||||
|
||||
/// clear the memory requests. |
||||
requestClear() { |
||||
this.requests.clear(); |
||||
} |
||||
|
||||
/// create a request for friend. |
||||
requestCreate(Request req) { |
||||
this.requests.remove(req.id); |
||||
|
||||
rpc.send('chat-request-create', [req.gid, req.addr, req.name, req.remark]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// agree a request for friend. |
||||
requestAgree(int id) { |
||||
this.requests[id].overIt(true); |
||||
|
||||
rpc.send('chat-request-agree', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// reject a request for friend. |
||||
requestReject(int id) { |
||||
this.requests[id].overIt(false); |
||||
|
||||
rpc.send('chat-request-reject', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delte a request for friend. |
||||
requestDelete(int id) { |
||||
this.requests.remove(id); |
||||
|
||||
rpc.send('chat-request-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// create a message. need core server handle this message. |
||||
/// and then this message will show in message list. |
||||
messageCreate(Message msg) { |
||||
final fgid = this.friends[msg.fid].gid; |
||||
|
||||
rpc.send('chat-message-create', [msg.fid, fgid, msg.type.toInt(), msg.content]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a message. |
||||
messageDelete(int id) { |
||||
this.activedMessages.remove(id); |
||||
|
||||
rpc.send('chat-message-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list all friends. |
||||
_friendList(List params) async { |
||||
this.orderKeys.clear(); |
||||
this.friends.clear(); |
||||
|
||||
params.forEach((params) { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
this.orderKeys.add(id); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys[id] = this.friends[id].lastMessageTime; |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_friendOnline(List params) async { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = true; |
||||
this.friends[id].addr = params[1]; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendOffline(List params) async { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendInfo(List params) async { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys[id] = this.friends[id].lastMessageTime; |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_friendUpdate(List params) async { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].isTop = params[1]; |
||||
this.friends[id].remark = params[2]; |
||||
|
||||
if (params[1]) { |
||||
this.topKeys[id] = this.friends[id].lastMessageTime; |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendClose(List params) async { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// list requests for friend. |
||||
_requestList(List params) async { |
||||
this.requests.clear(); |
||||
params.forEach((param) { |
||||
if (param.length == 10) { |
||||
this.requests[param[0]] = Request.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// receive a request for friend. |
||||
_requestCreate(List params) async { |
||||
this.requests[params[0]] = Request.fromList(params); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// created request had delivery. |
||||
_requestDelivery(List params) async { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// request for friend receive agree. |
||||
_requestAgree(List params) async { |
||||
final id = params[0]; // request's id. |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(true); |
||||
} |
||||
var friend = Friend.fromList(params[1]); |
||||
this.friends[friend.id] = friend; |
||||
orderFriends(friend.id); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// request for friend receive reject. |
||||
_requestReject(List params) async { |
||||
final id = params[0]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(false); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_requestDelete(List params) async { |
||||
this.requests.remove(params[0]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list message with friend. |
||||
_messageList(List params) async { |
||||
params.forEach((param) { |
||||
if (param.length == 8) { |
||||
this.activedMessages[param[0]] = Message.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// friend send message to me. |
||||
_messageCreate(List params) async { |
||||
final msg = Message.fromList(params); |
||||
if (msg.fid == this.activedFriendId) { |
||||
if (!msg.isDelivery) { |
||||
msg.isDelivery = null; // When message create, set is is none; |
||||
} |
||||
this.friends[msg.fid].updateLastMessage(msg, true); |
||||
this.activedMessages[msg.id] = msg; |
||||
rpc.send('chat-friend-readed', [this.activedFriendId]); |
||||
} else { |
||||
if (this.friends.containsKey(msg.fid)) { |
||||
this.friends[msg.fid].updateLastMessage(msg, false); |
||||
} |
||||
} |
||||
orderFriends(msg.fid); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_messageDelete(List params) { |
||||
this.activedMessages.remove(params[0]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// created message had delivery. |
||||
_messageDelivery(List params) async { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.activedMessages.containsKey(id)) { |
||||
this.activedMessages[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'package:esse/global.dart'; |
||||
import 'package:esse/rpc.dart'; |
||||
|
||||
import 'package:esse/apps/device/models.dart'; |
||||
|
||||
class DeviceProvider extends ChangeNotifier { |
||||
Map<int, Device> devices = {}; |
||||
DeviceStatus status = DeviceStatus(); |
||||
|
||||
DeviceProvider() { |
||||
// rpc. |
||||
rpc.addListener('device-list', _list, false); |
||||
rpc.addListener('device-create', _create, true); |
||||
rpc.addListener('device-delete', _delete, false); |
||||
rpc.addListener('device-online', _online, false); |
||||
rpc.addListener('device-offline', _offline, false); |
||||
rpc.addListener('device-status', _status, false); |
||||
} |
||||
|
||||
clear() { |
||||
this.status = DeviceStatus(); |
||||
} |
||||
|
||||
updateActived() { |
||||
this.clear(); |
||||
|
||||
// load devices. |
||||
rpc.send('device-list', []); |
||||
} |
||||
|
||||
updateActivedDevice(int id) { |
||||
this.clear(); |
||||
|
||||
// load status. |
||||
rpc.send('device-status', [this.devices[id].addr]); |
||||
} |
||||
|
||||
connect(String addr) { |
||||
rpc.send('device-connect', [addr]); |
||||
} |
||||
|
||||
delete(int id) { |
||||
this.devices.remove(id); |
||||
rpc.send('device-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_list(List params) { |
||||
this.devices.clear(); |
||||
params.forEach((params) { |
||||
if (params.length == 6) { |
||||
this.devices[params[0]] = Device.fromList(params); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_create(List params) { |
||||
if (params.length == 6) { |
||||
this.devices[params[0]] = Device.fromList(params); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_delete(List params) { |
||||
final id = params[0]; |
||||
if (this.devices.containsKey(id)) { |
||||
this.devices.remove(id); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_online(List params) { |
||||
final id = params[0]; |
||||
if (this.devices.containsKey(id)) { |
||||
this.devices[id].online = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_offline(List params) { |
||||
final id = params[0]; |
||||
if (this.devices.containsKey(id)) { |
||||
this.devices[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_status(List params) { |
||||
if (params.length == 9) { |
||||
this.status = DeviceStatus.fromList(params); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,247 @@
@@ -0,0 +1,247 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
import 'package:esse/utils/adaptive.dart'; |
||||
import 'package:esse/utils/file_image.dart'; |
||||
import 'package:esse/l10n/localizations.dart'; |
||||
import 'package:esse/provider.dart'; |
||||
|
||||
class FolderList extends StatefulWidget { |
||||
@override |
||||
_FolderListState createState() => _FolderListState(); |
||||
} |
||||
|
||||
const List FILE_DIRECTORY = [ |
||||
["Recent", Icons.label_rounded], |
||||
["Starred", Icons.star_rounded], |
||||
["Home", Icons.home_rounded], |
||||
["Documents", Icons.my_library_books_rounded], |
||||
["Pictures", Icons.collections_rounded], |
||||
["Music", Icons.my_library_music_rounded], |
||||
["Videos", Icons.video_collection_rounded], |
||||
["Trash", Icons.auto_delete_rounded], |
||||
]; |
||||
|
||||
class _FolderListState extends State<FolderList> { |
||||
int chooseIndex = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
Future.delayed(Duration.zero, () { |
||||
final isDesktop = isDisplayDesktop(context); |
||||
if (isDesktop) { |
||||
loadFolder(true, chooseIndex); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
loadFolder(bool isDesktop, int index) async { |
||||
final widget = FilePage(title: FILE_DIRECTORY[index][0]); |
||||
if (isDesktop) { |
||||
Provider.of<AccountProvider>(context, listen: false).updateActivedApp(widget); |
||||
} else { |
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); |
||||
} |
||||
} |
||||
|
||||
changeItem(int index, bool isDesktop) { |
||||
setState(() { |
||||
chooseIndex = index; |
||||
loadFolder(isDesktop, index); |
||||
}); |
||||
} |
||||
|
||||
Widget item(int index, ColorScheme color, bool isDesktop) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () => changeItem(index, isDesktop), |
||||
child: SizedBox( |
||||
height: 55.0, |
||||
child: Row( |
||||
children: [ |
||||
Container( |
||||
width: 45.0, |
||||
height: 45.0, |
||||
margin: const EdgeInsets.only(left: 20.0, right: 15.0), |
||||
child: Icon(FILE_DIRECTORY[index][1], size: 24.0, color: color.primary), |
||||
decoration: BoxDecoration( |
||||
color: color.surface, |
||||
borderRadius: BorderRadius.circular(15.0) |
||||
), |
||||
), |
||||
chooseIndex == index |
||||
? Text(FILE_DIRECTORY[index][0], style: TextStyle(fontSize: 16.0, color: color.primary)) |
||||
: Text(FILE_DIRECTORY[index][0], style: TextStyle(fontSize: 16.0)) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final color = Theme.of(context).colorScheme; |
||||
final isDesktop = isDisplayDesktop(context); |
||||
|
||||
return Expanded( |
||||
child: ListView.builder( |
||||
itemCount: FILE_DIRECTORY.length, |
||||
itemBuilder: (BuildContext ctx, int index) => item(index, color, isDesktop), |
||||
)); |
||||
} |
||||
} |
||||
|
||||
class FilePage extends StatelessWidget { |
||||
final String title; |
||||
const FilePage({Key key, this.title}) : super(key: key); |
||||
|
||||
String remove_dir(String name) { |
||||
if (name.endsWith('.dir')) { |
||||
final i = name.lastIndexOf('.'); |
||||
return name.substring(0, i); |
||||
} |
||||
|
||||
return name; |
||||
} |
||||
|
||||
Widget item(String name) { |
||||
final trueName = remove_dir(name); |
||||
return Container( |
||||
width: 80.0, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Container( |
||||
height: 60.0, |
||||
width: 60.0, |
||||
padding: const EdgeInsets.only(bottom: 10.0), |
||||
child: fileIcon(name, 48.0), |
||||
), |
||||
Tooltip( |
||||
message: trueName, |
||||
child: Text(trueName, style: TextStyle(fontSize: 16.0), maxLines: 1, overflow: TextOverflow.ellipsis), |
||||
) |
||||
] |
||||
) |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final isDesktop = isDisplayDesktop(context); |
||||
final color = Theme.of(context).colorScheme; |
||||
final lang = AppLocalizations.of(context); |
||||
|
||||
return Scaffold( |
||||
body: SafeArea( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(10.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Row( |
||||
children: [ |
||||
if (!isDesktop) |
||||
GestureDetector( |
||||
onTap: () => Navigator.pop(context), |
||||
child: Container(width: 20.0, child: Icon(Icons.arrow_back, color: color.primary)), |
||||
), |
||||
const SizedBox(width: 15.0), |
||||
Expanded(child: Text(title, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0))), |
||||
PopupMenuButton<int>( |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(15) |
||||
), |
||||
color: const Color(0xFFEDEDED), |
||||
child: Icon(Icons.add_rounded, color: color.primary), |
||||
onSelected: (int value) { |
||||
if (value == 0) { |
||||
// new post |
||||
} else if (value == 1) { |
||||
// new folder |
||||
} else if (value == 2) { |
||||
// upload file |
||||
} |
||||
}, |
||||
itemBuilder: (context) { |
||||
return <PopupMenuEntry<int>>[ |
||||
PopupMenuItem<int>(value: 0, |
||||
child: Text('New Post', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
PopupMenuItem<int>(value: 1, |
||||
child: Text('New Folder', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
PopupMenuItem<int>(value: 2, |
||||
child: Text('Upload File', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
]; |
||||
} |
||||
), |
||||
const SizedBox(width: 15.0), |
||||
GestureDetector( |
||||
onTap: () {}, // view_module_rounded |
||||
child: Container(width: 20.0, child: Icon(Icons.view_list_rounded, color: color.primary)), |
||||
), |
||||
const SizedBox(width: 10.0), |
||||
], |
||||
), |
||||
SizedBox(height: 5.0), |
||||
Row( |
||||
children: [ |
||||
const SizedBox(width: 15.0), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home'); |
||||
}, |
||||
child: Text('Home', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
Text('/', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home/workspace'); |
||||
}, |
||||
child: Text('workspace', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
Text('/', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home/workspace/cymple'); |
||||
}, |
||||
child: Text('cymple', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
] |
||||
), |
||||
SizedBox(height: 15.0), |
||||
Expanded( |
||||
child: Wrap( |
||||
spacing: 4.0, |
||||
runSpacing: 16.0, |
||||
alignment: WrapAlignment.start, |
||||
children: <Widget> [ |
||||
item('myworks.dir'), |
||||
item('ESSE-infos-public.dir'), |
||||
item('personal.dir'), |
||||
item('others.dir'), |
||||
item('logo.jpg'), |
||||
item('cat.png'), |
||||
item('what-is-esse_en.doc'), |
||||
item('20210101-customers.xls'), |
||||
item('product.pdf'), |
||||
item('deck.ppt'), |
||||
item('coder.md'), |
||||
item('how-to-live-in-happy.mp4'), |
||||
item('something_important'), |
||||
item('car.json'), |
||||
], |
||||
) |
||||
) |
||||
] |
||||
) |
||||
) |
||||
) |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
import 'package:esse/utils/adaptive.dart'; |
||||
import 'package:esse/l10n/localizations.dart'; |
||||
import 'package:esse/provider.dart'; |
||||
|
||||
class ServiceList extends StatefulWidget { |
||||
const ServiceList({Key key}) : super(key: key); |
||||
|
||||
@override |
||||
_ServiceListState createState() => _ServiceListState(); |
||||
} |
||||
|
||||
class _ServiceListState extends State<ServiceList> { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final serviceKeys = []; |
||||
final services = {}; |
||||
|
||||
return Expanded( |
||||
child: ListView.builder( |
||||
itemCount: serviceKeys.length, |
||||
itemBuilder: (BuildContext ctx, int index) => _ListService(), |
||||
)); |
||||
} |
||||
} |
||||
|
||||
class _ListService extends StatelessWidget { |
||||
const _ListService({Key key}) : super(key: key); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final color = Theme.of(context).colorScheme; |
||||
final lang = AppLocalizations.of(context); |
||||
final isDesktop = isDisplayDesktop(context); |
||||
|
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
// final widget = AssistantPage(); |
||||
// if (isDesktop) { |
||||
// Provider.of<AccountProvider>(context, listen: false).updateActivedApp(widget); |
||||
// } else { |
||||
// Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); |
||||
// } |
||||
}, |
||||
child: Container( |
||||
height: 55.0, |
||||
child: Row( |
||||
children: [ |
||||
Container( |
||||
width: 45.0, |
||||
height: 45.0, |
||||
margin: const EdgeInsets.only(left: 20.0, right: 15.0), |
||||
decoration: BoxDecoration( |
||||
image: DecorationImage( |
||||
image: AssetImage('assets/logo/logo_light.png'), |
||||
fit: BoxFit.cover, |
||||
), |
||||
borderRadius: BorderRadius.circular(15.0) |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Container( |
||||
height: 55.0, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
children: [ |
||||
Expanded( |
||||
child: Text('esse', |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle(fontSize: 16.0)) |
||||
), |
||||
Container( |
||||
margin: const EdgeInsets.only(left: 15.0, right: 20.0), |
||||
child: Text('2021-11-12', |
||||
style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0), |
||||
), |
||||
) |
||||
]), |
||||
SizedBox(height: 5.0), |
||||
Expanded( |
||||
child: Text('esse is a echo robot', |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0)), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,114 +0,0 @@
@@ -1,114 +0,0 @@
|
||||
import 'package:esse/models/message.dart'; |
||||
import 'package:esse/utils/relative_time.dart'; |
||||
import 'package:esse/widgets/avatar.dart'; |
||||
import 'package:esse/global.dart'; |
||||
|
||||
class Friend { |
||||
int id; |
||||
String gid; |
||||
String name; |
||||
String addr; |
||||
String remark; |
||||
bool isTop; |
||||
bool isClosed; |
||||
RelativeTime lastMessageTime; |
||||
String lastMessageContent; |
||||
bool lastMessageReaded; |
||||
bool online = false; |
||||
|
||||
// new friend from network |
||||
Friend(this.gid, this.name, this.addr) { |
||||
this.isTop = false; |
||||
this.isClosed = false; |
||||
this.lastMessageTime = RelativeTime(); |
||||
this.lastMessageContent = ''; |
||||
this.lastMessageReaded = true; |
||||
} |
||||
|
||||
Avatar showAvatar({double width = 45.0, bool needOnline = true}) { |
||||
final avatar = Global.avatarPath + this.gid + '.png'; |
||||
return Avatar( |
||||
width: width, |
||||
name: this.name, |
||||
avatarPath: avatar, |
||||
online: this.online, |
||||
needOnline: needOnline, |
||||
hasNew: !this.lastMessageReaded, |
||||
); |
||||
} |
||||
|
||||
updateLastMessage(Message msg, bool isReaded) { |
||||
this.lastMessageTime = msg.time; |
||||
this.lastMessageContent = msg.shortShow(); |
||||
this.lastMessageReaded = isReaded; |
||||
} |
||||
|
||||
static String betterPrint(String info) { |
||||
if (info == null) { |
||||
return ''; |
||||
} |
||||
final len = info.length; |
||||
if (len > 8) { |
||||
return info.substring(0, 8) + '...' + info.substring(len - 6, len); |
||||
} else { |
||||
return info; |
||||
} |
||||
} |
||||
|
||||
Friend.fromList(List params) { |
||||
this.id = params[0]; |
||||
this.gid = params[1]; |
||||
this.addr = params[2]; |
||||
this.name = params[3]; |
||||
this.remark = params[4]; |
||||
this.isTop = params[5] == "1"; |
||||
this.isClosed = params[6] == "1"; |
||||
this.lastMessageTime = RelativeTime.fromInt(params[7]); |
||||
this.lastMessageContent = params[8]; |
||||
this.lastMessageReaded = params[9]; |
||||
this.online = params[10] == "1"; |
||||
} |
||||
} |
||||
|
||||
class Request { |
||||
int id; |
||||
String gid; |
||||
String addr; |
||||
String name; |
||||
String remark; |
||||
bool isMe = true; |
||||
bool ok = false; |
||||
bool over = false; |
||||
bool isDelivery = false; |
||||
RelativeTime time = RelativeTime(); |
||||
|
||||
Request(this.gid, this.addr, this.name, this.remark); |
||||
|
||||
overIt(bool isOk) { |
||||
this.over = true; |
||||
this.ok = isOk; |
||||
} |
||||
|
||||
Friend toFriend(String gid) { |
||||
return Friend(gid, this.name, this.addr); |
||||
} |
||||
|
||||
Avatar showAvatar([double width = 45.0]) { |
||||
final avatar = Global.avatarPath + this.gid + '.png'; |
||||
return Avatar( |
||||
width: width, name: this.name, avatarPath: avatar, needOnline: false); |
||||
} |
||||
|
||||
Request.fromList(List params) { |
||||
this.id = params[0]; |
||||
this.gid = params[1]; |
||||
this.addr = params[2]; |
||||
this.name = params[3]; |
||||
this.remark = params[4]; |
||||
this.isMe = params[5]; |
||||
this.ok = params[6]; |
||||
this.over = params[7]; |
||||
this.isDelivery = params[8]; |
||||
this.time = RelativeTime.fromInt(params[9]); |
||||
} |
||||
} |
@ -1,248 +0,0 @@
@@ -1,248 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
import 'package:esse/utils/adaptive.dart'; |
||||
import 'package:esse/utils/file_image.dart'; |
||||
import 'package:esse/l10n/localizations.dart'; |
||||
import 'package:esse/provider/account.dart'; |
||||
|
||||
class ListFolder extends StatefulWidget { |
||||
@override |
||||
_ListFolderState createState() => _ListFolderState(); |
||||
} |
||||
|
||||
const List FILE_DIRECTORY = [ |
||||
["Recent", Icons.label_rounded], |
||||
["Starred", Icons.star_rounded], |
||||
["Home", Icons.home_rounded], |
||||
["Documents", Icons.my_library_books_rounded], |
||||
["Pictures", Icons.collections_rounded], |
||||
["Music", Icons.my_library_music_rounded], |
||||
["Videos", Icons.video_collection_rounded], |
||||
["Trash", Icons.auto_delete_rounded], |
||||
]; |
||||
|
||||
class _ListFolderState extends State<ListFolder> { |
||||
int chooseIndex = 0; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
Future.delayed(Duration.zero, () { |
||||
final isDesktop = isDisplayDesktop(context); |
||||
if (isDesktop) { |
||||
loadFolder(true, chooseIndex); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
loadFolder(bool isDesktop, int index) async { |
||||
print('load folder'); |
||||
final widget = FilePage(title: FILE_DIRECTORY[index][0]); |
||||
if (isDesktop) { |
||||
Provider.of<AccountProvider>(context, listen: false).updateActivedApp(widget); |
||||
} else { |
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); |
||||
} |
||||
} |
||||
|
||||
changeItem(int index, bool isDesktop) { |
||||
setState(() { |
||||
chooseIndex = index; |
||||
loadFolder(isDesktop, index); |
||||
}); |
||||
} |
||||
|
||||
Widget item(int index, ColorScheme color, bool isDesktop) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () => changeItem(index, isDesktop), |
||||
child: SizedBox( |
||||
height: 55.0, |
||||
child: Row( |
||||
children: [ |
||||
Container( |
||||
width: 45.0, |
||||
height: 45.0, |
||||
margin: const EdgeInsets.only(left: 20.0, right: 15.0), |
||||
child: Icon(FILE_DIRECTORY[index][1], size: 24.0, color: color.primary), |
||||
decoration: BoxDecoration( |
||||
color: color.surface, |
||||
borderRadius: BorderRadius.circular(15.0) |
||||
), |
||||
), |
||||
chooseIndex == index |
||||
? Text(FILE_DIRECTORY[index][0], style: TextStyle(fontSize: 16.0, color: color.primary)) |
||||
: Text(FILE_DIRECTORY[index][0], style: TextStyle(fontSize: 16.0)) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final color = Theme.of(context).colorScheme; |
||||
final isDesktop = isDisplayDesktop(context); |
||||
|
||||
return Expanded( |
||||
child: ListView.builder( |
||||
itemCount: FILE_DIRECTORY.length, |
||||
itemBuilder: (BuildContext ctx, int index) => item(index, color, isDesktop), |
||||
)); |
||||
} |
||||
} |
||||
|
||||
class FilePage extends StatelessWidget { |
||||
final String title; |
||||
const FilePage({Key key, this.title}) : super(key: key); |
||||
|
||||
String remove_dir(String name) { |
||||
if (name.endsWith('.dir')) { |
||||
final i = name.lastIndexOf('.'); |
||||
return name.substring(0, i); |
||||
} |
||||
|
||||
return name; |
||||
} |
||||
|
||||
Widget item(String name) { |
||||
final trueName = remove_dir(name); |
||||
return Container( |
||||
width: 80.0, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Container( |
||||
height: 60.0, |
||||
width: 60.0, |
||||
padding: const EdgeInsets.only(bottom: 10.0), |
||||
child: fileIcon(name, 48.0), |
||||
), |
||||
Tooltip( |
||||
message: trueName, |
||||
child: Text(trueName, style: TextStyle(fontSize: 16.0), maxLines: 1, overflow: TextOverflow.ellipsis), |
||||
) |
||||
] |
||||
) |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final isDesktop = isDisplayDesktop(context); |
||||
final color = Theme.of(context).colorScheme; |
||||
final lang = AppLocalizations.of(context); |
||||
|
||||
return Scaffold( |
||||
body: SafeArea( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(10.0), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Row( |
||||
children: [ |
||||
if (!isDesktop) |
||||
GestureDetector( |
||||
onTap: () => Navigator.pop(context), |
||||
child: Container(width: 20.0, child: Icon(Icons.arrow_back, color: color.primary)), |
||||
), |
||||
const SizedBox(width: 15.0), |
||||
Expanded(child: Text(title, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0))), |
||||
PopupMenuButton<int>( |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(15) |
||||
), |
||||
color: const Color(0xFFEDEDED), |
||||
child: Icon(Icons.add_rounded, color: color.primary), |
||||
onSelected: (int value) { |
||||
if (value == 0) { |
||||
// new post |
||||
} else if (value == 1) { |
||||
// new folder |
||||
} else if (value == 2) { |
||||
// upload file |
||||
} |
||||
}, |
||||
itemBuilder: (context) { |
||||
return <PopupMenuEntry<int>>[ |
||||
PopupMenuItem<int>(value: 0, |
||||
child: Text('New Post', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
PopupMenuItem<int>(value: 1, |
||||
child: Text('New Folder', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
PopupMenuItem<int>(value: 2, |
||||
child: Text('Upload File', style: TextStyle(color: Colors.black, fontSize: 16.0)), |
||||
), |
||||
]; |
||||
} |
||||
), |
||||
const SizedBox(width: 15.0), |
||||
GestureDetector( |
||||
onTap: () {}, // view_module_rounded |
||||
child: Container(width: 20.0, child: Icon(Icons.view_list_rounded, color: color.primary)), |
||||
), |
||||
const SizedBox(width: 10.0), |
||||
], |
||||
), |
||||
SizedBox(height: 5.0), |
||||
Row( |
||||
children: [ |
||||
const SizedBox(width: 15.0), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home'); |
||||
}, |
||||
child: Text('Home', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
Text('/', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home/workspace'); |
||||
}, |
||||
child: Text('workspace', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
Text('/', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))), |
||||
InkWell( |
||||
onTap: () { |
||||
print('Home/workspace/cymple'); |
||||
}, |
||||
child: Text('cymple', style: TextStyle(fontSize: 14.0, color: Color(0xFFADB0BB))) |
||||
), |
||||
] |
||||
), |
||||
SizedBox(height: 15.0), |
||||
Expanded( |
||||
child: Wrap( |
||||
spacing: 4.0, |
||||
runSpacing: 16.0, |
||||
alignment: WrapAlignment.start, |
||||
children: <Widget> [ |
||||
item('myworks.dir'), |
||||
item('ESSE-infos-public.dir'), |
||||
item('personal.dir'), |
||||
item('others.dir'), |
||||
item('logo.jpg'), |
||||
item('cat.png'), |
||||
item('what-is-esse_en.doc'), |
||||
item('20210101-customers.xls'), |
||||
item('product.pdf'), |
||||
item('deck.ppt'), |
||||
item('coder.md'), |
||||
item('how-to-live-in-happy.mp4'), |
||||
item('something_important'), |
||||
item('car.json'), |
||||
], |
||||
) |
||||
) |
||||
] |
||||
) |
||||
) |
||||
) |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,191 @@
@@ -0,0 +1,191 @@
|
||||
import 'dart:async'; |
||||
import "dart:collection"; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'package:esse/account.dart'; |
||||
import 'package:esse/utils/logined_cache.dart'; |
||||
import 'package:esse/widgets/default_core_show.dart'; |
||||
import 'package:esse/global.dart'; |
||||
import 'package:esse/rpc.dart'; |
||||
|
||||
const DEFAULT_ONLINE_INIT = 8; |
||||
const DEFAULT_ONLINE_DELAY = 5; |
||||
|
||||
class AccountProvider extends ChangeNotifier { |
||||
Map<String, Account> accounts = {}; // account's gid and account. |
||||
String activedAccountId; // actived account gid. |
||||
Account get activedAccount => this.accounts[activedAccountId]; |
||||
|
||||
Set<int> topKeys = Set(); |
||||
|
||||
/// current user's did. |
||||
String get id => this.activedAccount.id; |
||||
|
||||
Widget coreShowWidget = DefaultCoreShow(); |
||||
bool systemAppFriendAddNew = false; |
||||
bool systemAppGroupAddNew = false; |
||||
|
||||
AccountProvider() { |
||||
// rpc notice when account not actived. |
||||
rpc.addNotice(_accountNotice); |
||||
|
||||
// rpc |
||||
rpc.addListener('account-system-info', _systemInfo, false); |
||||
rpc.addListener('account-update', _accountUpdate, false); |
||||
rpc.addListener('account-login', _accountLogin, false); |
||||
|
||||
systemInfo(); |
||||
} |
||||
|
||||
handleTops() { |
||||
// |
||||
} |
||||
|
||||
/// when security load accounts from rpc. |
||||
initAccounts(Map accounts) { |
||||
this.accounts = accounts; |
||||
initLogined(this.accounts.values.toList()); |
||||
} |
||||
|
||||
/// when security load accounts from cache. |
||||
autoAccounts(String gid, Map accounts) { |
||||
Global.changeGid(gid); |
||||
this.activedAccountId = gid; |
||||
this.accounts = accounts; |
||||
|
||||
this.activedAccount.online = true; |
||||
rpc.send('account-login', [gid, this.activedAccount.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_INIT), |
||||
() => rpc.send('account-online', [gid])); |
||||
|
||||
this.accounts.forEach((k, v) { |
||||
if (k != gid && v.online) { |
||||
rpc.send('account-login', [v.gid, v.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_INIT), |
||||
() => rpc.send('account-online', [v.gid])); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/// when security add account. |
||||
addAccount(Account account) { |
||||
Global.changeGid(account.gid); |
||||
this.activedAccountId = account.gid; |
||||
this.accounts[account.gid] = account; |
||||
|
||||
rpc.send('account-login', [account.gid, account.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [account.gid])); |
||||
updateLogined(account); |
||||
} |
||||
|
||||
updateActivedAccount(String gid) { |
||||
Global.changeGid(gid); |
||||
this.clearActivedAccount(); |
||||
this.activedAccountId = gid; |
||||
this.activedAccount.hasNew = false; |
||||
|
||||
rpc.send('friend-list', []); |
||||
|
||||
if (!this.activedAccount.online) { |
||||
this.activedAccount.online = true; |
||||
rpc.send('account-login', [gid, this.activedAccount.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [gid])); |
||||
} |
||||
|
||||
mainLogined(gid); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
logout() { |
||||
this.accounts.clear(); |
||||
this.clearActivedAccount(); |
||||
rpc.send('account-logout', []); |
||||
clearLogined(); |
||||
} |
||||
|
||||
onlineAccount(String gid, String lock) { |
||||
this.accounts[gid].online = true; |
||||
updateLogined(this.accounts[gid]); |
||||
|
||||
rpc.send('account-login', [gid, lock]); |
||||
|
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [gid])); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
offlineAccount(String gid) { |
||||
this.accounts[gid].online = false; |
||||
updateLogined(this.accounts[gid]); |
||||
|
||||
if (gid == this.activedAccountId) { |
||||
this.clearActivedAccount(); |
||||
} |
||||
rpc.send('account-offline', [gid]); |
||||
|
||||
notifyListeners(); |
||||
} |
||||
|
||||
updateActivedApp(Widget widget) { |
||||
this.coreShowWidget = widget; |
||||
this.systemAppFriendAddNew = false; |
||||
notifyListeners(); |
||||
} |
||||
|
||||
clearActivedAccount() { |
||||
this.topKeys.clear(); |
||||
} |
||||
|
||||
accountUpdate(String name, [Uint8List avatar]) { |
||||
this.activedAccount.name = name; |
||||
|
||||
if (avatar != null && avatar.length > 0) { |
||||
this.activedAccount.avatar = avatar; |
||||
rpc.send('account-update', [name, this.activedAccount.encodeAvatar()]); |
||||
} else { |
||||
rpc.send('account-update', [name, '']); |
||||
} |
||||
updateLogined(this.activedAccount); |
||||
|
||||
notifyListeners(); |
||||
} |
||||
|
||||
accountPin(String lock) { |
||||
this.activedAccount.lock = lock; |
||||
updateLogined(this.activedAccount); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
systemInfo() { |
||||
rpc.send('account-system-info', []); |
||||
} |
||||
|
||||
// -- callback when receive rpc info. -- // |
||||
_systemInfo(List params) { |
||||
Global.addr = '0x' + params[0]; |
||||
} |
||||
|
||||
_accountLogin(List _params) { |
||||
// nothing. |
||||
} |
||||
|
||||
_accountNotice(String gid) { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_accountUpdate(List params) { |
||||
final gid = params[0]; |
||||
this.accounts[gid].name = params[1]; |
||||
if (params[2].length > 1) { |
||||
this.accounts[gid].updateAvatar(params[2]); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
} |
@ -1,553 +0,0 @@
@@ -1,553 +0,0 @@
|
||||
import 'dart:async'; |
||||
import "dart:collection"; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'package:esse/models/account.dart'; |
||||
import 'package:esse/models/friend.dart'; |
||||
import 'package:esse/models/message.dart'; |
||||
import 'package:esse/utils/logined_cache.dart'; |
||||
import 'package:esse/widgets/default_core_show.dart'; |
||||
import 'package:esse/pages/friend.dart'; |
||||
import 'package:esse/global.dart'; |
||||
import 'package:esse/rpc.dart'; |
||||
|
||||
const DEFAULT_ONLINE_INIT = 8; |
||||
const DEFAULT_ONLINE_DELAY = 5; |
||||
|
||||
class AccountProvider extends ChangeNotifier { |
||||
Map<String, Account> accounts = {}; // account's gid and account. |
||||
String activedAccountId; // actived account gid. |
||||
Account get activedAccount => this.accounts[activedAccountId]; |
||||
|
||||
Map<int, Friend> friends = {}; // all friends. friends need Re-order. |
||||
int activedFriendId; // actived friend's id. |
||||
Friend get activedFriend => this.friends[this.activedFriendId]; |
||||
Set<int> topKeys = Set(); |
||||
List<int> orderChats = []; // ordered chat friends with last message. |
||||
|
||||
Map<int, Friend> groups = {}; // all apps. |
||||
|
||||
/// all requests. request have order. |
||||
SplayTreeMap<int, Request> requests = SplayTreeMap(); |
||||
|
||||
/// current show messages. init number is 100, message have order. |
||||
SplayTreeMap<int, Message> activedMessages = SplayTreeMap(); |
||||
|
||||
/// current user's did. |
||||
String get id => this.activedAccount.id; |
||||
|
||||
// List<int> get chatKeys => this.orderChats.values.toList(); |
||||
List<int> get friendKeys => this.friends.keys.toList(); // TODO |
||||
|
||||
List<int> get groupKeys => this.groups.keys.toList(); |
||||
|
||||
Widget coreShowWidget = DefaultCoreShow(); |
||||
bool systemAppFriendAddNew = false; |
||||
bool systemAppGroupAddNew = false; |
||||
|
||||
void orderFriends(int id) { |
||||
if (this.orderChats.length == 0 || this.orderChats[0] != id) { |
||||
this.orderChats.remove(id); |
||||
this.orderChats.insert(0, id); |
||||
} |
||||
} |
||||
|
||||
void addContacts() { |
||||
// TODO order contacts. |
||||
} |
||||
|
||||
initStates() { |
||||
// rpc |
||||
rpc.addListener('system-info', _systemInfo); |
||||
rpc.addListener('account-update', _accountUpdate); |
||||
rpc.addListener('friend-list', _friendList); |
||||
rpc.addListener('friend-online', _friendOnline); |
||||
rpc.addListener('friend-offline', _friendOffline); |
||||
rpc.addListener('friend-info', _friendInfo); |
||||
rpc.addListener('friend-update', _friendUpdate); |
||||
rpc.addListener('friend-close', _friendClose); |
||||
rpc.addListener('request-list', _requestList); |
||||
rpc.addListener('request-create', _requestCreate); |
||||
rpc.addListener('request-delivery', _requestDelivery); |
||||
rpc.addListener('request-agree', _requestAgree); |
||||
rpc.addListener('request-reject', _requestReject); |
||||
rpc.addListener('request-delete', _requestDelete); |
||||
rpc.addListener('message-list', _messageList); |
||||
rpc.addListener('message-create', _messageCreate); |
||||
rpc.addListener('message-delete', _messageDelete); |
||||
rpc.addListener('message-delivery', _messageDelivery); |
||||
|
||||
systemInfo(); |
||||
} |
||||
|
||||
/// when security load accounts from rpc. |
||||
initAccounts(Map accounts) { |
||||
this.accounts = accounts; |
||||
initStates(); |
||||
initLogined(this.accounts.values.toList()); |
||||
} |
||||
|
||||
/// when security load accounts from cache. |
||||
autoAccounts(String gid, Map accounts) { |
||||
Global.changeGid(gid); |
||||
this.activedAccountId = gid; |
||||
this.accounts = accounts; |
||||
initStates(); |
||||
|
||||
rpc.send('friend-list', []); |
||||
|
||||
this.activedAccount.online = true; |
||||
rpc.send('account-login', [gid, this.activedAccount.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_INIT), |
||||
() => rpc.send('account-online', [gid])); |
||||
|
||||
this.accounts.forEach((k, v) { |
||||
if (k != gid && v.online) { |
||||
rpc.send('account-login', [v.gid, v.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_INIT), |
||||
() => rpc.send('account-online', [v.gid])); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/// when security add account. |
||||
addAccount(Account account) { |
||||
Global.changeGid(account.gid); |
||||
this.activedAccountId = account.gid; |
||||
this.accounts[account.gid] = account; |
||||
|
||||
rpc.send('account-login', [account.gid, account.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [account.gid])); |
||||
updateLogined(account); |
||||
} |
||||
|
||||
updateActivedAccount(String gid) { |
||||
Global.changeGid(gid); |
||||
this.clearActivedAccount(); |
||||
this.activedAccountId = gid; |
||||
this.activedAccount.hasNew = false; |
||||
|
||||
rpc.send('friend-list', []); |
||||
|
||||
if (!this.activedAccount.online) { |
||||
this.activedAccount.online = true; |
||||
rpc.send('account-login', [gid, this.activedAccount.lock]); |
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [gid])); |
||||
} |
||||
|
||||
mainLogined(gid); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
logout() { |
||||
this.accounts.clear(); |
||||
this.clearActivedAccount(); |
||||
rpc.send('account-logout', []); |
||||
clearLogined(); |
||||
} |
||||
|
||||
onlineAccount(String gid, String lock) { |
||||
this.accounts[gid].online = true; |
||||
updateLogined(this.accounts[gid]); |
||||
|
||||
rpc.send('account-login', [gid, lock]); |
||||
|
||||
new Future.delayed(Duration(seconds: DEFAULT_ONLINE_DELAY), |
||||
() => rpc.send('account-online', [gid])); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
offlineAccount(String gid) { |
||||
this.accounts[gid].online = false; |
||||
updateLogined(this.accounts[gid]); |
||||
|
||||
if (gid == this.activedAccountId) { |
||||
this.clearActivedAccount(); |
||||
} |
||||
rpc.send('account-offline', [gid]); |
||||
|
||||
notifyListeners(); |
||||
} |
||||
|
||||
updateActivedApp(Widget widget) { |
||||
this.coreShowWidget = widget; |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
this.systemAppFriendAddNew = false; |
||||
notifyListeners(); |
||||
} |
||||
|
||||
updateActivedFriend(int id, bool isDesktop) { |
||||
this.activedFriendId = id; |
||||
this.activedMessages.clear(); |
||||
this.friends[id].lastMessageReaded = true; |
||||
rpc.send('message-list', [this.activedFriendId]); |
||||
|
||||
if (isDesktop && this.coreShowWidget is! ChatPage) { |
||||
this.coreShowWidget = ChatPage(); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
clearActivedAccount() { |
||||
this.topKeys.clear(); |
||||
this.orderChats.clear(); |
||||
this.friends.clear(); |
||||
this.requests.clear(); |
||||
this.clearActivedFriend(); |
||||
} |
||||
|
||||
clearActivedFriend() { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
this.coreShowWidget = DefaultCoreShow(); |
||||
} |
||||
|
||||
accountUpdate(String name, [Uint8List avatar]) { |
||||
this.activedAccount.name = name; |
||||
|
||||
if (avatar != null && avatar.length > 0) { |
||||
this.activedAccount.avatar = avatar; |
||||
rpc.send('account-update', [name, this.activedAccount.encodeAvatar()]); |
||||
} else { |
||||
rpc.send('account-update', [name, '']); |
||||
} |
||||
updateLogined(this.activedAccount); |
||||
|
||||
notifyListeners(); |
||||
} |
||||
|
||||
accountPin(String lock) { |
||||
this.activedAccount.lock = lock; |
||||
updateLogined(this.activedAccount); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
systemInfo() { |
||||
rpc.send('system-info', []); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendUpdate(int id, {String remark, bool isTop}) { |
||||
if (remark != null) { |
||||
this.friends[id].remark = remark; |
||||
} |
||||
|
||||
if (isTop != null) { |
||||
this.friends[id].isTop = isTop; |
||||
if (isTop) { |
||||
this.topKeys.add(id); |
||||
} else { |
||||
this.topKeys.remove(id); |
||||
} |
||||
} |
||||
|
||||
final friend = this.friends[id]; |
||||
rpc.send('friend-update', [id, friend.remark, friend.isTop]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendClose(int id) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
rpc.send('friend-close', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendDelete(int id) { |
||||
if (id == this.activedFriendId) { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
this.coreShowWidget = DefaultCoreShow(); |
||||
} |
||||
this.friends.remove(id); |
||||
this.orderChats.remove(id); |
||||
this.topKeys.remove(id); |
||||
rpc.send('friend-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list all request. |
||||
requestList() { |
||||
rpc.send('request-list', []); |
||||
} |
||||
|
||||
/// clear the memory requests. |
||||
requestClear() { |
||||
this.requests.clear(); |
||||
} |
||||
|
||||
/// create a request for friend. |
||||
requestCreate(Request req) { |
||||
rpc.send('request-create', [req.gid, req.addr, req.name, req.remark]); |
||||
this.requests.remove(req.id); |
||||
rpc.send('request-list', []); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// agree a request for friend. |
||||
requestAgree(int id) { |
||||
rpc.send('request-agree', [id]); |
||||
this.requests[id].overIt(true); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// reject a request for friend. |
||||
requestReject(int id) { |
||||
rpc.send('request-reject', [id]); |
||||
this.requests[id].overIt(false); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delte a request for friend. |
||||
requestDelete(int id) { |
||||
rpc.send('request-delete', [id]); |
||||
this.requests.remove(id); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// create a message. need core server handle this message. |
||||
/// and then this message will show in message list. |
||||
messageCreate(Message msg) { |
||||
final fgid = this.friends[msg.fid].gid; |
||||
rpc.send('message-create', [msg.fid, fgid, msg.type.toInt(), msg.content]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a message. |
||||
messageDelete(int id) { |
||||
rpc.send('message-delete', [id]); |
||||
this.activedMessages.remove(id); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
// -- callback when receive rpc info. -- // |
||||
_systemInfo(String _gid, List params) { |
||||
Global.addr = '0x' + params[0]; |
||||
} |
||||
|
||||
_accountUpdate(String gid, List params) { |
||||
this.accounts[gid].name = params[0]; |
||||
if (params[1].length > 0) { |
||||
if (params[1].length > 1) { |
||||
this.accounts[gid].updateAvatar(params[1]); |
||||
} |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list all friends. |
||||
_friendList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
this.orderChats.clear(); |
||||
this.friends.clear(); |
||||
|
||||
params.forEach((params) { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
this.orderChats.add(id); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys.add(id); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendOnline(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = true; |
||||
this.friends[id].addr = params[1]; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendOffline(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendInfo(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys.add(id); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendUpdate(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].isTop = params[1]; |
||||
this.friends[id].remark = params[2]; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendClose(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// list requests for friend. |
||||
_requestList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
this.requests.clear(); |
||||
params.forEach((param) { |
||||
if (param.length == 10) { |
||||
this.requests[param[0]] = Request.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// receive a request for friend. |
||||
_requestCreate(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
if (params.length == 10) { |
||||
this.requests[params[0]] = Request.fromList(params); |
||||
this.systemAppFriendAddNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// created request had delivery. |
||||
_requestDelivery(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// request for friend receive agree. |
||||
_requestAgree(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; // request's id. |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(true); |
||||
} |
||||
var friend = Friend.fromList(params[1]); |
||||
this.friends[friend.id] = friend; |
||||
orderFriends(friend.id); |
||||
notifyListeners(); |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// request for friend receive reject. |
||||
_requestReject(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(false); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_requestDelete(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
this.requests.remove(params[0]); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// list message with friend. |
||||
_messageList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
params.forEach((param) { |
||||
if (param.length == 8) { |
||||
this.activedMessages[param[0]] = Message.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// friend send message to me. |
||||
_messageCreate(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
if (params.length == 8) { |
||||
final msg = Message.fromList(params); |
||||
if (msg.fid == this.activedFriendId) { |
||||
if (!msg.isDelivery) { |
||||
msg.isDelivery = null; // When message create, set is is none; |
||||
} |
||||
this.friends[msg.fid].updateLastMessage(msg, true); |
||||
this.activedMessages[msg.id] = msg; |
||||
rpc.send('friend-readed', [this.activedFriendId]); |
||||
} else { |
||||
if (this.friends.containsKey(msg.fid)) { |
||||
this.friends[msg.fid].updateLastMessage(msg, false); |
||||
} |
||||
} |
||||
orderFriends(msg.fid); |
||||
notifyListeners(); |
||||
} |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_messageDelete(String gid, List params) { |
||||
if (gid == this.activedAccountId) { |
||||
this.activedMessages.remove(params[0]); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// created message had delivery. |
||||
_messageDelivery(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.activedMessages.containsKey(id)) { |
||||
this.activedMessages[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,97 +0,0 @@
@@ -1,97 +0,0 @@
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'package:esse/models/account.dart'; |
||||
import 'package:esse/models/device.dart'; |
||||
import 'package:esse/global.dart'; |
||||
import 'package:esse/rpc.dart'; |
||||
|
||||
class DeviceProvider extends ChangeNotifier { |
||||
Map<int, Device> devices = {}; |
||||
int activedId = -1; |
||||
DeviceStatus status = DeviceStatus(); |
||||
|
||||
init() { |
||||
// rpc. |
||||
rpc.addListener('device-list', _list); |
||||
rpc.addListener('device-create', _create); |
||||
rpc.addListener('device-delete', _delete); |
||||
rpc.addListener('device-online', _online); |
||||
rpc.addListener('device-offline', _offline); |
||||
rpc.addListener('device-status', _status); |
||||
|
||||
// init. |
||||
rpc.send('device-list', []); |
||||
} |
||||
|
||||
updateActived(int id) { |
||||
this.status = DeviceStatus(); |
||||
this.activedId = id; |
||||
rpc.send('device-status', [this.devices[id].addr]); |
||||
} |
||||
|
||||
clearActived() { |
||||
this.activedId = -1; |
||||
} |
||||
|
||||
connect(String addr) { |
||||
rpc.send('device-connect', [addr]); |
||||
} |
||||
|
||||
delete(int id) { |
||||
this.activedId = -1; |
||||
this.devices.remove(id); |
||||
rpc.send('device-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
_list(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
this.devices.clear(); |
||||
params.forEach((params) { |
||||
if (params.length == 6) { |
||||
this.devices[params[0]] = Device.fromList(params); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_create(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
if (params.length == 6) { |
||||
this.devices[params[0]] = Device.fromList(params); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_delete(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
this.devices.remove(params[0]); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_online(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
this.devices[params[0]].online = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_offline(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
this.devices[params[0]].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_status(String gid, List params) { |
||||
if (Global.gid == gid) { |
||||
if (params.length == 9) { |
||||
this.status = DeviceStatus.fromList(params); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,371 +0,0 @@
@@ -1,371 +0,0 @@
|
||||
import 'dart:async'; |
||||
import "dart:collection"; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
|
||||
import 'models/account.dart'; |
||||
import 'models/friend.dart'; |
||||
import 'models/message.dart'; |
||||
import 'models/system.dart'; |
||||
import 'utils/logined_cache.dart'; |
||||
import 'widgets/default_core_show.dart'; |
||||
|
||||
import 'pages/friend.dart'; |
||||
|
||||
import 'rpc.dart'; |
||||
import 'options.dart'; |
||||
|
||||
class SessionProvider extends ChangeNotifier { |
||||
Map<int, Friend> friends = {}; // all friends. friends need Re-order. |
||||
int activedFriendId; // actived friend's id. |
||||
Friend get activedFriend => this.friends[this.activedFriendId]; |
||||
Set<int> topKeys = Set(); |
||||
List<int> orderChats = []; // ordered chat friends with last message. |
||||
|
||||
/// all requests. request have order. |
||||
SplayTreeMap<int, Request> requests = SplayTreeMap(); |
||||
|
||||
/// current show messages. init number is 100, message have order. |
||||
SplayTreeMap<int, Message> activedMessages = SplayTreeMap(); |
||||
|
||||
/// current user's did. |
||||
String get id => this.activedAccount.id; |
||||
|
||||
// List<int> get chatKeys => this.orderChats.values.toList(); |
||||
List<int> get friendKeys => this.friends.keys.toList(); // TODO |
||||
|
||||
void orderFriends(int id) { |
||||
if (this.orderChats.length == 0 || this.orderChats[0] != id) { |
||||
this.orderChats.remove(id); |
||||
this.orderChats.insert(0, id); |
||||
} |
||||
} |
||||
|
||||
void addContacts() { |
||||
// TODO order contacts. |
||||
} |
||||
|
||||
init() { |
||||
// rpc |
||||
rpc.addListener('friend-list', _friendList); |
||||
rpc.addListener('friend-online', _friendOnline); |
||||
rpc.addListener('friend-offline', _friendOffline); |
||||
rpc.addListener('friend-info', _friendInfo); |
||||
rpc.addListener('friend-close', _friendClose); |
||||
rpc.addListener('request-list', _requestList); |
||||
rpc.addListener('request-create', _requestCreate); |
||||
rpc.addListener('request-delivery', _requestDelivery); |
||||
rpc.addListener('request-agree', _requestAgree); |
||||
rpc.addListener('request-reject', _requestReject); |
||||
rpc.addListener('message-list', _messageList); |
||||
rpc.addListener('message-create', _messageCreate); |
||||
rpc.addListener('message-delivery', _messageDelivery); |
||||
} |
||||
|
||||
updateActivedFriend(int id, bool isDesktop) { |
||||
this.activedFriendId = id; |
||||
this.activedMessages.clear(); |
||||
this.friends[id].lastMessageReaded = true; |
||||
rpc.send('message-list', [this.activedFriendId]); |
||||
|
||||
if (isDesktop && this.coreShowWidget is! ChatPage) { |
||||
this.coreShowWidget = ChatPage(); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
clearActivedFriend() { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
this.coreShowWidget = DefaultCoreShow(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendInfo(int id, {String remark, bool isTop, bool isHidden}) { |
||||
if (remark != null) { |
||||
this.friends[id].remark = remark; |
||||
} |
||||
|
||||
if (isTop != null) { |
||||
this.friends[id].isTop = isTop; |
||||
if (isTop) { |
||||
this.topKeys.add(id); |
||||
} else { |
||||
this.topKeys.remove(id); |
||||
} |
||||
} |
||||
|
||||
if (isHidden != null) { |
||||
this.friends[id].isHidden = isHidden; |
||||
} |
||||
|
||||
final friend = this.friends[id]; |
||||
rpc.send('friend-info', [id, friend.remark, friend.isTop, friend.isHidden]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendClose(int id) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
rpc.send('friend-close', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a friend. |
||||
friendDelete(int id) { |
||||
if (id == this.activedFriendId) { |
||||
this.activedFriendId = null; |
||||
this.activedMessages.clear(); |
||||
this.coreShowWidget = DefaultCoreShow(); |
||||
} |
||||
this.friends.remove(id); |
||||
this.orderChats.remove(id); |
||||
this.topKeys.remove(id); |
||||
rpc.send('friend-delete', [id]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// list all request. |
||||
requestList() { |
||||
rpc.send('request-list', []); |
||||
} |
||||
|
||||
/// clear the memory requests. |
||||
requestClear() { |
||||
this.requests.clear(); |
||||
} |
||||
|
||||
/// create a request for friend. |
||||
requestCreate(Request req) { |
||||
rpc.send('request-create', [req.gid, req.addr, req.name, req.remark]); |
||||
this.requests.remove(req.id); |
||||
rpc.send('request-list', []); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// agree a request for friend. |
||||
requestAgree(int id) { |
||||
rpc.send('request-agree', [id]); |
||||
this.requests[id].overIt(true); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// reject a request for friend. |
||||
requestReject(int id) { |
||||
rpc.send('request-reject', [id]); |
||||
this.requests[id].overIt(false); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delte a request for friend. |
||||
requestDelete(int id) { |
||||
rpc.send('request-delete', [id]); |
||||
this.requests.remove(id); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// create a message. need core server handle this message. |
||||
/// and then this message will show in message list. |
||||
messageCreate(Message msg) { |
||||
rpc.send('message-create', [msg.fid, msg.type.toInt(), msg.content]); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// delete a message. |
||||
messageDelete(int id) { |
||||
rpc.send('message-delete', [id]); |
||||
this.activedMessages.remove(id); |
||||
notifyListeners(); |
||||
} |
||||
|
||||
// -- callback when receive rpc info. -- // |
||||
|
||||
/// list all friends. |
||||
_friendList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
this.orderChats.clear(); |
||||
this.friends.clear(); |
||||
|
||||
params.forEach((params) { |
||||
if (params.length == 12) { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
this.orderChats.add(id); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys.add(id); |
||||
} |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
_friendOnline(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = true; |
||||
this.friends[id].addr = params[1]; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendOffline(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendInfo(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
if (params.length == 12) { |
||||
final id = params[0]; |
||||
this.friends[id] = Friend.fromList(params); |
||||
if (this.friends[id].isTop) { |
||||
this.topKeys.add(id); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
_friendClose(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.friends.containsKey(id)) { |
||||
this.friends[id].isClosed = true; |
||||
this.friends[id].online = false; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// list requests for friend. |
||||
_requestList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
this.requests.clear(); |
||||
params.forEach((param) { |
||||
if (param.length == 10) { |
||||
this.requests[param[0]] = Request.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// receive a request for friend. |
||||
_requestCreate(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
if (params.length == 10) { |
||||
this.requests[params[0]] = Request.fromList(params); |
||||
this.systemAppFriendAddNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// created request had delivery. |
||||
_requestDelivery(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// request for friend receive agree. |
||||
_requestAgree(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; // request's id. |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(true); |
||||
} |
||||
if (params[1].length == 12) { |
||||
var friend = Friend.fromList(params[1]); |
||||
this.friends[friend.id] = friend; |
||||
orderFriends(friend.id); |
||||
} |
||||
notifyListeners(); |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// request for friend receive reject. |
||||
_requestReject(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
if (this.requests.containsKey(id)) { |
||||
this.requests[id].overIt(false); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// list message with friend. |
||||
_messageList(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
params.forEach((param) { |
||||
if (param.length == 8) { |
||||
this.activedMessages[param[0]] = Message.fromList(param); |
||||
} |
||||
}); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// friend send message to me. |
||||
_messageCreate(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
if (params.length == 8) { |
||||
final msg = Message.fromList(params); |
||||
if (msg.fid == this.activedFriendId) { |
||||
this.friends[msg.fid].updateLastMessage(msg, true); |
||||
this.activedMessages[msg.id] = msg; |
||||
rpc.send('friend-readed', [this.activedFriendId]); |
||||
} else { |
||||
if (this.friends.containsKey(msg.fid)) { |
||||
this.friends[msg.fid].updateLastMessage(msg, false); |
||||
} |
||||
} |
||||
orderFriends(msg.fid); |
||||
notifyListeners(); |
||||
} |
||||
} else { |
||||
if (this.accounts.containsKey(gid)) { |
||||
this.accounts[gid].hasNew = true; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// created message had delivery. |
||||
_messageDelivery(String gid, List params) async { |
||||
if (gid == this.activedAccountId) { |
||||
final id = params[0]; |
||||
final isDelivery = params[1]; |
||||
if (this.activedMessages.containsKey(id)) { |
||||
this.activedMessages[id].isDelivery = isDelivery; |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
String betterPrint(String info) { |
||||
if (info == null) { |
||||
return ''; |
||||
} |
||||
final len = info.length; |
||||
if (len > 8) { |
||||
return info.substring(0, 8) + '...' + info.substring(len - 6, len); |
||||
} else { |
||||
return info; |
||||
} |
||||
} |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
import 'package:esse/utils/adaptive.dart'; |
||||
import 'package:esse/l10n/localizations.dart'; |
||||
import 'package:esse/provider/account.dart'; |
||||
|
||||
import 'package:esse/apps/assistant/page.dart'; |
||||
|
||||
class ListService extends StatelessWidget { |
||||
const ListService({Key key}) : super(key: key); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final color = Theme.of(context).colorScheme; |
||||
final lang = AppLocalizations.of(context); |
||||
final isDesktop = isDisplayDesktop(context); |
||||
|
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
final widget = AssistantPage(); |
||||
if (isDesktop) { |
||||
Provider.of<AccountProvider>(context, listen: false).updateActivedApp(widget); |
||||
} else { |
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => widget)); |
||||
} |
||||
}, |
||||
child: Container( |
||||
height: 55.0, |
||||
child: Row( |
||||
children: [ |
||||
Container( |
||||
width: 45.0, |
||||
height: 45.0, |
||||
margin: const EdgeInsets.only(left: 20.0, right: 15.0), |
||||
decoration: BoxDecoration( |
||||
image: DecorationImage( |
||||
image: AssetImage('assets/logo/logo_light.png'), |
||||
fit: BoxFit.cover, |
||||
), |
||||
borderRadius: BorderRadius.circular(15.0) |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Container( |
||||
height: 55.0, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
children: [ |
||||
Expanded( |
||||
child: Text('esse', |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle(fontSize: 16.0)) |
||||
), |
||||
Container( |
||||
margin: const EdgeInsets.only(left: 15.0, right: 20.0), |
||||
child: Text('2021-11-12', |
||||
style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0), |
||||
), |
||||
) |
||||
]), |
||||
SizedBox(height: 5.0), |
||||
Expanded( |
||||
child: Text('esse is a echo robot', |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: const TextStyle(color: Color(0xFFADB0BB), fontSize: 12.0)), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
Loading…
Reference in new issue