Browse Source

add invite message type

pull/18/head
Sun 4 years ago
parent
commit
259613cd1c
  1. 2
      lib/apps/group_chat/add.dart
  2. 208
      lib/apps/group_chat/detail.dart
  3. 41
      lib/apps/group_chat/provider.dart
  4. 5
      lib/apps/primitives.dart
  5. 6
      lib/l10n/localizations.dart
  6. 12
      lib/l10n/localizations_en.dart
  7. 12
      lib/l10n/localizations_zh.dart
  8. 22
      lib/widgets/chat_message.dart
  9. 117
      lib/widgets/show_contact.dart
  10. 41
      pubspec.lock
  11. 3
      src/apps/chat/layer.rs
  12. 2
      src/apps/chat/mod.rs
  13. 6
      src/apps/chat/models.rs
  14. 2
      src/apps/group_chat/models.rs
  15. 86
      src/apps/group_chat/rpc.rs

2
lib/apps/group_chat/add.dart

@ -144,7 +144,7 @@ class _GroupAddPageState extends State<GroupAddPage> { @@ -144,7 +144,7 @@ class _GroupAddPageState extends State<GroupAddPage> {
addr = addr.substring(2);
}
var name = _joinNameController.text;
context.read<GroupChatProvider>().join(id, addr, name, "");
context.read<GroupChatProvider>().join(GroupType.Open, id, addr, name, "");
setState(() {
_joinIdController.text = '';
_joinAddrController.text = '';

208
lib/apps/group_chat/detail.dart

@ -14,6 +14,8 @@ import 'package:esse/widgets/shadow_dialog.dart'; @@ -14,6 +14,8 @@ 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/widgets/show_contact.dart';
import 'package:esse/rpc.dart';
import 'package:esse/global.dart';
import 'package:esse/provider.dart';
@ -214,7 +216,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> { @@ -214,7 +216,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
return Scaffold(
key: GroupChatDetail._scaffoldKey,
endDrawer: _MemberDrawerWidget(title: lang.members),
endDrawer: _MemberDrawerWidget(gid: this.group.gid, title: lang.members),
drawerScrimColor: color.background,
body: SafeArea(
child: Column(
@ -588,24 +590,38 @@ Widget _menuItem(Color color, int value, IconData icon, String text) { @@ -588,24 +590,38 @@ Widget _menuItem(Color color, int value, IconData icon, String text) {
}
class _MemberDrawerWidget extends StatelessWidget {
final String gid;
final String title;
const _MemberDrawerWidget({Key key, this.title}) : super(key: key);
const _MemberDrawerWidget({Key key, this.gid, this.title}) : super(key: key);
Widget _item(context, Member member, bool isOwner, Color color) {
Widget _meItem(Member member, bool meOwner, bool meManager, Color color, lang) {
return Container(
height: 55.0,
child: ListTile(
leading: member.showAvatar(colorSurface: false),
title: Text(lang.me, textAlign: TextAlign.left,
style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.italic)),
trailing: Text(meOwner ? lang.groupOwner : (meManager ? lang.manager : ''),
style: TextStyle(color: color)),
)
);
}
Widget _item(context, Member member, bool isOwner, bool meOwner, bool meManager, Color color, lang) {
return Container(
height: 55.0,
child: ListTile(
leading: member.showAvatar(colorSurface: false),
title: Text(member.name, textAlign: TextAlign.left, style: TextStyle(fontSize: 16.0)),
trailing: Text(member.isBlock
? 'Blocked' : (isOwner
? 'Owner' : (member.isManager
? 'Manager' : '')),
? lang.blocked : (isOwner
? lang.groupOwner : (member.isManager
? lang.manager : '')),
style: TextStyle(color: color)),
onTap: () {
Navigator.pop(context);
showShadowDialog(context, Icons.group_rounded, title,
MemberDetail(member: member, isGroupOwner: isOwner, isGroupManager: member.isManager),
MemberDetail(member: member, isGroupOwner: meOwner, isGroupManager: meManager),
10.0,
);
}
@ -613,16 +629,33 @@ class _MemberDrawerWidget extends StatelessWidget { @@ -613,16 +629,33 @@ class _MemberDrawerWidget extends StatelessWidget {
);
}
_action(List<int> ids) {
rpc.send('group-chat-invite', [gid, ids]);
}
_invite(context, String title) {
Navigator.pop(context);
showShadowDialog(context, Icons.people_rounded, title,
ContactList(callback: _action, multiple: true),
0.0,
);
}
@override
Widget build(BuildContext context) {
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
final isLight = color.brightness == Brightness.light;
final isDesktop = isDisplayDesktop(context);
final myId = context.read<AccountProvider>().activedAccountId;
final provider = context.watch<GroupChatProvider>();
final members = provider.activedMembers;
final allKeys = provider.activedMemberOrder;
final all = provider.activedMemberOrder(myId);
final allKeys = all[0];
final meId = all[1];
final meOwner = all[2];
final meManager = all[3];
return Drawer(
child: BackdropFilter(
@ -633,15 +666,41 @@ class _MemberDrawerWidget extends StatelessWidget { @@ -633,15 +666,41 @@ class _MemberDrawerWidget extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Column(
children: [
Text(lang.members, style: Theme.of(context).textTheme.title),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: const EdgeInsets.only(left: 20.0),
child: Text("${lang.members} (${allKeys.length + 1})",
style: Theme.of(context).textTheme.title),
),
Container(
margin: const EdgeInsets.only(right: 10.0),
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Color(0xFF6174FF)),
borderRadius: BorderRadius.circular(25.0)),
child: TextButton(child: Row(
children: [
Icon(Icons.add, size: 16.0),
Text(lang.invite),
]
),
onPressed: () => _invite(context, lang.contact),
),
)
]
),
const SizedBox(height: 10.0),
const Divider(height: 1.0, color: Color(0x40ADB0BB)),
const SizedBox(height: 10.0),
_meItem(members[meId], meOwner, meManager, color.primary, lang),
Expanded(
child: ListView.builder(
itemCount: allKeys.length,
itemBuilder: (BuildContext ctx, int index) => _item(
context, members[allKeys[index]], index == 0, color.primary
context, members[allKeys[index]],
index == 0 && !meOwner, meOwner, meManager, color.primary, lang
),
)
)
@ -702,75 +761,84 @@ class _MemberDetailState extends State<MemberDetail> { @@ -702,75 +761,84 @@ class _MemberDetailState extends State<MemberDetail> {
const SizedBox(height: 10.0),
_infoListTooltip(Icons.person, color.primary, widget.member.mid),
_infoListTooltip(Icons.location_on, color.primary, widget.member.addr),
const SizedBox(height: 10.0),
if (widget.isGroupOwner)
InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(widget.member.isManager ? 'Cancel Manager' : 'Set Manager',
style: TextStyle(fontSize: 14.0))),
Container(
padding: const EdgeInsets.only(top: 20.0, bottom: 10.0),
child: InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: color.primary),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(widget.member.isManager ? 'Cancel Manager' : 'Set Manager',
style: TextStyle(fontSize: 14.0, color: color.primary))),
)
)
),
const SizedBox(height: 10.0),
if (notFriend)
InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Color(0xFF6174FF)),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(lang.addFriend,
style: TextStyle(fontSize: 14.0, color: Color(0xFF6174FF)))),
Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Color(0xFF6174FF)),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(lang.addFriend,
style: TextStyle(fontSize: 14.0, color: Color(0xFF6174FF)))),
)
)
),
const SizedBox(height: 10.0),
if (widget.isGroupManager || widget.isGroupOwner)
InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(lang.delete,
style: TextStyle(fontSize: 14.0, color: Colors.red))),
Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: InkWell(
onTap: () {
Navigator.pop(context);
// TODO delete.
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(lang.delete,
style: TextStyle(fontSize: 14.0, color: Colors.red))),
)
)
),
InkWell(
onTap: () {
Navigator.pop(context);
context.read<GroupChatProvider>().memberUpdate(
widget.member.id, !widget.member.isBlock);
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(widget.member.isBlock ? 'Blocked' : 'Block',
style: TextStyle(fontSize: 14.0, color: Colors.red))),
Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: InkWell(
onTap: () {
Navigator.pop(context);
context.read<GroupChatProvider>().memberUpdate(
widget.member.id, !widget.member.isBlock);
},
hoverColor: Colors.transparent,
child: Container(
width: 300.0,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(10.0)),
child: Center(child: Text(widget.member.isBlock ? lang.blocked : lang.block,
style: TextStyle(fontSize: 14.0, color: Colors.black))),
)
)
),
]

