Browse Source

group chat close & delete

pull/18/head
Sun 4 years ago
parent
commit
c88e742d5a
  1. 27
      lib/apps/group_chat/detail.dart
  2. 37
      lib/apps/group_chat/provider.dart
  3. 1
      lib/l10n/localizations.dart
  4. 2
      lib/l10n/localizations_en.dart
  5. 2
      lib/l10n/localizations_zh.dart
  6. 7
      lib/pages/home.dart
  7. 11
      lib/provider.dart
  8. 4
      lib/session.dart
  9. 24
      src/apps/group_chat/models.rs
  10. 52
      src/apps/group_chat/rpc.rs
  11. 10
      src/rpc.rs
  12. 35
      src/session.rs

27
lib/apps/group_chat/detail.dart

@ -194,7 +194,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
if (!isDesktop) if (!isDesktop)
GestureDetector( GestureDetector(
onTap: () { onTap: () {
context.read<GroupChatProvider>().clearActivedGroup(); provider.clearActivedGroup();
Navigator.pop(context); Navigator.pop(context);
}, },
child: Container( child: Container(
@ -202,7 +202,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
child: child:
Icon(Icons.arrow_back, color: color.primary)), Icon(Icons.arrow_back, color: color.primary)),
), ),
SizedBox(width: 15.0), const SizedBox(width: 15.0),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -211,9 +211,9 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
this.group.name, this.group.name,
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
SizedBox(height: 6.0), const SizedBox(height: 6.0),
Text(this.group.isClosed Text(this.group.isClosed
? lang.unfriended ? lang.closed
: session.onlineLang(lang), : session.onlineLang(lang),
style: TextStyle( style: TextStyle(
color: color.onPrimary.withOpacity(0.5), color: color.onPrimary.withOpacity(0.5),
@ -221,7 +221,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
], ],
), ),
), ),
SizedBox(width: 20.0), const SizedBox(width: 20.0),
GestureDetector( GestureDetector(
onTap: () {}, onTap: () {},
child: Container( child: Container(
@ -229,7 +229,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
child: Icon(Icons.phone_rounded, child: Icon(Icons.phone_rounded,
color: Color(0x26ADB0BB))), color: Color(0x26ADB0BB))),
), ),
SizedBox(width: 20.0), const SizedBox(width: 20.0),
GestureDetector( GestureDetector(
onTap: () {}, onTap: () {},
child: Container( child: Container(
@ -237,7 +237,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
child: Icon(Icons.videocam_rounded, child: Icon(Icons.videocam_rounded,
color: Color(0x26ADB0BB))), color: Color(0x26ADB0BB))),
), ),
SizedBox(width: 20.0), const SizedBox(width: 20.0),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
GroupChatDetail._scaffoldKey.currentState.openEndDrawer(); GroupChatDetail._scaffoldKey.currentState.openEndDrawer();
@ -246,7 +246,7 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
width: 20.0, width: 20.0,
child: Icon(Icons.group_rounded, color: color.primary)), child: Icon(Icons.group_rounded, color: color.primary)),
), ),
SizedBox(width: 20.0), const SizedBox(width: 20.0),
PopupMenuButton<int>( PopupMenuButton<int>(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15) borderRadius: BorderRadius.circular(15)
@ -304,22 +304,23 @@ class _GroupChatDetailState extends State<GroupChatDetail> {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
provider.delete(this.group.id); provider.delete(this.group.id);
context.read<AccountProvider>().clearActivedSession(
SessionType.Group
);
}, },
), ),
] ]
); );
}, },
); );
} else if (value == 4) {
provider.reAdd(this.group.id);
} }
}, },
itemBuilder: (context) { itemBuilder: (context) {
return <PopupMenuEntry<int>>[ return <PopupMenuEntry<int>>[
_menuItem(Color(0xFF6174FF), 1, Icons.qr_code_rounded, lang.info), _menuItem(Color(0xFF6174FF), 1, Icons.qr_code_rounded, lang.info),
this.group.isClosed if (!this.group.isClosed && isOnline)
? _menuItem(Color(0xFF6174FF), 4, Icons.send_rounded, lang.add) _menuItem(Colors.orange, 2, Icons.block_rounded, lang.exit),
: _menuItem(Colors.orange, 2, Icons.block_rounded, lang.exit), if (isOnline)
_menuItem(Colors.red, 3, Icons.delete_rounded, lang.delete), _menuItem(Colors.red, 3, Icons.delete_rounded, lang.delete),
]; ];
}, },

