mirror of https://github.com/CympleTech/ESSE.git
35 changed files with 967 additions and 586 deletions
@ -0,0 +1,122 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
|
||||||
|
import 'package:esse/l10n/localizations.dart'; |
||||||
|
import 'package:esse/utils/relative_time.dart'; |
||||||
|
import 'package:esse/widgets/avatar.dart'; |
||||||
|
import 'package:esse/global.dart'; |
||||||
|
import 'package:esse/apps/service/models.dart'; |
||||||
|
import 'package:esse/apps/primitives.dart'; |
||||||
|
|
||||||
|
enum SessionType { |
||||||
|
Chat, |
||||||
|
Group, |
||||||
|
Files, |
||||||
|
Device, |
||||||
|
Assistant, |
||||||
|
Domain, |
||||||
|
Service, |
||||||
|
} |
||||||
|
|
||||||
|
extension SessionTypeExtension on SessionType { |
||||||
|
static SessionType fromInt(int s) { |
||||||
|
switch (s) { |
||||||
|
case 0: |
||||||
|
return SessionType.Chat; |
||||||
|
case 1: |
||||||
|
return SessionType.Group; |
||||||
|
case 2: |
||||||
|
return SessionType.Files; |
||||||
|
case 3: |
||||||
|
return SessionType.Device; |
||||||
|
case 4: |
||||||
|
return SessionType.Assistant; |
||||||
|
case 5: |
||||||
|
return SessionType.Domain; |
||||||
|
case 6: |
||||||
|
return SessionType.Service; |
||||||
|
default: |
||||||
|
return SessionType.Chat; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Session { |
||||||
|
int id; |
||||||
|
int fid; |
||||||
|
String gid; |
||||||
|
String addr; |
||||||
|
SessionType type; |
||||||
|
String name; |
||||||
|
bool isTop; |
||||||
|
RelativeTime lastTime; |
||||||
|
String lastContent; |
||||||
|
bool lastReaded; |
||||||
|
bool online = false; |
||||||
|
|
||||||
|
static List innerService(InnerService service, AppLocalizations lang) { |
||||||
|
final params = service.params(lang); |
||||||
|
final avatar = Container( |
||||||
|
padding: const EdgeInsets.all(6.0), |
||||||
|
decoration: BoxDecoration( |
||||||
|
borderRadius: BorderRadius.circular(15.0), |
||||||
|
), |
||||||
|
child: Image.asset(params[2]), |
||||||
|
); |
||||||
|
final name = params[0]; |
||||||
|
final bio = params[1]; |
||||||
|
|
||||||
|
return [avatar, name, bio]; |
||||||
|
} |
||||||
|
|
||||||
|
List parse(AppLocalizations lang) { |
||||||
|
switch (this.type) { |
||||||
|
case SessionType.Chat: |
||||||
|
return [showAvatar(), this.name, this.lastContent, this.lastTime.toString()]; |
||||||
|
case SessionType.Assistant: |
||||||
|
final params = Session.innerService(InnerService.Assistant, lang); |
||||||
|
return [params[0], params[1], params[2], '']; |
||||||
|
case SessionType.Files: |
||||||
|
final params = Session.innerService(InnerService.Files, lang); |
||||||
|
return [params[0], params[1], params[2], '']; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Avatar showAvatar({double width = 45.0, bool needOnline = true}) { |
||||||
|
final avatar = Global.avatarPath + this.gid + '.png'; |
||||||
|
return Avatar( |
||||||
|
width: width, |
||||||
|
name: this.name, |
||||||
|
avatarPath: avatar, |
||||||
|
online: this.online, |
||||||
|
needOnline: needOnline, |
||||||
|
hasNew: !this.lastReaded, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
last(List params) { |
||||||
|
this.lastTime = RelativeTime.fromInt(params[1]); |
||||||
|
this.lastContent = params[2]; |
||||||
|
this.lastReaded = params[3]; |
||||||
|
} |
||||||
|
|
||||||
|
update(List params) { |
||||||
|
this.addr = params[1]; |
||||||
|
this.name = params[2]; |
||||||
|
this.isTop = params[3]; |
||||||
|
this.online = params[4]; |
||||||
|
} |
||||||
|
|
||||||
|
Session.fromList(List params) { |
||||||
|
this.id = params[0]; |
||||||
|
this.fid = params[1]; |
||||||
|
this.gid = params[2]; |
||||||
|
this.addr = params[3]; |
||||||
|
this.type = SessionTypeExtension.fromInt(params[4]); |
||||||
|
this.name = params[5]; |
||||||
|
this.isTop = params[6]; |
||||||
|
this.lastTime = RelativeTime.fromInt(params[7]); |
||||||
|
this.lastContent = params[8]; |
||||||
|
this.lastReaded = params[9]; |
||||||
|
this.online = params[10]; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
#[rustfmt::skip] |
||||||
|
pub(super) const CHAT_VERSIONS: [&str; 3] = [ |
||||||
|
"CREATE TABLE IF NOT EXISTS friends( |
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
||||||
|
gid TEXT NOT NULL, |
||||||
|
addr TEXT NOT NULL, |
||||||
|
name TEXT NOT NULL, |
||||||
|
remark TEXT, |
||||||
|
is_closed INTEGER NOT NULL, |
||||||
|
datetime INTEGER NOT NULL, |
||||||
|
is_deleted INTEGER NOT NULL);", |
||||||
|
"CREATE TABLE IF NOT EXISTS requests( |
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
||||||
|
gid TEXT NOT NULL, |
||||||
|
addr TEXT NOT NULL, |
||||||
|
name TEXT, |
||||||
|
remark TEXT, |
||||||
|
is_me INTEGER NOT NULL, |
||||||
|
is_ok INTEGER NOT NULL, |
||||||
|
is_over INTEGER NOT NULL, |
||||||
|
is_delivery INTEGER NOT NULL, |
||||||
|
datetime INTEGER NOT NULL, |
||||||
|
is_deleted INTEGER NOT NULL);", |
||||||
|
"CREATE TABLE IF NOT EXISTS messages( |
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
||||||
|
hash TEXT NOT NULL, |
||||||
|
fid INTEGER NOT NULL, |
||||||
|
is_me INTEGER NOT NULL, |
||||||
|
m_type INTEGER NOT NULL, |
||||||
|
content TEXT NOT NULL, |
||||||
|
is_delivery INTEGER NOT NULL, |
||||||
|
datetime INTEGER NOT NULL, |
||||||
|
is_deleted INTEGER NOT NULL);", |
||||||
|
]; |
@ -1,37 +1,16 @@ |
|||||||
#[rustfmt::skip] |
#[rustfmt::skip] |
||||||
pub(super) const SESSION_VERSIONS: [&str; 3] = [ |
pub(super) const SESSION_VERSIONS: [&str; 3] = [ |
||||||
"CREATE TABLE IF NOT EXISTS friends( |
"CREATE TABLE IF NOT EXISTS sessions( |
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
||||||
|
fid INTEGER NOT NULL, |
||||||
gid TEXT NOT NULL, |
gid TEXT NOT NULL, |
||||||
addr TEXT NOT NULL, |
addr TEXT NOT NULL, |
||||||
|
s_type INTEGER NOT NULL, |
||||||
name TEXT NOT NULL, |
name TEXT NOT NULL, |
||||||
remark TEXT, |
|
||||||
is_top INTEGER NOT NULL, |
is_top INTEGER NOT NULL, |
||||||
is_closed INTEGER NOT NULL, |
last_datetime INTEGER, |
||||||
last_message_datetime INTEGER, |
last_content TEXT, |
||||||
last_message_content TEXT, |
last_readed INTEGER);", |
||||||
last_message_readed INTEGER, |
"INSERT INTO sessions (fid, gid, addr, s_type, name, is_top, last_datetime, last_content, last_readed) VALUES (0, '', '', 4, '', 0, 0, '', 1);", // Assistant.
|
||||||
is_deleted INTEGER NOT NULL);", |
"INSERT INTO sessions (fid, gid, addr, s_type, name, is_top, last_datetime, last_content, last_readed) VALUES (0, '', '', 2, '', 0, 0, '', 1);", // File.
|
||||||
"CREATE TABLE IF NOT EXISTS requests( |
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|
||||||
gid TEXT NOT NULL, |
|
||||||
addr TEXT NOT NULL, |
|
||||||
name TEXT, |
|
||||||
remark TEXT, |
|
||||||
is_me INTEGER NOT NULL, |
|
||||||
is_ok INTEGER NOT NULL, |
|
||||||
is_over INTEGER NOT NULL, |
|
||||||
is_delivery INTEGER NOT NULL, |
|
||||||
datetime INTEGER NOT NULL, |
|
||||||
is_deleted INTEGER NOT NULL);", |
|
||||||
"CREATE TABLE IF NOT EXISTS messages( |
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, |
|
||||||
hash TEXT NOT NULL, |
|
||||||
fid INTEGER NOT NULL, |
|
||||||
is_me INTEGER NOT NULL, |
|
||||||
m_type INTEGER NOT NULL, |
|
||||||
content TEXT NOT NULL, |
|
||||||
is_delivery INTEGER NOT NULL, |
|
||||||
datetime INTEGER NOT NULL, |
|
||||||
is_deleted INTEGER NOT NULL);", |
|
||||||
]; |
]; |
||||||
|
@ -0,0 +1,171 @@ |
|||||||
|
use tdn::types::{ |
||||||
|
group::GroupId, |
||||||
|
primitive::{new_io_error, PeerAddr, Result}, |
||||||
|
rpc::{json, RpcParam}, |
||||||
|
}; |
||||||
|
use tdn_storage::local::{DStorage, DsValue}; |
||||||
|
|
||||||
|
pub(crate) enum SessionType { |
||||||
|
Chat, |
||||||
|
Group, |
||||||
|
Files, |
||||||
|
Device, |
||||||
|
Assistant, |
||||||
|
Domain, |
||||||
|
Service, |
||||||
|
} |
||||||
|
|
||||||
|
impl SessionType { |
||||||
|
fn to_int(&self) -> i64 { |
||||||
|
match self { |
||||||
|
SessionType::Chat => 0, |
||||||
|
SessionType::Group => 1, |
||||||
|
SessionType::Files => 2, |
||||||
|
SessionType::Device => 3, |
||||||
|
SessionType::Assistant => 4, |
||||||
|
SessionType::Domain => 5, |
||||||
|
SessionType::Service => 6, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn from_int(i: i64) -> Self { |
||||||
|
match i { |
||||||
|
0 => SessionType::Chat, |
||||||
|
1 => SessionType::Group, |
||||||
|
2 => SessionType::Files, |
||||||
|
3 => SessionType::Device, |
||||||
|
4 => SessionType::Assistant, |
||||||
|
5 => SessionType::Domain, |
||||||
|
6 => SessionType::Service, |
||||||
|
_ => SessionType::Chat, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub(crate) struct Session { |
||||||
|
id: i64, |
||||||
|
fid: i64, |
||||||
|
pub gid: GroupId, |
||||||
|
pub addr: PeerAddr, |
||||||
|
pub s_type: SessionType, |
||||||
|
name: String, |
||||||
|
is_top: bool, |
||||||
|
last_datetime: i64, |
||||||
|
last_content: String, |
||||||
|
last_readed: bool, |
||||||
|
pub online: bool, |
||||||
|
} |
||||||
|
|
||||||
|
impl Session { |
||||||
|
pub fn new( |
||||||
|
fid: i64, |
||||||
|
gid: GroupId, |
||||||
|
addr: PeerAddr, |
||||||
|
s_type: SessionType, |
||||||
|
name: String, |
||||||
|
datetime: i64, |
||||||
|
) -> Self { |
||||||
|
Self { |
||||||
|
fid, |
||||||
|
gid, |
||||||
|
addr, |
||||||
|
s_type, |
||||||
|
name, |
||||||
|
id: 0, |
||||||
|
is_top: false, |
||||||
|
last_datetime: datetime, |
||||||
|
last_content: "".to_owned(), |
||||||
|
last_readed: true, |
||||||
|
online: false, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_rpc(&self) -> RpcParam { |
||||||
|
json!([ |
||||||
|
self.id, |
||||||
|
self.fid, |
||||||
|
self.gid.to_hex(), |
||||||
|
self.addr.to_hex(), |
||||||
|
self.s_type.to_int(), |
||||||
|
self.name, |
||||||
|
self.is_top, |
||||||
|
self.last_datetime, |
||||||
|
self.last_content, |
||||||
|
self.last_readed, |
||||||
|
self.online |
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
fn from_values(mut v: Vec<DsValue>) -> Self { |
||||||
|
Self { |
||||||
|
last_readed: v.pop().unwrap().as_bool(), |
||||||
|
last_content: v.pop().unwrap().as_string(), |
||||||
|
last_datetime: v.pop().unwrap().as_i64(), |
||||||
|
is_top: v.pop().unwrap().as_bool(), |
||||||
|
name: v.pop().unwrap().as_string(), |
||||||
|
s_type: SessionType::from_int(v.pop().unwrap().as_i64()), |
||||||
|
addr: PeerAddr::from_hex(v.pop().unwrap().as_str()).unwrap_or(PeerAddr::default()), |
||||||
|
gid: GroupId::from_hex(v.pop().unwrap().as_str()).unwrap_or(GroupId::default()), |
||||||
|
fid: v.pop().unwrap().as_i64(), |
||||||
|
id: v.pop().unwrap().as_i64(), |
||||||
|
online: false, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn insert(&mut self, db: &DStorage) -> Result<()> { |
||||||
|
let sql = format!("INSERT INTO sessions (fid, gid, addr, s_type, name, is_top, last_datetime, last_content, last_readed) VALUES ({}, '{}', '{}', {}, '{}', {}, {}, '{}', {})", |
||||||
|
self.fid, |
||||||
|
self.gid.to_hex(), |
||||||
|
self.addr.to_hex(), |
||||||
|
self.s_type.to_int(), |
||||||
|
self.name, |
||||||
|
if self.is_top { 1 } else { 0 }, |
||||||
|
self.last_datetime, |
||||||
|
self.last_content, |
||||||
|
if self.last_readed { 1 } else { 0 }, |
||||||
|
); |
||||||
|
let id = db.insert(&sql)?; |
||||||
|
self.id = id; |
||||||
|
Ok(()) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get(db: &DStorage, id: i64) -> Result<Session> { |
||||||
|
let sql = format!("SELECT id, fid, gid, addr, s_type, name, is_top, last_datetime, last_content, last_readed FROM sessions WHERE id = {}", id); |
||||||
|
let mut matrix = db.query(&sql)?; |
||||||
|
if matrix.len() > 0 { |
||||||
|
Ok(Session::from_values(matrix.pop().unwrap())) // safe unwrap()
|
||||||
|
} else { |
||||||
|
Err(new_io_error("session missing.")) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn list(db: &DStorage) -> Result<Vec<Session>> { |
||||||
|
let matrix = db.query("SELECT id, fid, gid, addr, s_type, name, is_top, last_datetime, last_content, last_readed FROM sessions ORDER BY last_datetime DESC")?; |
||||||
|
let mut sessions = vec![]; |
||||||
|
for values in matrix { |
||||||
|
sessions.push(Session::from_values(values)); |
||||||
|
} |
||||||
|
Ok(sessions) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn top(db: &DStorage, id: &i64, is_top: bool) -> Result<usize> { |
||||||
|
db.update(&format!("UPDATE sessions SET is_top = 1 WHERE id = {}", id)) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn last( |
||||||
|
db: &DStorage, |
||||||
|
id: &i64, |
||||||
|
datetime: &i64, |
||||||
|
content: &str, |
||||||
|
readed: bool, |
||||||
|
) -> Result<usize> { |
||||||
|
db.update(&format!("UPDATE sessions SET last_datetime = {}, last_content = '{}', last_readed = {} WHERE id = {}", datetime, content, if readed { 1 } else { 0 }, id)) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn read(db: &DStorage, id: &i64) -> Result<usize> { |
||||||
|
db.update(&format!( |
||||||
|
"UPDATE sessions SET last_readed = 1 WHERE id = {}", |
||||||
|
id |
||||||
|
)) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue