From c88e742d5a06f40b5b39cdc7a9c6f1529a7d4d0f Mon Sep 17 00:00:00 2001 From: Sun Date: Sun, 6 Jun 2021 22:19:41 +0800 Subject: [PATCH] group chat close & delete --- lib/apps/group_chat/detail.dart | 27 ++++++++-------- lib/apps/group_chat/provider.dart | 37 ++++++++-------------- lib/l10n/localizations.dart | 1 + lib/l10n/localizations_en.dart | 2 ++ lib/l10n/localizations_zh.dart | 2 ++ lib/pages/home.dart | 7 ++++- lib/provider.dart | 11 +++++++ lib/session.dart | 4 +++ src/apps/group_chat/models.rs | 24 ++++++++++++++ src/apps/group_chat/rpc.rs | 52 +++++++++++++++++++++++++++++-- src/rpc.rs | 10 ++++++ src/session.rs | 35 ++++++++++++++++++++- 12 files changed, 171 insertions(+), 41 deletions(-) diff --git a/lib/apps/group_chat/detail.dart b/lib/apps/group_chat/detail.dart index 492d0d4..e4059b6 100644 --- a/lib/apps/group_chat/detail.dart +++ b/lib/apps/group_chat/detail.dart @@ -194,7 +194,7 @@ class _GroupChatDetailState extends State { if (!isDesktop) GestureDetector( onTap: () { - context.read().clearActivedGroup(); + provider.clearActivedGroup(); Navigator.pop(context); }, child: Container( @@ -202,7 +202,7 @@ class _GroupChatDetailState extends State { child: Icon(Icons.arrow_back, color: color.primary)), ), - SizedBox(width: 15.0), + const SizedBox(width: 15.0), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -211,9 +211,9 @@ class _GroupChatDetailState extends State { this.group.name, style: TextStyle(fontWeight: FontWeight.bold), ), - SizedBox(height: 6.0), + const SizedBox(height: 6.0), Text(this.group.isClosed - ? lang.unfriended + ? lang.closed : session.onlineLang(lang), style: TextStyle( color: color.onPrimary.withOpacity(0.5), @@ -221,7 +221,7 @@ class _GroupChatDetailState extends State { ], ), ), - SizedBox(width: 20.0), + const SizedBox(width: 20.0), GestureDetector( onTap: () {}, child: Container( @@ -229,7 +229,7 @@ class _GroupChatDetailState extends State { child: Icon(Icons.phone_rounded, color: Color(0x26ADB0BB))), ), - SizedBox(width: 20.0), + const SizedBox(width: 20.0), GestureDetector( onTap: () {}, child: Container( @@ -237,7 +237,7 @@ class _GroupChatDetailState extends State { child: Icon(Icons.videocam_rounded, color: Color(0x26ADB0BB))), ), - SizedBox(width: 20.0), + const SizedBox(width: 20.0), GestureDetector( onTap: () { GroupChatDetail._scaffoldKey.currentState.openEndDrawer(); @@ -246,7 +246,7 @@ class _GroupChatDetailState extends State { width: 20.0, child: Icon(Icons.group_rounded, color: color.primary)), ), - SizedBox(width: 20.0), + const SizedBox(width: 20.0), PopupMenuButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15) @@ -304,22 +304,23 @@ class _GroupChatDetailState extends State { onPressed: () { Navigator.pop(context); provider.delete(this.group.id); + context.read().clearActivedSession( + SessionType.Group + ); }, ), ] ); }, ); - } else if (value == 4) { - provider.reAdd(this.group.id); } }, itemBuilder: (context) { return >[ _menuItem(Color(0xFF6174FF), 1, Icons.qr_code_rounded, lang.info), - this.group.isClosed - ? _menuItem(Color(0xFF6174FF), 4, Icons.send_rounded, lang.add) - : _menuItem(Colors.orange, 2, Icons.block_rounded, lang.exit), + if (!this.group.isClosed && isOnline) + _menuItem(Colors.orange, 2, Icons.block_rounded, lang.exit), + if (isOnline) _menuItem(Colors.red, 3, Icons.delete_rounded, lang.delete), ]; }, diff --git a/lib/apps/group_chat/provider.dart b/lib/apps/group_chat/provider.dart index c0668b8..4254dbe 100644 --- a/lib/apps/group_chat/provider.dart +++ b/lib/apps/group_chat/provider.dart @@ -18,7 +18,6 @@ class GroupChatProvider extends ChangeNotifier { SplayTreeMap requests = SplayTreeMap(); int actived; - bool activedOnline; SplayTreeMap activedMessages = SplayTreeMap(); SplayTreeMap activedMembers = SplayTreeMap(); @@ -72,8 +71,6 @@ 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', _offline, false); rpc.addListener('group-chat-check', _check, false); rpc.addListener('group-chat-create', _create, false); rpc.addListener('group-chat-result', _result, false); @@ -144,20 +141,26 @@ class GroupChatProvider extends ChangeNotifier { } messageCreate(MessageType mtype, String content) { - final gid = this.activedGroup.gid; - rpc.send('group-chat-message-create', [gid, mtype.toInt(), content]); + final gcd = this.activedGroup.gid; + rpc.send('group-chat-message-create', [gcd, mtype.toInt(), content]); } close(int id) { - // rpc.send('group-chat-close', [id]); + final gcd = this.activedGroup.gid; + rpc.send('group-chat-close', [gcd, id]); + + this.activedGroup.isClosed = true; + notifyListeners(); } delete(int id) { - // rpc.send('group-chat-delete', [id]); - } + final gcd = this.activedGroup.gid; + rpc.send('group-chat-delete', [gcd, id]); - reAdd(int id) { - // rpc.send('group-chat-readd', [id]); + this.actived = 0; + this.groups.remove(id); + this.activedMessages.clear(); + this.activedMembers.clear(); } memberUpdate(int id, bool isBlock) { @@ -178,20 +181,6 @@ class GroupChatProvider extends ChangeNotifier { notifyListeners(); } - _online(List params) { - if (this.actived == params[0]) { - this.activedOnline = true; - notifyListeners(); - } - } - - _offline(List params) { - if (this.actived == params[0]) { - this.activedOnline = false; - notifyListeners(); - } - } - _check(List params) { this.createSupported.clear(); if (this.createCheckType == CheckType.Wait) { diff --git a/lib/l10n/localizations.dart b/lib/l10n/localizations.dart index 3ccba48..fcc6f19 100644 --- a/lib/l10n/localizations.dart +++ b/lib/l10n/localizations.dart @@ -91,6 +91,7 @@ abstract class AppLocalizations { String get emoji; String get record; String get others; + String get closed; // theme String get themeDark; diff --git a/lib/l10n/localizations_en.dart b/lib/l10n/localizations_en.dart index cabd5c8..c61f8f9 100644 --- a/lib/l10n/localizations_en.dart +++ b/lib/l10n/localizations_en.dart @@ -106,6 +106,8 @@ class AppLocalizationsEn extends AppLocalizations { String get record => 'Record'; @override String get others => 'Others'; + @override + String get closed => 'Closed'; // theme @override diff --git a/lib/l10n/localizations_zh.dart b/lib/l10n/localizations_zh.dart index db92bf3..0e159aa 100644 --- a/lib/l10n/localizations_zh.dart +++ b/lib/l10n/localizations_zh.dart @@ -106,6 +106,8 @@ class AppLocalizationsZh extends AppLocalizations { String get record => '语音'; @override String get others => '其他'; + @override + String get closed => '已关闭'; // theme @override diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 468a0ab..972ccd6 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -572,7 +572,12 @@ class _SessionWidget extends StatelessWidget { ] ), ), - Container(width: 8.0, height: 8.0, + session.isClose + ? Container( + margin: const EdgeInsets.only(left: 15.0, right: 20.0), + child: Icon(Icons.block_rounded, color: Color(0xFFADB0BB), size: 14.0) + ) + : Container(width: 8.0, height: 8.0, margin: const EdgeInsets.only(left: 15.0, right: 20.0), decoration: BoxDecoration( color: session.lastReaded ? color.background : Colors.red, diff --git a/lib/provider.dart b/lib/provider.dart index 2f30ec5..534b290 100644 --- a/lib/provider.dart +++ b/lib/provider.dart @@ -58,6 +58,7 @@ class AccountProvider extends ChangeNotifier { rpc.addListener('session-create', _sessionCreate, true); rpc.addListener('session-update', _sessionUpdate, false); rpc.addListener('session-close', _sessionClose, false); + rpc.addListener('session-delete', _sessionDelete, false); rpc.addListener('session-connect', _sessionConnect, false); rpc.addListener('session-suspend', _sessionSuspend, false); rpc.addListener('session-lost', _sessionLost, false); @@ -334,8 +335,18 @@ class AccountProvider extends ChangeNotifier { _sessionClose(List params) { final id = params[0]; this.sessions[id].isClose = true; + notifyListeners(); + } + + _sessionDelete(List params) { + final id = params[0]; + this.sessions.remove(id); this.orderKeys.remove(id); this.topKeys.remove(id); + if (id == this.actived) { + this.actived = 0; + this.coreShowWidget = DefaultCoreShow(); + } notifyListeners(); } diff --git a/lib/session.dart b/lib/session.dart index 871d5a4..8360e3e 100644 --- a/lib/session.dart +++ b/lib/session.dart @@ -153,6 +153,10 @@ class Session { break; } + if (this.isClose) { + color = Color(0xFFADB0BB); + } + return Avatar( width: width, name: this.name, diff --git a/src/apps/group_chat/models.rs b/src/apps/group_chat/models.rs index 9567cb1..dc1952e 100644 --- a/src/apps/group_chat/models.rs +++ b/src/apps/group_chat/models.rs @@ -338,6 +338,30 @@ impl GroupChat { let sql = format!("UPDATE groups SET height={} WHERE id = {}", height, id,); db.update(&sql) } + + pub fn close(db: &DStorage, id: &i64) -> Result { + let sql = format!("UPDATE groups SET is_closed = 1 WHERE id = {}", id); + db.update(&sql) + } + + /// return if is closed + pub fn delete(db: &DStorage, id: &i64) -> Result { + let sql = format!("SELECT is_closed FROM groups WHERE id = {}", id); + let mut matrix = db.query(&sql)?; + let is_closed = if let Some(mut value) = matrix.pop() { + value.pop().unwrap().as_bool() // safe unwrap + } else { + false + }; + + let sql = format!( + "UPDATE groups SET is_closed = 1, is_deleted = 1 WHERE id = {}", + id + ); + db.update(&sql)?; + + Ok(is_closed) + } } /// Group Join Request model. include my requests and other requests. diff --git a/src/apps/group_chat/rpc.rs b/src/apps/group_chat/rpc.rs index 7d6d257..858bf7f 100644 --- a/src/apps/group_chat/rpc.rs +++ b/src/apps/group_chat/rpc.rs @@ -10,8 +10,9 @@ use tdn_did::Proof; use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent}; use crate::apps::chat::{Friend, MessageType}; -use crate::rpc::RpcState; -use crate::storage::{chat_db, group_chat_db}; +use crate::rpc::{session_close, session_delete, RpcState}; +use crate::session::{Session, SessionType}; +use crate::storage::{chat_db, group_chat_db, session_db}; use super::add_layer; use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request}; @@ -403,4 +404,51 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler) { Ok(results) }, ); + + handler.add_method( + "group-chat-close", + |gid: GroupId, params: Vec, state: Arc| async move { + let gcd = GroupId::from_hex(params[0].as_str()?)?; + let id = params[1].as_i64()?; + + let addr = state.layer.write().await.remove_online(&gid, &gcd)?; + + let mut results = HandleResult::new(); + let base = state.layer.read().await.base().clone(); + let sid = Session::close(&session_db(&base, &gid)?, &id, &SessionType::Group)?; + results.rpcs.push(session_close(gid, &sid)); + + let db = group_chat_db(&base, &gid)?; + GroupChat::close(&db, &id)?; + + let event = Event::MemberLeave(gid); + let data = postcard::to_allocvec(&LayerEvent::Sync(gcd, 0, event)).unwrap_or(vec![]); + let msg = SendType::Event(0, addr, data); + add_layer(&mut results, gid, msg); + Ok(results) + }, + ); + + handler.add_method( + "group-chat-delete", + |gid: GroupId, params: Vec, state: Arc| async move { + let gcd = GroupId::from_hex(params[0].as_str()?)?; + let id = params[1].as_i64()?; + + let mut results = HandleResult::new(); + let base = state.layer.read().await.base().clone(); + let sid = Session::delete(&session_db(&base, &gid)?, &id, &SessionType::Group)?; + results.rpcs.push(session_delete(gid, &sid)); + let db = group_chat_db(&base, &gid)?; + if GroupChat::delete(&db, &id)? { + let addr = state.layer.write().await.remove_online(&gid, &gcd)?; + let event = Event::MemberLeave(gid); + let data = + postcard::to_allocvec(&LayerEvent::Sync(gcd, 0, event)).unwrap_or(vec![]); + let msg = SendType::Event(0, addr, data); + add_layer(&mut results, gid, msg); + } + Ok(results) + }, + ); } diff --git a/src/rpc.rs b/src/rpc.rs index ef60412..e53e590 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -115,6 +115,16 @@ pub(crate) fn session_lost(mgid: GroupId, id: &i64) -> RpcParam { rpc_response(0, "session-lost", json!([id]), mgid) } +#[inline] +pub(crate) fn session_delete(mgid: GroupId, id: &i64) -> RpcParam { + rpc_response(0, "session-delete", json!([id]), mgid) +} + +#[inline] +pub(crate) fn session_close(mgid: GroupId, id: &i64) -> RpcParam { + rpc_response(0, "session-close", json!([id]), mgid) +} + #[inline] fn session_list(sessions: Vec) -> RpcParam { let mut results = vec![]; diff --git a/src/session.rs b/src/session.rs index 7778cdf..c899b61 100644 --- a/src/session.rs +++ b/src/session.rs @@ -19,7 +19,7 @@ pub(crate) enum SessionType { } impl SessionType { - fn to_int(&self) -> i64 { + pub fn to_int(&self) -> i64 { match self { SessionType::Chat => 0, SessionType::Group => 1, @@ -159,6 +159,39 @@ impl Session { )) } + pub fn delete(db: &DStorage, fid: &i64, s_type: &SessionType) -> Result { + let sql = format!( + "SELECT id from sessions WHERE fid = {} AND s_type = {}", + fid, + s_type.to_int() + ); + let mut matrix = db.query(&sql)?; + if let Some(mut values) = matrix.pop() { + let id = values.pop().unwrap().as_i64(); // safe unwrap. + db.delete(&format!("DELETE FROM sessions WHERE id = {}", id))?; + Ok(id) + } else { + Err(new_io_error("session missing")) + } + } + + pub fn close(db: &DStorage, fid: &i64, s_type: &SessionType) -> Result { + let sql = format!( + "SELECT id from sessions WHERE fid = {} AND s_type = {}", + fid, + s_type.to_int() + ); + let mut matrix = db.query(&sql)?; + if let Some(mut values) = matrix.pop() { + let id = values.pop().unwrap().as_i64(); // safe unwrap. + let s = format!("UPDATE sessions SET is_close = 1 WHERE id = {}", id); + db.update(&s)?; + Ok(id) + } else { + Err(new_io_error("session missing")) + } + } + pub fn last( db: &DStorage, fid: &i64,