diff --git a/lib/apps/group_chat/provider.dart b/lib/apps/group_chat/provider.dart index 1eaa1b8..dc84265 100644 --- a/lib/apps/group_chat/provider.dart +++ b/lib/apps/group_chat/provider.dart @@ -35,8 +35,8 @@ class GroupChatProvider extends ChangeNotifier { GroupChatProvider() { // rpc. rpc.addListener('group-chat-list', _list, false); - // rpc.addListener('group-chat-online', _online, false); - // rpc.addListener('group-chat-offline', _online, false); + rpc.addListener('group-chat-online', _online, false); + rpc.addListener('group-chat-offline', _offline, false); rpc.addListener('group-chat-check', _check, false); rpc.addListener('group-chat-create', _create, false); rpc.addListener('group-chat-result', _result, false); @@ -149,4 +149,20 @@ class GroupChatProvider extends ChangeNotifier { }); notifyListeners(); } + + _online(List params) { + final id = params[0]; + if (this.groups.containsKey(id)) { + this.groups[id].online = true; + notifyListeners(); + } + } + + _offline(List params) { + final id = params[0]; + if (this.groups.containsKey(id)) { + this.groups[id].online = false; + notifyListeners(); + } + } } diff --git a/src/apps/chat/layer.rs b/src/apps/chat/layer.rs index a50b4d4..c4e3da4 100644 --- a/src/apps/chat/layer.rs +++ b/src/apps/chat/layer.rs @@ -99,9 +99,11 @@ pub(crate) async fn handle( .running_mut(&mgid)? .check_add_online(fgid, Online::Direct(addr), f.id)?; // 3. update remote addr. TODO - let db = session_db(&layer.base, &mgid)?; - Friend::addr_update(&db, f.id, &addr)?; - drop(db); + if f.addr != addr { + let db = session_db(&layer.base, &mgid)?; + let _ = Friend::addr_update(&db, f.id, &addr); + drop(db); + } // 4. online to UI. results.rpcs.push(rpc::friend_online(mgid, f.id, addr)); // 5. connected. diff --git a/src/apps/group_chat/layer.rs b/src/apps/group_chat/layer.rs index 31940c5..d2c5522 100644 --- a/src/apps/group_chat/layer.rs +++ b/src/apps/group_chat/layer.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; use std::sync::Arc; use tdn::{ smol::lock::RwLock, @@ -12,11 +13,11 @@ use group_chat_types::{GroupConnect, GroupResult, JoinProof}; use tdn_did::Proof; //use group_chat_types::{Event, GroupConnect, GroupEvent, GroupInfo, GroupResult, GroupType}; -use crate::layer::Layer; +use crate::layer::{Layer, Online}; use crate::storage::group_chat_db; use super::models::GroupChat; -use super::rpc; +use super::{add_layer, rpc}; pub(crate) async fn handle( layer: &Arc>, @@ -27,12 +28,12 @@ pub(crate) async fn handle( match msg { RecvType::Connect(_addr, _data) => { - // None. + // Never to here. } RecvType::Leave(_addr) => { // } - RecvType::Result(_addr, _is_ok, data) => { + RecvType::Result(addr, _is_ok, data) => { let res: GroupResult = postcard::from_bytes(&data) .map_err(|_e| new_io_error("Deseralize result failure"))?; match res { @@ -51,8 +52,48 @@ pub(crate) async fn handle( } } } - _ => { - // + GroupResult::Join(gcd, ok, height) => { + println!("Got join result: {}", ok); + if ok { + let base = layer.read().await.base.clone(); + if let Some(group) = load_group(&base, &mgid, &gcd)? { + let mut layer_lock = layer.write().await; + // 1. check address. + if group.g_addr != addr { + return Ok(results); + } + // 2. online this group. + layer_lock.running_mut(&mgid)?.check_add_online( + gcd, + Online::Direct(addr), + group.id, + )?; + // 3. online to UI. + results.rpcs.push(rpc::group_online(mgid, group.id)); + + // 5. sync group height. + let db = group_chat_db(&base, &mgid)?; + let my_height = GroupChat::get_height(&db, &group.id)?; + drop(db); + + if my_height < height { + // TOOD + } + } else { + let msg = SendType::Result(0, addr, false, false, vec![]); + add_layer(&mut results, mgid, msg); + return Ok(results); + } + } + } + GroupResult::Waiting(_gcd) => { + // TODO waiting + } + GroupResult::Agree(_gcd, _group_info, _height) => { + // TOOD + } + GroupResult::Reject(_gcd) => { + // TOOD } } } @@ -74,8 +115,14 @@ pub(crate) async fn handle( Ok(results) } -pub(crate) fn group_chat_conn(proof: Proof, addr: PeerAddr, gid: GroupId, height: u64) -> SendType { - let data = postcard::to_allocvec(&GroupConnect::Join(gid, JoinProof::Had(proof), height)) - .unwrap_or(vec![]); +#[inline] +fn load_group(base: &PathBuf, mgid: &GroupId, gcd: &GroupId) -> Result> { + let db = group_chat_db(base, mgid)?; + GroupChat::get(&db, gcd) +} + +pub(crate) fn group_chat_conn(proof: Proof, addr: PeerAddr, gid: GroupId) -> SendType { + let data = + postcard::to_allocvec(&GroupConnect::Join(gid, JoinProof::Had(proof))).unwrap_or(vec![]); SendType::Connect(0, addr, None, None, data) } diff --git a/src/apps/group_chat/models.rs b/src/apps/group_chat/models.rs index f75887f..4b7a794 100644 --- a/src/apps/group_chat/models.rs +++ b/src/apps/group_chat/models.rs @@ -233,7 +233,7 @@ impl GroupChat { Ok(None) } - pub fn get_height(&self, db: &DStorage) -> Result { + pub fn get_height(db: &DStorage, id: &i64) -> Result { // TODO Ok(0) } @@ -267,6 +267,15 @@ impl GroupChat { let sql = format!("UPDATE groups SET is_ok=1 WHERE id = {}", self.id); db.update(&sql) } + + pub fn addr_update(db: &DStorage, id: i64, addr: &PeerAddr) -> Result { + let sql = format!( + "UPDATE groups SET addr='{}' WHERE id = {}", + addr.to_hex(), + id, + ); + db.update(&sql) + } } /// Group Member Model. diff --git a/src/apps/group_chat/rpc.rs b/src/apps/group_chat/rpc.rs index 0343186..829085d 100644 --- a/src/apps/group_chat/rpc.rs +++ b/src/apps/group_chat/rpc.rs @@ -26,6 +26,16 @@ pub(crate) fn create_result(mgid: GroupId, gid: i64, ok: bool) -> RpcParam { rpc_response(0, "group-chat-result", json!([gid, ok]), mgid) } +#[inline] +pub(crate) fn group_online(mgid: GroupId, gid: i64) -> RpcParam { + rpc_response(0, "group-chat-online", json!([gid]), mgid) +} + +#[inline] +pub(crate) fn group_offline(mgid: GroupId, gid: i64) -> RpcParam { + rpc_response(0, "group-chat-offline", json!([gid]), mgid) +} + #[inline] fn group_list(groups: Vec) -> RpcParam { let mut results = vec![]; diff --git a/src/layer.rs b/src/layer.rs index 91607a0..dcc9d8b 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -139,9 +139,8 @@ impl Layer { let db = group_chat_db(&self.base, mgid)?; let groups = GroupChat::all_ok(&db)?; for g in groups { - let height = g.get_height(&db)? as u64; let proof = group_lock.prove_addr(mgid, &g.g_addr)?; - vecs.push((GROUP_ID, group_chat_conn(proof, g.g_addr, g.g_id, height))); + vecs.push((GROUP_ID, group_chat_conn(proof, g.g_addr, g.g_id))); } drop(db); diff --git a/src/rpc.rs b/src/rpc.rs index 3df9494..a3c9faf 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -374,13 +374,8 @@ fn new_rpc_handler( let db = group_chat_db(group_lock.base(), &gid)?; let groups = GroupChat::all_ok(&db)?; for g in groups { - let height = g.get_height(&db)? as u64; let proof = group_lock.prove_addr(&gid, &g.g_addr)?; - add_layer( - &mut results, - gid, - group_chat_conn(proof, g.g_addr, g.g_id, height), - ); + add_layer(&mut results, gid, group_chat_conn(proof, g.g_addr, g.g_id)); } drop(db); drop(group_lock);