37
lib/apps/group_chat/provider.dart

@ -18,7 +18,6 @@ class GroupChatProvider extends ChangeNotifier {
SplayTreeMap<int, Request> requests = SplayTreeMap(); SplayTreeMap<int, Request> requests = SplayTreeMap();
int actived; int actived;
bool activedOnline;
SplayTreeMap<int, Message> activedMessages = SplayTreeMap(); SplayTreeMap<int, Message> activedMessages = SplayTreeMap();
SplayTreeMap<int, Member> activedMembers = SplayTreeMap(); SplayTreeMap<int, Member> activedMembers = SplayTreeMap();
@ -72,8 +71,6 @@ class GroupChatProvider extends ChangeNotifier {
GroupChatProvider() { GroupChatProvider() {
// rpc. // rpc.
rpc.addListener('group-chat-list', _list, false); 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-check', _check, false);
rpc.addListener('group-chat-create', _create, false); rpc.addListener('group-chat-create', _create, false);
rpc.addListener('group-chat-result', _result, false); rpc.addListener('group-chat-result', _result, false);
@ -144,20 +141,26 @@ class GroupChatProvider extends ChangeNotifier {
} }
messageCreate(MessageType mtype, String content) { messageCreate(MessageType mtype, String content) {
final gid = this.activedGroup.gid; final gcd = this.activedGroup.gid;
rpc.send('group-chat-message-create', [gid, mtype.toInt(), content]); rpc.send('group-chat-message-create', [gcd, mtype.toInt(), content]);
} }
close(int id) { 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) { delete(int id) {
// rpc.send('group-chat-delete', [id]); final gcd = this.activedGroup.gid;
} rpc.send('group-chat-delete', [gcd, id]);
reAdd(int id) { this.actived = 0;
// rpc.send('group-chat-readd', [id]); this.groups.remove(id);
this.activedMessages.clear();
this.activedMembers.clear();
} }
memberUpdate(int id, bool isBlock) { memberUpdate(int id, bool isBlock) {
@ -178,20 +181,6 @@ class GroupChatProvider extends ChangeNotifier {
notifyListeners(); 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) { _check(List params) {
this.createSupported.clear(); this.createSupported.clear();
if (this.createCheckType == CheckType.Wait) { if (this.createCheckType == CheckType.Wait) {

1
lib/l10n/localizations.dart

@ -91,6 +91,7 @@ abstract class AppLocalizations {
String get emoji; String get emoji;
String get record; String get record;
String get others; String get others;
String get closed;
// theme // theme
String get themeDark; String get themeDark;

2
lib/l10n/localizations_en.dart

@ -106,6 +106,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get record => 'Record'; String get record => 'Record';
@override @override
String get others => 'Others'; String get others => 'Others';
@override
String get closed => 'Closed';
// theme // theme
@override @override

2
lib/l10n/localizations_zh.dart

@ -106,6 +106,8 @@ class AppLocalizationsZh extends AppLocalizations {
String get record => '语音'; String get record => '语音';
@override @override
String get others => '其他'; String get others => '其他';
@override
String get closed => '已关闭';
// theme // theme
@override @override

7
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), margin: const EdgeInsets.only(left: 15.0, right: 20.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: session.lastReaded ? color.background : Colors.red, color: session.lastReaded ? color.background : Colors.red,

11
lib/provider.dart

@ -58,6 +58,7 @@ class AccountProvider extends ChangeNotifier {
rpc.addListener('session-create', _sessionCreate, true); rpc.addListener('session-create', _sessionCreate, true);
rpc.addListener('session-update', _sessionUpdate, false); rpc.addListener('session-update', _sessionUpdate, false);
rpc.addListener('session-close', _sessionClose, false); rpc.addListener('session-close', _sessionClose, false);
rpc.addListener('session-delete', _sessionDelete, false);
rpc.addListener('session-connect', _sessionConnect, false); rpc.addListener('session-connect', _sessionConnect, false);
rpc.addListener('session-suspend', _sessionSuspend, false); rpc.addListener('session-suspend', _sessionSuspend, false);
rpc.addListener('session-lost', _sessionLost, false); rpc.addListener('session-lost', _sessionLost, false);
@ -334,8 +335,18 @@ class AccountProvider extends ChangeNotifier {
_sessionClose(List params) { _sessionClose(List params) {
final id = params[0]; final id = params[0];
this.sessions[id].isClose = true; this.sessions[id].isClose = true;
notifyListeners();
}
_sessionDelete(List params) {
final id = params[0];
this.sessions.remove(id);
this.orderKeys.remove(id); this.orderKeys.remove(id);
this.topKeys.remove(id); this.topKeys.remove(id);
if (id == this.actived) {
this.actived = 0;
this.coreShowWidget = DefaultCoreShow();
}
notifyListeners(); notifyListeners();
} }

4
lib/session.dart

@ -153,6 +153,10 @@ class Session {
break; break;
} }
if (this.isClose) {
color = Color(0xFFADB0BB);
}
return Avatar( return Avatar(
width: width, width: width,
name: this.name, name: this.name,

24
src/apps/group_chat/models.rs

@ -338,6 +338,30 @@ impl GroupChat {
let sql = format!("UPDATE groups SET height={} WHERE id = {}", height, id,); let sql = format!("UPDATE groups SET height={} WHERE id = {}", height, id,);
db.update(&sql) db.update(&sql)
} }
pub fn close(db: &DStorage, id: &i64) -> Result<usize> {
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<bool> {
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. /// Group Join Request model. include my requests and other requests.

52
src/apps/group_chat/rpc.rs

@ -10,8 +10,9 @@ use tdn_did::Proof;
use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent}; use group_chat_types::{CheckType, Event, GroupType, JoinProof, LayerEvent};
use crate::apps::chat::{Friend, MessageType}; use crate::apps::chat::{Friend, MessageType};
use crate::rpc::RpcState; use crate::rpc::{session_close, session_delete, RpcState};
use crate::storage::{chat_db, group_chat_db}; use crate::session::{Session, SessionType};
use crate::storage::{chat_db, group_chat_db, session_db};
use super::add_layer; use super::add_layer;
use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request}; use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request};
@ -403,4 +404,51 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
Ok(results) Ok(results)
}, },
); );
handler.add_method(
"group-chat-close",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| 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<RpcParam>, state: Arc<RpcState>| 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)
},
);
} }

10
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) 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] #[inline]
fn session_list(sessions: Vec<Session>) -> RpcParam { fn session_list(sessions: Vec<Session>) -> RpcParam {
let mut results = vec![]; let mut results = vec![];

35
src/session.rs

@ -19,7 +19,7 @@ pub(crate) enum SessionType {
} }
impl SessionType { impl SessionType {
fn to_int(&self) -> i64 { pub fn to_int(&self) -> i64 {
match self { match self {
SessionType::Chat => 0, SessionType::Chat => 0,
SessionType::Group => 1, SessionType::Group => 1,
@ -159,6 +159,39 @@ impl Session {
)) ))
} }
pub fn delete(db: &DStorage, fid: &i64, s_type: &SessionType) -> Result<i64> {
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<i64> {
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( pub fn last(
db: &DStorage, db: &DStorage,
fid: &i64, fid: &i64,

Loading…
Cancel
Save