41
lib/apps/group_chat/provider.dart

@ -33,27 +33,40 @@ class GroupChatProvider extends ChangeNotifier { @@ -33,27 +33,40 @@ class GroupChatProvider extends ChangeNotifier {
return false;
}
List<int> get activedMemberOrder {
List activedMemberOrder(String myId) {
int meId = 0;
bool meOwner = false;
bool meManager = false;
List<int> allKeys = [];
List<int> managers = [];
List<int> commons = [];
List<int> blocks = [];
this.activedMembers.forEach((i, m) {
if (m.isBlock) {
blocks.add(i);
} else {
if (m.mid == myId) {
meId = i;
if (m.isManager) {
meManager = true;
if (m.mid == this.activedGroup.owner) {
allKeys.add(i);
} else {
managers.add(i);
meOwner = true;
}
}
} else {
if (m.isBlock) {
blocks.add(i);
} else {
commons.add(i);
if (m.isManager) {
if (m.mid == this.activedGroup.owner) {
allKeys.add(i);
} else {
managers.add(i);
}
} else {
commons.add(i);
}
}
}
});
return allKeys + managers + commons + blocks;
return [allKeys + managers + commons + blocks, meId, meOwner, meManager];
}
GroupChatProvider() {
@ -117,8 +130,8 @@ class GroupChatProvider extends ChangeNotifier { @@ -117,8 +130,8 @@ class GroupChatProvider extends ChangeNotifier {
rpc.send('group-chat-resend', [id, myName]);
}
join(String gid, String gaddr, String name, String remark, [String key = '']) {
rpc.send('group-chat-join', [gid, gaddr, name, remark, key]);
join(GroupType gtype, String gid, String gaddr, String name, String remark, [String proof = '', String key = '']) {
rpc.send('group-chat-join', [gtype.toInt(), gid, gaddr, name, remark, proof, key]);
}
requestHandle(String gid, int id, int rid, bool ok) {
@ -150,6 +163,12 @@ class GroupChatProvider extends ChangeNotifier { @@ -150,6 +163,12 @@ class GroupChatProvider extends ChangeNotifier {
// rpc.send('group-chat-readd', [id]);
}
invite(String gid, List<int> ids) {
print(gid);
print(ids);
rpc.send('group-chat-invite', [ids]);
}
memberUpdate(int id, bool isBlock) {
rpc.send('group-chat-member-update', [id, isBlock]);
}

5
lib/apps/primitives.dart

@ -11,6 +11,7 @@ enum MessageType { @@ -11,6 +11,7 @@ enum MessageType {
Record,
Phone,
Video,
Invite,
}
// use 00-99
@ -33,6 +34,8 @@ extension MessageTypeExtension on MessageType { @@ -33,6 +34,8 @@ extension MessageTypeExtension on MessageType {
return 6;
case MessageType.Video:
return 7;
case MessageType.Invite:
return 8;
default:
return 0;
}
@ -56,6 +59,8 @@ extension MessageTypeExtension on MessageType { @@ -56,6 +59,8 @@ extension MessageTypeExtension on MessageType {
return MessageType.Phone;
case 7:
return MessageType.Video;
case 8:
return MessageType.Invite;
default:
return MessageType.String;
}

6
lib/l10n/localizations.dart

@ -82,6 +82,11 @@ abstract class AppLocalizations { @@ -82,6 +82,11 @@ abstract class AppLocalizations {
String get create;
String get exit;
String get loadMore;
String get me;
String get manager;
String get block;
String get blocked;
String get invite;
// theme
String get themeDark;
@ -175,6 +180,7 @@ abstract class AppLocalizations { @@ -175,6 +180,7 @@ abstract class AppLocalizations {
String get groupChatBio;
String get groupJoin;
String get groupCreate;
String get groupOwner;
String get groupTypeEncrypted;
String get groupTypeEncryptedInfo;
String get groupTypePrivate;

12
lib/l10n/localizations_en.dart

@ -88,6 +88,16 @@ class AppLocalizationsEn extends AppLocalizations { @@ -88,6 +88,16 @@ class AppLocalizationsEn extends AppLocalizations {
String get exit => 'Exit';
@override
String get loadMore => 'Load more...';
@override
String get me => 'Me';
@override
String get manager => 'Manager';
@override
String get block => 'Block';
@override
String get blocked => 'Blocked';
@override
String get invite => 'Invite';
// theme
@override
@ -261,6 +271,8 @@ class AppLocalizationsEn extends AppLocalizations { @@ -261,6 +271,8 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get groupCreate => 'Create Group';
@override
String get groupOwner => 'Owner';
@override
String get groupTypeEncrypted => 'Encrypted';
@override
String get groupTypeEncryptedInfo => "Encrypted: It can only be joined by the invitation of members, and the manager's consent is optional, Members hold a zero-knowledge proof about the key to enter; Group information and messages are encrypted and stored on the server, and the server NOT has secret key, INVISIBLE information.";

12
lib/l10n/localizations_zh.dart

@ -88,6 +88,16 @@ class AppLocalizationsZh extends AppLocalizations { @@ -88,6 +88,16 @@ class AppLocalizationsZh extends AppLocalizations {
String get exit => '退出';
@override
String get loadMore => '加载更多';
@override
String get me => '';
@override
String get manager => '管理员';
@override
String get block => '拉黑';
@override
String get blocked => '已拉黑';
@override
String get invite => '邀请';
// theme
@override
@ -261,6 +271,8 @@ class AppLocalizationsZh extends AppLocalizations { @@ -261,6 +271,8 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get groupCreate => '新建群';
@override
String get groupOwner => '群主';
@override
String get groupTypeEncrypted => '加密';
@override
String get groupTypeEncryptedInfo => '加密的群聊:只能通过群成员邀请加入,可选是否需要管理员同意,成员需持有密钥的零知识证明方可进入;群信息和消息全部加密存储在服务端,服务端无密钥,不可见信息。';

22
lib/widgets/chat_message.dart

@ -308,6 +308,26 @@ class ChatMessage extends StatelessWidget { @@ -308,6 +308,26 @@ class ChatMessage extends StatelessWidget {
}
}
Widget _showInvite(context, lang, color) {
// contact [name, gid, addr, avatar]
//final infos = message.showContact();
//final gid = 'EG' + infos[1].toUpperCase();
final width = MediaQuery.of(context).size.width * 0.6;
// text
return Container(
constraints: BoxConstraints(minWidth: 50, maxWidth: width),
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 14.0),
decoration: BoxDecoration(
color: message.isMe ? Color(0xFF6174FF) : color.primaryVariant,
borderRadius: BorderRadius.circular(15.0),
),
child: Text(message.content,
style: TextStyle(
color: message.isMe ? Colors.white : Color(0xFF1C1939),
fontSize: 14.0)));
}
Widget _infoListTooltip(icon, color, text) {
return Container(
width: 300.0,
@ -338,6 +358,8 @@ class ChatMessage extends StatelessWidget { @@ -338,6 +358,8 @@ class ChatMessage extends StatelessWidget {
return _showContact(context, lang, color);
} else if (message.type == MessageType.Record) {
return _showRecord();
} else if (message.type == MessageType.Invite) {
return _showInvite(context, lang, color);
}
return _showText(context, color, isDesktop);
}

117
lib/widgets/show_contact.dart

@ -1,12 +1,65 @@ @@ -1,12 +1,65 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:esse/l10n/localizations.dart';
import 'package:esse/models/friend.dart';
import 'package:esse/widgets/shadow_dialog.dart';
import 'package:esse/apps/chat/models.dart' show Friend;
import 'package:esse/apps/chat/provider.dart';
openContact(BuildContext context, ColorScheme color, AppLocalizations lang, List<int> orders, Map<int, Friend> friends, Function callback) {
showShadowDialog(
context, Icons.person_rounded, lang.contact, Column(
class ContactList extends StatefulWidget {
final Function callback;
final bool multiple;
const ContactList({Key key, this.callback, this.multiple}): super(key: key);
@override
_ContactListState createState() => _ContactListState();
}
class _ContactListState extends State<ContactList> {
List<bool> _checks = [];
Map<int, Friend> _friends = {};
List<int> _keys = [];
@override
initState() {
super.initState();
new Future.delayed(Duration.zero, () {
final provider = context.read<ChatProvider>();
_friends = provider.friends;
_keys = provider.orderKeys;
_checks = List<bool>.generate(_keys.length, (_) => false);
setState(() {});
});
}
Widget _friend(int i, Friend friend) {
return Container(
height: 55.0,
child: ListTile(
leading: friend.showAvatar(),
title: Text(friend.name),
trailing: Checkbox(
value: _checks[i],
onChanged: (bool value) {
setState(() {
_checks[i] = value;
});
},
),
)
);
}
@override
Widget build(BuildContext context) {
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
double maxHeight = (MediaQuery.of(context).size.height - 300);
if (maxHeight < 100.0) {
maxHeight = 100.0;
}
return Column(
children: [
Container(
height: 40.0,
@ -29,28 +82,38 @@ openContact(BuildContext context, ColorScheme color, AppLocalizations lang, List @@ -29,28 +82,38 @@ openContact(BuildContext context, ColorScheme color, AppLocalizations lang, List
),
),
),
SizedBox(height: 15.0),
Column(
children: orders.map<Widget>((id) {
final contact = friends[id];
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => callback(context, contact.id),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 14.0),
child: Row(
children: [
contact.showAvatar(needOnline: false),
SizedBox(width: 15.0),
Text(contact.name, style: TextStyle(fontSize: 16.0)),
],
),
),
);
}).toList()
const SizedBox(height: 16.0),
Container(
height: maxHeight,
child: SingleChildScrollView(
child: Column(children: List<Widget>.generate(_keys.length, (i) =>
_friend(i, _friends[_keys[i]])
))
)
),
const Divider(height: 1.0, color: Color(0x40ADB0BB)),
const SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(child: Text(lang.cancel, style: TextStyle(color: color.onSurface)),
onPressed: () => Navigator.pop(context),
),
TextButton(child: Text(lang.ok),
onPressed: () {
Navigator.pop(context);
List<int> ids = [];
_keys.asMap().forEach((i, value) {
if (_checks[i]) {
ids.add(value);
}
});
widget.callback(ids);
},
),
]
)
]
)
);
);
}
}

41
pubspec.lock

@ -21,14 +21,14 @@ packages: @@ -21,14 +21,14 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
version: "2.7.0"
audio_session:
dependency: transitive
description:
name: audio_session
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
version: "0.1.2"
boolean_selector:
dependency: transitive
description:
@ -64,6 +64,13 @@ packages: @@ -64,6 +64,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
collision:
dependency: transitive
description:
name: collision
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.3"
convert:
dependency: "direct main"
description:
@ -77,7 +84,7 @@ packages: @@ -77,7 +84,7 @@ packages:
name: crop
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.1"
version: "0.5.1+1"
cross_file:
dependency: transitive
description:
@ -154,7 +161,7 @@ packages: @@ -154,7 +161,7 @@ packages:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.1"
file:
dependency: transitive
description:
@ -168,7 +175,7 @@ packages: @@ -168,7 +175,7 @@ packages:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.0.2+2"
file_selector:
dependency: "direct main"
description:
@ -181,7 +188,7 @@ packages: @@ -181,7 +188,7 @@ packages:
description:
path: "plugins/file_selector/file_selector_linux"
ref: HEAD
resolved-ref: f2d8aa3820fb87316516670bf4d51a74de8ac0dd
resolved-ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
url: "git://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.0.2"
@ -190,7 +197,7 @@ packages: @@ -190,7 +197,7 @@ packages:
description:
path: "plugins/file_selector/file_selector_macos"
ref: HEAD
resolved-ref: f2d8aa3820fb87316516670bf4d51a74de8ac0dd
resolved-ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
url: "git://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.0.4"
@ -213,7 +220,7 @@ packages: @@ -213,7 +220,7 @@ packages:
description:
path: "plugins/file_selector/file_selector_windows"
ref: HEAD
resolved-ref: f2d8aa3820fb87316516670bf4d51a74de8ac0dd
resolved-ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
url: "git://github.com/google/flutter-desktop-embedding.git"
source: git
version: "0.0.2"
@ -245,14 +252,14 @@ packages: @@ -245,14 +252,14 @@ packages:
name: flutter_localized_locales
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.2"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.2"
flutter_test:
dependency: "direct dev"
description: flutter
@ -302,7 +309,7 @@ packages: @@ -302,7 +309,7 @@ packages:
name: image_picker
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.5+2"
version: "0.7.5+3"
image_picker_for_web:
dependency: transitive
description:
@ -342,7 +349,7 @@ packages: @@ -342,7 +349,7 @@ packages:
name: just_audio
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.4+1"
version: "0.7.5"
just_audio_platform_interface:
dependency: transitive
description:
@ -370,7 +377,7 @@ packages: @@ -370,7 +377,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.4.0"
nested:
dependency: transitive
description:
@ -398,7 +405,7 @@ packages: @@ -398,7 +405,7 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.2"
path_provider_linux:
dependency: transitive
description:
@ -524,14 +531,14 @@ packages: @@ -524,14 +531,14 @@ packages:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.26.0"
version: "0.27.1"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.0.6"
shared_preferences_linux:
dependency: transitive
description:
@ -620,7 +627,7 @@ packages: @@ -620,7 +627,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
version: "0.4.0"
typed_data:
dependency: transitive
description:

3
src/apps/chat/layer.rs

@ -445,6 +445,7 @@ impl LayerEvent { @@ -445,6 +445,7 @@ impl LayerEvent {
// TODO
(NetworkMessage::Video, content)
}
MessageType::Invite => (NetworkMessage::Invite(content.clone()), content),
};
let mut msg = Message::new(&mgid, fid, true, m_type, raw, false);
@ -499,7 +500,7 @@ pub(super) fn reject_message( @@ -499,7 +500,7 @@ pub(super) fn reject_message(
SendType::Event(uid, addr, data)
}
pub(super) fn event_message(
pub(crate) fn event_message(
layer: &mut Layer,
tid: i64,
me_id: GroupId,

2
src/apps/chat/mod.rs

@ -2,8 +2,8 @@ mod layer; @@ -2,8 +2,8 @@ mod layer;
mod models;
pub(crate) mod rpc;
pub(crate) use layer::chat_conn;
pub(crate) use layer::handle as layer_handle;
pub(crate) use layer::LayerEvent;
pub(crate) use layer::{chat_conn, event_message};
pub(crate) use models::{Friend, Message, MessageType, NetworkMessage, Request};
pub(crate) use rpc::new_rpc_handler;

6
src/apps/chat/models.rs

@ -51,6 +51,7 @@ pub(crate) enum NetworkMessage { @@ -51,6 +51,7 @@ pub(crate) enum NetworkMessage {
Emoji,
Phone,
Video,
Invite(String),
None,
}
@ -97,6 +98,7 @@ impl NetworkMessage { @@ -97,6 +98,7 @@ impl NetworkMessage {
// TODO
(MessageType::Video, "".to_owned())
}
NetworkMessage::Invite(content) => (MessageType::Invite, content),
NetworkMessage::None => {
return Ok(Message::new_with_id(
hash,
@ -148,6 +150,7 @@ impl NetworkMessage { @@ -148,6 +150,7 @@ impl NetworkMessage {
};
Ok(NetworkMessage::Record(bytes, time))
}
MessageType::Invite => Ok(NetworkMessage::Invite(model.content)),
MessageType::Emoji => Ok(NetworkMessage::Emoji),
MessageType::Phone => Ok(NetworkMessage::Phone),
MessageType::Video => Ok(NetworkMessage::Video),
@ -165,6 +168,7 @@ pub(crate) enum MessageType { @@ -165,6 +168,7 @@ pub(crate) enum MessageType {
Record,
Phone,
Video,
Invite,
}
impl MessageType {
@ -178,6 +182,7 @@ impl MessageType { @@ -178,6 +182,7 @@ impl MessageType {
MessageType::Record => 5,
MessageType::Phone => 6,
MessageType::Video => 7,
MessageType::Invite => 8,
}
}
@ -191,6 +196,7 @@ impl MessageType { @@ -191,6 +196,7 @@ impl MessageType {
5 => MessageType::Record,
6 => MessageType::Phone,
7 => MessageType::Video,
8 => MessageType::Invite,
_ => MessageType::String,
}
}

2
src/apps/group_chat/models.rs

@ -65,7 +65,7 @@ pub(crate) struct GroupChat { @@ -65,7 +65,7 @@ pub(crate) struct GroupChat {
/// group chat id.
pub g_id: GroupId,
/// group chat type.
g_type: GroupType,
pub g_type: GroupType,
/// group chat server addresse.
pub g_addr: PeerAddr,
/// group chat name.

86
src/apps/group_chat/rpc.rs

@ -9,9 +9,9 @@ use tdn_did::Proof; @@ -9,9 +9,9 @@ use tdn_did::Proof;
use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent};
use crate::apps::chat::MessageType;
use crate::apps::chat::{Friend, MessageType};
use crate::rpc::RpcState;
use crate::storage::group_chat_db;
use crate::storage::{chat_db, group_chat_db};
use super::add_layer;
use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request};
@ -236,11 +236,14 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -236,11 +236,14 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
handler.add_method(
"group-chat-join",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {
let gcd = GroupId::from_hex(params[0].as_str()?)?;
let gaddr = PeerAddr::from_hex(params[1].as_str()?)?;
let gname = params[2].as_str()?.to_owned();
let gremark = params[3].as_str()?.to_owned();
let gkey = params[4].as_str()?;
let _gtype = GroupType::from_u32(params[0].as_i64()? as u32);
let gcd = GroupId::from_hex(params[1].as_str()?)?;
let gaddr = PeerAddr::from_hex(params[2].as_str()?)?;
let gname = params[3].as_str()?.to_owned();
let gremark = params[4].as_str()?.to_owned();
let gproof = params[5].as_str()?;
let _proof = Proof::from_hex(gproof).unwrap_or(Proof::default());
let gkey = params[6].as_str()?;
let key = GroupChatKey::from_hex(gkey).unwrap_or(GroupChatKey::new(vec![]));
let mut request = Request::new_by_me(gcd, gaddr, gname, gremark, key);
@ -259,6 +262,75 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -259,6 +262,75 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
},
);
handler.add_method(
"group-chat-invite",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {
let id = params[0].as_i64()?;
let gcd = GroupId::from_hex(params[1].as_str()?)?;
let ids: Vec<i64> = params[2]
.as_array()?
.iter()
.filter_map(|v| v.as_i64())
.collect();
//
let group_lock = state.group.read().await;
let base = group_lock.base().clone();
let chat = chat_db(&base, &gid)?;
let group_db = group_chat_db(&base, &gid)?;
let mut invites = vec![];
for id in ids {
let friend = Friend::get_id(&chat, id)??;
if Member::get_id(&group_db, &id, &friend.gid).is_err() {
let proof = group_lock.prove_addr(&gid, &friend.gid.into())?;
invites.push((friend.id, friend.gid, friend.addr, proof));
}
}
drop(chat);
let gc = GroupChat::get_id(&group_db, &id)??;
let tmp_name = gc.g_name.replace(";", "-;");
let mut results = HandleResult::new();
let mut layer_lock = state.layer.write().await;
for (fid, fgid, mut faddr, proof) in invites {
let contact_values = format!(
"{};;{};;{};;{};;{}",
gc.g_type.to_u32(),
gcd.to_hex(),
gc.g_addr.to_hex(),
tmp_name,
proof.to_hex(),
);
// check if encrypted group type. need online.
if gc.g_type == GroupType::Encrypted {
if let Ok(addr) = layer_lock.running(&gid)?.online(&fgid) {
faddr = addr;
} else {
continue;
}
}
let (msg, nw) = crate::apps::chat::LayerEvent::from_message(
&base,
gid,
fid,
MessageType::Invite,
contact_values,
)
.await?;
let event = crate::apps::chat::LayerEvent::Message(msg.hash, nw);
let s =
crate::apps::chat::event_message(&mut layer_lock, msg.id, gid, faddr, &event);
results.layers.push((gid, fgid, s));
}
Ok(results)
},
);
handler.add_method(
"group-chat-request-handle",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {

Loading…
Cancel
Save