Browse Source

add member join UI

pull/18/head
Sun 4 years ago
parent
commit
c932db2e30
  1. 15
      lib/apps/group_chat/add.dart
  2. 36
      lib/apps/group_chat/models.dart
  3. 32
      lib/apps/group_chat/provider.dart
  4. 2
      pubspec.lock
  5. 23
      src/apps/group_chat/layer.rs
  6. 103
      src/apps/group_chat/models.rs
  7. 45
      src/apps/group_chat/rpc.rs
  8. 2
      src/migrate/group_chat.rs

15
lib/apps/group_chat/add.dart

@ -16,7 +16,6 @@ import 'package:esse/widgets/qr_scan.dart'; @@ -16,7 +16,6 @@ import 'package:esse/widgets/qr_scan.dart';
import 'package:esse/global.dart';
import 'package:esse/provider.dart';
import 'package:esse/apps/chat/models.dart' show Request; // TODO delete.
import 'package:esse/apps/group_chat/models.dart';
import 'package:esse/apps/group_chat/provider.dart';
@ -112,7 +111,7 @@ class _GroupAddPageState extends State<GroupAddPage> { @@ -112,7 +111,7 @@ class _GroupAddPageState extends State<GroupAddPage> {
return;
}
if (id.substring(0, 2) == 'EH') {
if (id.substring(0, 2) == 'EG') {
id = id.substring(2);
}
@ -123,8 +122,7 @@ class _GroupAddPageState extends State<GroupAddPage> { @@ -123,8 +122,7 @@ class _GroupAddPageState extends State<GroupAddPage> {
}
var name = _joinNameController.text;
var remark = _joinRemarkController.text;
//context.read<GroupChatProvider>().requestCreate(Request(id, addr, name, remark));
context.read<GroupChatProvider>().join(id, addr, name, remark);
setState(() {
_joinIdController.text = '';
_joinAddrController.text = '';
@ -135,7 +133,11 @@ class _GroupAddPageState extends State<GroupAddPage> { @@ -135,7 +133,11 @@ class _GroupAddPageState extends State<GroupAddPage> {
_create() {
final myName = context.read<AccountProvider>().activedAccount.name;
final addr = _createAddrController.text.trim();
var addr = _createAddrController.text.trim();
// if has 0x, need remove
if (addr.substring(0, 2) == '0x') {
addr = addr.substring(2);
}
final name = _createNameController.text.trim();
final bio = _createBioController.text.trim();
context.read<GroupChatProvider>().create(myName, addr, name, bio, _groupNeedAgree);
@ -520,7 +522,8 @@ class _RequestItem extends StatelessWidget { @@ -520,7 +522,8 @@ class _RequestItem extends StatelessWidget {
const SizedBox(height: 10.0),
const Divider(height: 1.0, color: Color(0x40ADB0BB)),
const SizedBox(height: 10.0),
_infoListTooltip(Icons.person, color.primary, 'EH' + request.gid.toUpperCase()),
_infoListTooltip(Icons.person, color.primary,
(request.isMe ? 'EG' : 'EH') + request.gid.toUpperCase()),
_infoListTooltip(Icons.location_on, color.primary, "0x" + request.addr),
_infoList(Icons.turned_in, color.primary, request.remark),
_infoList(Icons.access_time_rounded, color.primary, request.time.toString()),

36
lib/apps/group_chat/models.dart

@ -135,6 +135,42 @@ class GroupChat { @@ -135,6 +135,42 @@ class GroupChat {
}
}
class Request {
int id;
int fid;
String gid;
String addr;
String name;
String remark;
bool ok;
bool over;
RelativeTime time;
bool get isMe => this.fid == 0;
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.fid = params[1];
this.gid = params[2];
this.addr = params[3];
this.name = params[4];
this.remark = params[5];
this.ok = params[6];
this.over = params[7];
this.time = RelativeTime.fromInt(params[8]);
}
}
class Member {
int id;
int fid;

32
lib/apps/group_chat/provider.dart

@ -15,7 +15,7 @@ class GroupChatProvider extends ChangeNotifier { @@ -15,7 +15,7 @@ class GroupChatProvider extends ChangeNotifier {
Map<int, GroupChat> groups = {};
List<int> createKeys = [];
List<int> orderKeys = [];
SplayTreeMap<int, GroupChat> requests = SplayTreeMap();
SplayTreeMap<int, Request> requests = SplayTreeMap();
int actived;
SplayTreeMap<int, Message> activedMessages = SplayTreeMap();
@ -42,11 +42,11 @@ class GroupChatProvider extends ChangeNotifier { @@ -42,11 +42,11 @@ class GroupChatProvider extends ChangeNotifier {
rpc.addListener('group-chat-result', _result, false);
rpc.addListener('group-chat-detail', _detail, true);
// rpc.addListener('group-chat-update', _update, false);
// rpc.addListener('group-chat-join', _join, true);
rpc.addListener('group-chat-join', _join, true);
// rpc.addListener('group-chat-agree', _agree, true);
// rpc.addListener('group-chat-reject', _reject, false);
rpc.addListener('group-chat-member-join', _memberJoin, false);
// rpc.addListener('group-chat-member-info', _memberInfo, false);
rpc.addListener('group-chat-member-info', _memberInfo, false);
// rpc.addListener('group-chat-member-leave', _memberLeave, false);
rpc.addListener('group-chat-member-online', _memberOnline, false);
rpc.addListener('group-chat-member-offline', _memberOffline, false);
@ -86,6 +86,7 @@ class GroupChatProvider extends ChangeNotifier { @@ -86,6 +86,7 @@ class GroupChatProvider extends ChangeNotifier {
}
create(String myName, String addr, String name, String bio, bool needAgree) {
print(addr);
rpc.send('group-chat-create', [myName, addr, name, bio, needAgree]);
}
@ -93,6 +94,10 @@ class GroupChatProvider extends ChangeNotifier { @@ -93,6 +94,10 @@ class GroupChatProvider extends ChangeNotifier {
//
}
join(String gid, String gaddr, String name, String remark) {
rpc.send('group-chat-join', [gid, gaddr, name, remark]);
}
messageCreate(MessageType mtype, String content) {
final gid = this.activedGroup.gid;
rpc.send('group-chat-message-create', [gid, mtype.toInt(), content]);
@ -173,8 +178,27 @@ class GroupChatProvider extends ChangeNotifier { @@ -173,8 +178,27 @@ class GroupChatProvider extends ChangeNotifier {
}
}
_join(List params) {
this.requests[params[0]] = Request.fromList(params);
notifyListeners();
}
_memberJoin(List params) {
//
final member = Member.fromList(params);
if (this.actived == member.fid) {
this.activedMembers[member.id] = member;
// TODO Better add UI member joined.
notifyListeners();
}
}
_memberInfo(List params) {
final id = params[0];
if (this.activedMembers.containsKey(id)) {
this.activedMembers[id].addr = params[1];
this.activedMembers[id].name = params[2];
notifyListeners();
}
}
_memberOnline(List params) {

2
pubspec.lock

@ -21,7 +21,7 @@ packages: @@ -21,7 +21,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.0"
version: "2.6.1"
audio_session:
dependency: transitive
description:

23
src/apps/group_chat/layer.rs

@ -13,7 +13,7 @@ use group_chat_types::{Event, GroupConnect, GroupResult, JoinProof, LayerEvent}; @@ -13,7 +13,7 @@ use group_chat_types::{Event, GroupConnect, GroupResult, JoinProof, LayerEvent};
use tdn_did::Proof;
use crate::layer::{Layer, Online};
use crate::storage::group_chat_db;
use crate::storage::{group_chat_db, write_avatar_sync};
use super::models::{from_network_message, GroupChat, Member};
use super::{add_layer, rpc};
@ -146,20 +146,32 @@ async fn handle_event( @@ -146,20 +146,32 @@ async fn handle_event(
results.rpcs.push(rpc::group_online(mgid, gid));
}
LayerEvent::Sync(_, height, event) => {
let base = layer.read().await.base().clone();
let db = group_chat_db(&base, &mgid)?;
match event {
Event::GroupInfo => {}
Event::GroupTransfer => {}
Event::GroupManagerAdd => {}
Event::GroupManagerDel => {}
Event::GroupClose => {}
Event::MemberInfo(mid, maddr, mname, mavatar) => {}
Event::MemberInfo(mid, maddr, mname, mavatar) => {
let id = Member::get_id(&db, &gid, &mid)?;
Member::update(&db, &id, &maddr, &mname)?;
if mavatar.len() > 0 {
write_avatar_sync(&base, &mgid, &mid, mavatar)?;
}
results.rpcs.push(rpc::member_info(mgid, id, maddr, mname));
}
Event::MemberJoin(mid, maddr, mname, mavatar, mtime) => {
let db = group_chat_db(layer.read().await.base(), &mgid)?;
let mut member = Member::new(gid, mid, maddr, mname, false, mtime);
member.insert(&db)?;
if mavatar.len() > 0 {
write_avatar_sync(&base, &mgid, &mid, mavatar)?;
}
results.rpcs.push(rpc::member_join(mgid, member));
}
Event::MemberLeave(mid) => {}
Event::MemberLeave(_mid) => {}
Event::MessageCreate(mid, nmsg, mtime) => {
let base = layer.read().await.base.clone();
let msg =
@ -169,8 +181,7 @@ async fn handle_event( @@ -169,8 +181,7 @@ async fn handle_event(
}
// save event.
// update to UI.
GroupChat::add_height(&db, gid, height)?;
}
LayerEvent::MemberOnline(_, mid, maddr) => {
results.rpcs.push(rpc::member_online(mgid, gid, mid, maddr));

103
src/apps/group_chat/models.rs

@ -274,6 +274,11 @@ impl GroupChat { @@ -274,6 +274,11 @@ impl GroupChat {
db.update(&sql)
}
pub fn add_height(db: &DStorage, id: i64, height: i64) -> Result<usize> {
let sql = format!("UPDATE groups SET height={} WHERE id = {}", height, id,);
db.update(&sql)
}
pub fn update_last_message(db: &DStorage, id: i64, msg: &Message, read: bool) -> Result<usize> {
let sql = format!(
"UPDATE groups SET last_datetime={}, last_content='{}', last_readed={} WHERE id = {}",
@ -291,6 +296,94 @@ impl GroupChat { @@ -291,6 +296,94 @@ impl GroupChat {
}
}
/// Group Join Request model. include my requests and other requests.
/// When fid is 0, it's my requests.
pub(crate) struct Request {
id: i64,
fid: i64,
pub gid: GroupId,
pub addr: PeerAddr,
pub name: String,
remark: String,
is_ok: bool,
is_over: bool,
datetime: i64,
}
impl Request {
pub fn new_by_remote(
fid: i64,
gid: GroupId,
addr: PeerAddr,
name: String,
remark: String,
datetime: i64,
) -> Self {
Self {
fid,
gid,
addr,
name,
remark,
datetime,
is_ok: false,
is_over: false,
id: 0,
}
}
pub fn new_by_me(gid: GroupId, addr: PeerAddr, name: String, remark: String) -> Self {
let start = SystemTime::now();
let datetime = start
.duration_since(UNIX_EPOCH)
.map(|s| s.as_secs())
.unwrap_or(0) as i64; // safe for all life.
Self {
gid,
addr,
name,
remark,
datetime,
is_ok: false,
is_over: false,
fid: 0,
id: 0,
}
}
pub fn to_rpc(&self) -> RpcParam {
json!([
self.id,
self.fid,
self.gid.to_hex(),
self.addr.to_hex(),
self.name,
self.remark,
self.is_ok,
self.is_over,
self.datetime,
])
}
pub fn insert(&mut self, db: &DStorage) -> Result<()> {
let sql = format!("INSERT INTO requests (fid, gid, addr, name, remark, is_ok, is_over, datetime, is_deleted) VALUES ({}, '{}', '{}', '{}', '{}', {}, {}, {}, false)",
self.fid,
self.gid.to_hex(),
self.addr.to_hex(),
self.name,
self.remark,
if self.is_ok { 1 } else { 0 },
if self.is_over { 1 } else { 0 },
self.datetime,
);
println!("{}", sql);
let id = db.insert(&sql)?;
self.id = id;
Ok(())
}
}
/// Group Member Model.
pub(crate) struct Member {
/// db auto-increment id.
@ -398,6 +491,16 @@ impl Member { @@ -398,6 +491,16 @@ impl Member {
Err(new_io_error("missing member"))
}
}
pub fn update(db: &DStorage, id: &i64, addr: &PeerAddr, name: &str) -> Result<usize> {
let sql = format!(
"UPDATE members SET addr='{}', name='{}' WHERE id = {}",
addr.to_hex(),
name,
id,
);
db.update(&sql)
}
}
/// Group Chat Message Model.

45
src/apps/group_chat/rpc.rs

@ -7,14 +7,14 @@ use tdn::types::{ @@ -7,14 +7,14 @@ use tdn::types::{
};
use tdn_did::Proof;
use group_chat_types::{CheckType, Event, GroupConnect, GroupType, LayerEvent, NetworkMessage};
use group_chat_types::{CheckType, Event, GroupConnect, GroupType, JoinProof, LayerEvent};
use crate::apps::chat::MessageType;
use crate::rpc::RpcState;
use crate::storage::group_chat_db;
use super::add_layer;
use super::models::{to_network_message, GroupChat, Member, Message};
use super::models::{to_network_message, GroupChat, Member, Message, Request};
#[inline]
pub(crate) fn create_check(mgid: GroupId, ct: CheckType, supported: Vec<GroupType>) -> RpcParam {
@ -42,6 +42,16 @@ pub(crate) fn member_join(mgid: GroupId, member: Member) -> RpcParam { @@ -42,6 +42,16 @@ pub(crate) fn member_join(mgid: GroupId, member: Member) -> RpcParam {
rpc_response(0, "group-chat-member-join", json!(member.to_rpc()), mgid)
}
#[inline]
pub(crate) fn member_info(mgid: GroupId, id: i64, addr: PeerAddr, name: String) -> RpcParam {
rpc_response(
0,
"group-chat-member-info",
json!([id, addr.to_hex(), name]),
mgid,
)
}
#[inline]
pub(crate) fn member_online(mgid: GroupId, gid: i64, mid: GroupId, maddr: PeerAddr) -> RpcParam {
rpc_response(
@ -129,9 +139,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -129,9 +139,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
handler.add_method(
"group-chat-check",
|gid: GroupId, params: Vec<RpcParam>, _state: Arc<RpcState>| async move {
let addr = PeerAddr::from_hex(params[0].as_str()?)
.map_err(|_e| new_io_error("PeerAddr invalid!"))?;
println!("addr: {}", addr.to_hex());
let addr = PeerAddr::from_hex(params[0].as_str()?)?;
let mut results = HandleResult::new();
let data = postcard::to_allocvec(&GroupConnect::Check).unwrap_or(vec![]);
@ -145,8 +153,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -145,8 +153,7 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
"group-chat-create",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {
let my_name = params[0].as_str()?.to_owned();
let addr = PeerAddr::from_hex(params[1].as_str()?)
.map_err(|_e| new_io_error("PeerAddr invalid!"))?;
let addr = PeerAddr::from_hex(params[1].as_str()?)?;
let name = params[2].as_str()?.to_owned();
let bio = params[3].as_str()?.to_owned();
let need_agree = params[4].as_bool()?;
@ -178,6 +185,30 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -178,6 +185,30 @@ 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 mut request = Request::new_by_me(gcd, gaddr, gname, gremark);
let db = group_chat_db(state.layer.read().await.base(), &gid)?;
request.insert(&db)?;
drop(db);
let mut results = HandleResult::rpc(request.to_rpc());
let me = state.group.read().await.clone_user(&gid)?;
let join_proof = JoinProof::Open(me.name, me.avatar);
let data = postcard::to_allocvec(&GroupConnect::Join(request.gid, join_proof))
.unwrap_or(vec![]);
let s = SendType::Connect(0, request.addr, None, None, data);
add_layer(&mut results, gid, s);
Ok(results)
},
);
handler.add_method(
"group-chat-message-create",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {

2
src/migrate/group_chat.rs

@ -22,7 +22,7 @@ pub(super) const GROUP_CHAT_VERSIONS: [&str; 4] = [ @@ -22,7 +22,7 @@ pub(super) const GROUP_CHAT_VERSIONS: [&str; 4] = [
"CREATE TABLE IF NOT EXISTS requests(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
fid INTEGER NOT NULL,
mid TEXT NOT NULL,
gid TEXT NOT NULL,
addr TEXT NOT NULL,
name TEXT NOT NULL,
remark TEXT,

Loading…
Cancel
Save