mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Reduce number of Tokio workers (#129)
This commit is contained in:
parent
8d4539831f
commit
61aba80be1
7 changed files with 232 additions and 258 deletions
14
src/base.rs
14
src/base.rs
|
@ -21,7 +21,7 @@ use url::Url;
|
|||
|
||||
use matrix_sdk::{
|
||||
encryption::verification::SasVerification,
|
||||
room::Joined,
|
||||
room::{Joined, Room as MatrixRoom},
|
||||
ruma::{
|
||||
events::{
|
||||
reaction::ReactionEvent,
|
||||
|
@ -644,6 +644,13 @@ fn emoji_map() -> CompletionMap<String, &'static Emoji> {
|
|||
return emojis;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SyncInfo {
|
||||
pub spaces: Vec<MatrixRoom>,
|
||||
pub rooms: Vec<Arc<(MatrixRoom, Option<Tags>)>>,
|
||||
pub dms: Vec<Arc<(MatrixRoom, Option<Tags>)>>,
|
||||
}
|
||||
|
||||
pub struct ChatStore {
|
||||
pub cmds: ProgramCommands,
|
||||
pub worker: Requester,
|
||||
|
@ -654,6 +661,7 @@ pub struct ChatStore {
|
|||
pub settings: ApplicationSettings,
|
||||
pub need_load: HashSet<OwnedRoomId>,
|
||||
pub emojis: CompletionMap<String, &'static Emoji>,
|
||||
pub sync_info: SyncInfo,
|
||||
}
|
||||
|
||||
impl ChatStore {
|
||||
|
@ -663,12 +671,14 @@ impl ChatStore {
|
|||
settings,
|
||||
|
||||
cmds: crate::commands::setup_commands(),
|
||||
emojis: emoji_map(),
|
||||
|
||||
names: Default::default(),
|
||||
rooms: Default::default(),
|
||||
presences: Default::default(),
|
||||
verifications: Default::default(),
|
||||
need_load: Default::default(),
|
||||
emojis: emoji_map(),
|
||||
sync_info: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -712,6 +712,7 @@ fn main() -> IambResult<()> {
|
|||
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.worker_threads(2)
|
||||
.thread_name_fn(|| {
|
||||
static ATOMIC_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
let id = ATOMIC_ID.fetch_add(1, Ordering::SeqCst);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::cmp::{Ord, Ordering, PartialOrd};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use matrix_sdk::{
|
||||
|
@ -10,7 +12,6 @@ use matrix_sdk::{
|
|||
OwnedRoomId,
|
||||
RoomId,
|
||||
},
|
||||
DisplayName,
|
||||
};
|
||||
|
||||
use modalkit::tui::{
|
||||
|
@ -78,6 +79,8 @@ use self::{room::RoomState, welcome::WelcomeState};
|
|||
pub mod room;
|
||||
pub mod welcome;
|
||||
|
||||
type MatrixRoomInfo = Arc<(MatrixRoom, Option<Tags>)>;
|
||||
|
||||
const MEMBER_FETCH_DEBOUNCE: Duration = Duration::from_secs(5);
|
||||
|
||||
#[inline]
|
||||
|
@ -380,10 +383,13 @@ impl WindowOps<IambInfo> for IambWindow {
|
|||
match self {
|
||||
IambWindow::Room(state) => state.draw(area, buf, focused, store),
|
||||
IambWindow::DirectList(state) => {
|
||||
let dms = store.application.worker.direct_messages();
|
||||
let mut items = dms
|
||||
let mut items = store
|
||||
.application
|
||||
.sync_info
|
||||
.dms
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(id, name, tags)| DirectItem::new(id, name, tags, store))
|
||||
.map(|room_info| DirectItem::new(room_info, store))
|
||||
.collect::<Vec<_>>();
|
||||
items.sort();
|
||||
|
||||
|
@ -416,10 +422,13 @@ impl WindowOps<IambInfo> for IambWindow {
|
|||
.render(area, buf, state);
|
||||
},
|
||||
IambWindow::RoomList(state) => {
|
||||
let joined = store.application.worker.active_rooms();
|
||||
let mut items = joined
|
||||
let mut items = store
|
||||
.application
|
||||
.sync_info
|
||||
.rooms
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(room, name, tags)| RoomItem::new(room, name, tags, store))
|
||||
.map(|room_info| RoomItem::new(room_info, store))
|
||||
.collect::<Vec<_>>();
|
||||
items.sort();
|
||||
|
||||
|
@ -432,9 +441,13 @@ impl WindowOps<IambInfo> for IambWindow {
|
|||
.render(area, buf, state);
|
||||
},
|
||||
IambWindow::SpaceList(state) => {
|
||||
let spaces = store.application.worker.spaces();
|
||||
let items =
|
||||
spaces.into_iter().map(|(room, name)| SpaceItem::new(room, name, store));
|
||||
let items = store
|
||||
.application
|
||||
.sync_info
|
||||
.spaces
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|room| SpaceItem::new(room, store));
|
||||
state.set(items.collect());
|
||||
state.draw(area, buf, focused, store);
|
||||
|
||||
|
@ -639,36 +652,45 @@ impl Window<IambInfo> for IambWindow {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct RoomItem {
|
||||
room: MatrixRoom,
|
||||
tags: Option<Tags>,
|
||||
room_info: MatrixRoomInfo,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl RoomItem {
|
||||
fn new(
|
||||
room: MatrixRoom,
|
||||
name: DisplayName,
|
||||
tags: Option<Tags>,
|
||||
store: &mut ProgramStore,
|
||||
) -> Self {
|
||||
let name = name.to_string();
|
||||
fn new(room_info: MatrixRoomInfo, store: &mut ProgramStore) -> Self {
|
||||
let room = &room_info.deref().0;
|
||||
let room_id = room.room_id();
|
||||
|
||||
let info = store.application.get_room_info(room_id.to_owned());
|
||||
info.name = name.clone().into();
|
||||
info.tags = tags.clone();
|
||||
let name = info.name.clone().unwrap_or_default();
|
||||
info.tags = room_info.deref().1.clone();
|
||||
|
||||
if let Some(alias) = room.canonical_alias() {
|
||||
store.application.names.insert(alias.to_string(), room_id.to_owned());
|
||||
}
|
||||
|
||||
RoomItem { room, tags, name }
|
||||
RoomItem { room_info, name }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn room(&self) -> &MatrixRoom {
|
||||
&self.room_info.deref().0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn room_id(&self) -> &RoomId {
|
||||
self.room().room_id()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn tags(&self) -> &Option<Tags> {
|
||||
&self.room_info.deref().1
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for RoomItem {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.room.room_id() == other.room.room_id()
|
||||
self.room_id() == other.room_id()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,7 +698,7 @@ impl Eq for RoomItem {}
|
|||
|
||||
impl Ord for RoomItem {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
tag_cmp(&self.tags, &other.tags).then_with(|| room_cmp(&self.room, &other.room))
|
||||
tag_cmp(self.tags(), other.tags()).then_with(|| room_cmp(self.room(), other.room()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,7 +716,7 @@ impl ToString for RoomItem {
|
|||
|
||||
impl ListItem<IambInfo> for RoomItem {
|
||||
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||
if let Some(tags) = &self.tags {
|
||||
if let Some(tags) = &self.tags() {
|
||||
let style = selected_style(selected);
|
||||
let mut spans = vec![Span::styled(self.name.as_str(), style)];
|
||||
|
||||
|
@ -707,7 +729,7 @@ impl ListItem<IambInfo> for RoomItem {
|
|||
}
|
||||
|
||||
fn get_word(&self) -> Option<String> {
|
||||
self.room.room_id().to_string().into()
|
||||
self.room_id().to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,29 +740,37 @@ impl Promptable<ProgramContext, ProgramStore, IambInfo> for RoomItem {
|
|||
ctx: &ProgramContext,
|
||||
_: &mut ProgramStore,
|
||||
) -> EditResult<Vec<(ProgramAction, ProgramContext)>, IambInfo> {
|
||||
room_prompt(self.room.room_id(), act, ctx)
|
||||
room_prompt(self.room_id(), act, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DirectItem {
|
||||
room: MatrixRoom,
|
||||
tags: Option<Tags>,
|
||||
room_info: MatrixRoomInfo,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl DirectItem {
|
||||
fn new(
|
||||
room: MatrixRoom,
|
||||
name: DisplayName,
|
||||
tags: Option<Tags>,
|
||||
store: &mut ProgramStore,
|
||||
) -> Self {
|
||||
let name = name.to_string();
|
||||
fn new(room_info: MatrixRoomInfo, store: &mut ProgramStore) -> Self {
|
||||
let room_id = room_info.deref().0.room_id().to_owned();
|
||||
let name = store.application.get_room_info(room_id).name.clone().unwrap_or_default();
|
||||
|
||||
store.application.set_room_name(room.room_id(), name.as_str());
|
||||
DirectItem { room_info, name }
|
||||
}
|
||||
|
||||
DirectItem { room, tags, name }
|
||||
#[inline]
|
||||
fn room(&self) -> &MatrixRoom {
|
||||
&self.room_info.deref().0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn room_id(&self) -> &RoomId {
|
||||
self.room().room_id()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn tags(&self) -> &Option<Tags> {
|
||||
&self.room_info.deref().1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -752,7 +782,7 @@ impl ToString for DirectItem {
|
|||
|
||||
impl ListItem<IambInfo> for DirectItem {
|
||||
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||
if let Some(tags) = &self.tags {
|
||||
if let Some(tags) = &self.tags() {
|
||||
let style = selected_style(selected);
|
||||
let mut spans = vec![Span::styled(self.name.as_str(), style)];
|
||||
|
||||
|
@ -765,13 +795,13 @@ impl ListItem<IambInfo> for DirectItem {
|
|||
}
|
||||
|
||||
fn get_word(&self) -> Option<String> {
|
||||
self.room.room_id().to_string().into()
|
||||
self.room_id().to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for DirectItem {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.room.room_id() == other.room.room_id()
|
||||
self.room_id() == other.room_id()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,7 +809,7 @@ impl Eq for DirectItem {}
|
|||
|
||||
impl Ord for DirectItem {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
tag_cmp(&self.tags, &other.tags).then_with(|| room_cmp(&self.room, &other.room))
|
||||
tag_cmp(self.tags(), other.tags()).then_with(|| room_cmp(self.room(), other.room()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,7 +826,7 @@ impl Promptable<ProgramContext, ProgramStore, IambInfo> for DirectItem {
|
|||
ctx: &ProgramContext,
|
||||
_: &mut ProgramStore,
|
||||
) -> EditResult<Vec<(ProgramAction, ProgramContext)>, IambInfo> {
|
||||
room_prompt(self.room.room_id(), act, ctx)
|
||||
room_prompt(self.room_id(), act, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,11 +837,14 @@ pub struct SpaceItem {
|
|||
}
|
||||
|
||||
impl SpaceItem {
|
||||
fn new(room: MatrixRoom, name: DisplayName, store: &mut ProgramStore) -> Self {
|
||||
let name = name.to_string();
|
||||
fn new(room: MatrixRoom, store: &mut ProgramStore) -> Self {
|
||||
let room_id = room.room_id();
|
||||
|
||||
store.application.set_room_name(room_id, name.as_str());
|
||||
let name = store
|
||||
.application
|
||||
.get_room_info(room_id.to_owned())
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(alias) = room.canonical_alias() {
|
||||
store.application.names.insert(alias.to_string(), room_id.to_owned());
|
||||
|
|
|
@ -120,11 +120,12 @@ impl<'a> StatefulWidget for Space<'a> {
|
|||
let items = members
|
||||
.into_iter()
|
||||
.filter_map(|id| {
|
||||
let (room, name, tags) =
|
||||
let (room, _, tags) =
|
||||
self.store.application.worker.get_room(id.clone()).ok()?;
|
||||
let room_info = std::sync::Arc::new((room, tags));
|
||||
|
||||
if id != state.room_id {
|
||||
Some(RoomItem::new(room, name, tags, self.store))
|
||||
Some(RoomItem::new(room_info, self.store))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
341
src/worker.rs
341
src/worker.rs
|
@ -8,6 +8,7 @@ use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
|||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use gethostname::gethostname;
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::task::JoinHandle;
|
||||
|
@ -260,19 +261,122 @@ async fn load_insert(room_id: OwnedRoomId, res: MessageFetchResult, store: Async
|
|||
}
|
||||
}
|
||||
|
||||
async fn load_older(client: &Client, store: &AsyncProgramStore) {
|
||||
async fn load_older(client: &Client, store: &AsyncProgramStore) -> usize {
|
||||
let limit = MIN_MSG_LOAD;
|
||||
let plan = load_plan(store).await;
|
||||
|
||||
// Fetch each room separately, so they don't block each other.
|
||||
for (room_id, fetch_id) in plan.into_iter() {
|
||||
let client = client.clone();
|
||||
let store = store.clone();
|
||||
load_plan(store)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|(room_id, fetch_id)| {
|
||||
let client = client.clone();
|
||||
let store = store.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let res = load_older_one(client, room_id.as_ref(), fetch_id, limit).await;
|
||||
load_insert(room_id, res, store).await;
|
||||
});
|
||||
async move {
|
||||
let res = load_older_one(client, room_id.as_ref(), fetch_id, limit).await;
|
||||
load_insert(room_id, res, store).await;
|
||||
}
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>()
|
||||
.count()
|
||||
.await
|
||||
}
|
||||
|
||||
async fn load_older_forever(client: &Client, store: &AsyncProgramStore) {
|
||||
// Load older messages every 2 seconds.
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(2));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
load_older(client, store).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_rooms(client: &Client, store: &AsyncProgramStore) {
|
||||
let mut names = vec![];
|
||||
|
||||
let mut spaces = vec![];
|
||||
let mut rooms = vec![];
|
||||
let mut dms = vec![];
|
||||
|
||||
for room in client.invited_rooms().into_iter() {
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty).to_string();
|
||||
names.push((room.room_id().to_owned(), name));
|
||||
|
||||
if room.is_direct() {
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
dms.push(Arc::new((room.into(), tags)));
|
||||
} else if room.is_space() {
|
||||
spaces.push(room.into());
|
||||
} else {
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push(Arc::new((room.into(), tags)));
|
||||
}
|
||||
}
|
||||
|
||||
for room in client.joined_rooms().into_iter() {
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty).to_string();
|
||||
names.push((room.room_id().to_owned(), name));
|
||||
|
||||
if room.is_direct() {
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
dms.push(Arc::new((room.into(), tags)));
|
||||
} else if room.is_space() {
|
||||
spaces.push(room.into());
|
||||
} else {
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push(Arc::new((room.into(), tags)));
|
||||
}
|
||||
}
|
||||
|
||||
let mut locked = store.lock().await;
|
||||
locked.application.sync_info.spaces = spaces;
|
||||
locked.application.sync_info.rooms = rooms;
|
||||
locked.application.sync_info.dms = dms;
|
||||
|
||||
for (room_id, name) in names {
|
||||
locked.application.set_room_name(&room_id, &name);
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_rooms_forever(client: &Client, store: &AsyncProgramStore) {
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(5));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
refresh_rooms(client, store).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_receipts_forever(client: &Client, store: &AsyncProgramStore) {
|
||||
// Update the displayed read receipts every 5 seconds.
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(5));
|
||||
let mut sent = HashMap::<OwnedRoomId, OwnedEventId>::default();
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let receipts = update_receipts(client).await;
|
||||
let read = store.lock().await.application.set_receipts(receipts).await;
|
||||
|
||||
for (room_id, read_till) in read.into_iter() {
|
||||
if let Some(read_sent) = sent.get(&room_id) {
|
||||
if read_sent == &read_till {
|
||||
// Skip unchanged receipts.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(room) = client.get_joined_room(&room_id) {
|
||||
if room.read_receipt(&read_till).await.is_ok() {
|
||||
sent.insert(room_id, read_till);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,8 +435,6 @@ async fn update_receipts(client: &Client) -> Vec<(OwnedRoomId, Receipts)> {
|
|||
pub type FetchedRoom = (MatrixRoom, DisplayName, Option<Tags>);
|
||||
|
||||
pub enum WorkerTask {
|
||||
ActiveRooms(ClientReply<Vec<FetchedRoom>>),
|
||||
DirectMessages(ClientReply<Vec<FetchedRoom>>),
|
||||
Init(AsyncProgramStore, ClientReply<()>),
|
||||
Login(LoginStyle, ClientReply<IambResult<EditInfo>>),
|
||||
GetInviter(Invited, ClientReply<IambResult<Option<RoomMember>>>),
|
||||
|
@ -340,7 +442,6 @@ pub enum WorkerTask {
|
|||
JoinRoom(String, ClientReply<IambResult<OwnedRoomId>>),
|
||||
Members(OwnedRoomId, ClientReply<IambResult<Vec<RoomMember>>>),
|
||||
SpaceMembers(OwnedRoomId, ClientReply<IambResult<Vec<OwnedRoomId>>>),
|
||||
Spaces(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
||||
TypingNotice(OwnedRoomId),
|
||||
Verify(VerifyAction, SasVerification, ClientReply<IambResult<EditInfo>>),
|
||||
VerifyRequest(OwnedUserId, ClientReply<IambResult<EditInfo>>),
|
||||
|
@ -349,14 +450,6 @@ pub enum WorkerTask {
|
|||
impl Debug for WorkerTask {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
WorkerTask::ActiveRooms(_) => {
|
||||
f.debug_tuple("WorkerTask::ActiveRooms").field(&format_args!("_")).finish()
|
||||
},
|
||||
WorkerTask::DirectMessages(_) => {
|
||||
f.debug_tuple("WorkerTask::DirectMessages")
|
||||
.field(&format_args!("_"))
|
||||
.finish()
|
||||
},
|
||||
WorkerTask::Init(_, _) => {
|
||||
f.debug_tuple("WorkerTask::Init")
|
||||
.field(&format_args!("_"))
|
||||
|
@ -396,9 +489,6 @@ impl Debug for WorkerTask {
|
|||
.field(&format_args!("_"))
|
||||
.finish()
|
||||
},
|
||||
WorkerTask::Spaces(_) => {
|
||||
f.debug_tuple("WorkerTask::Spaces").field(&format_args!("_")).finish()
|
||||
},
|
||||
WorkerTask::TypingNotice(room_id) => {
|
||||
f.debug_tuple("WorkerTask::TypingNotice").field(room_id).finish()
|
||||
},
|
||||
|
@ -442,14 +532,6 @@ impl Requester {
|
|||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn direct_messages(&self) -> Vec<FetchedRoom> {
|
||||
let (reply, response) = oneshot();
|
||||
|
||||
self.tx.send(WorkerTask::DirectMessages(reply)).unwrap();
|
||||
|
||||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn get_inviter(&self, invite: Invited) -> IambResult<Option<RoomMember>> {
|
||||
let (reply, response) = oneshot();
|
||||
|
||||
|
@ -474,14 +556,6 @@ impl Requester {
|
|||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn active_rooms(&self) -> Vec<FetchedRoom> {
|
||||
let (reply, response) = oneshot();
|
||||
|
||||
self.tx.send(WorkerTask::ActiveRooms(reply)).unwrap();
|
||||
|
||||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn members(&self, room_id: OwnedRoomId) -> IambResult<Vec<RoomMember>> {
|
||||
let (reply, response) = oneshot();
|
||||
|
||||
|
@ -498,14 +572,6 @@ impl Requester {
|
|||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn spaces(&self) -> Vec<(MatrixRoom, DisplayName)> {
|
||||
let (reply, response) = oneshot();
|
||||
|
||||
self.tx.send(WorkerTask::Spaces(reply)).unwrap();
|
||||
|
||||
return response.recv();
|
||||
}
|
||||
|
||||
pub fn typing_notice(&self, room_id: OwnedRoomId) {
|
||||
self.tx.send(WorkerTask::TypingNotice(room_id)).unwrap();
|
||||
}
|
||||
|
@ -532,7 +598,6 @@ pub struct ClientWorker {
|
|||
settings: ApplicationSettings,
|
||||
client: Client,
|
||||
load_handle: Option<JoinHandle<()>>,
|
||||
rcpt_handle: Option<JoinHandle<()>>,
|
||||
sync_handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
|
@ -571,7 +636,6 @@ impl ClientWorker {
|
|||
settings,
|
||||
client: client.clone(),
|
||||
load_handle: None,
|
||||
rcpt_handle: None,
|
||||
sync_handle: None,
|
||||
};
|
||||
|
||||
|
@ -597,18 +661,10 @@ impl ClientWorker {
|
|||
if let Some(handle) = self.sync_handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
if let Some(handle) = self.rcpt_handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self, task: WorkerTask) {
|
||||
match task {
|
||||
WorkerTask::DirectMessages(reply) => {
|
||||
assert!(self.initialized);
|
||||
reply.send(self.direct_messages().await);
|
||||
},
|
||||
WorkerTask::Init(store, reply) => {
|
||||
assert_eq!(self.initialized, false);
|
||||
self.init(store).await;
|
||||
|
@ -626,10 +682,6 @@ impl ClientWorker {
|
|||
assert!(self.initialized);
|
||||
reply.send(self.get_room(room_id).await);
|
||||
},
|
||||
WorkerTask::ActiveRooms(reply) => {
|
||||
assert!(self.initialized);
|
||||
reply.send(self.active_rooms().await);
|
||||
},
|
||||
WorkerTask::Login(style, reply) => {
|
||||
assert!(self.initialized);
|
||||
reply.send(self.login_and_sync(style).await);
|
||||
|
@ -642,10 +694,6 @@ impl ClientWorker {
|
|||
assert!(self.initialized);
|
||||
reply.send(self.space_members(space).await);
|
||||
},
|
||||
WorkerTask::Spaces(reply) => {
|
||||
assert!(self.initialized);
|
||||
reply.send(self.spaces().await);
|
||||
},
|
||||
WorkerTask::TypingNotice(room_id) => {
|
||||
assert!(self.initialized);
|
||||
self.typing_notice(room_id).await;
|
||||
|
@ -903,50 +951,14 @@ impl ClientWorker {
|
|||
},
|
||||
);
|
||||
|
||||
self.rcpt_handle = tokio::spawn({
|
||||
let store = store.clone();
|
||||
let client = self.client.clone();
|
||||
let mut sent = HashMap::<OwnedRoomId, OwnedEventId>::default();
|
||||
|
||||
async move {
|
||||
// Update the displayed read receipts every 5 seconds.
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(5));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let receipts = update_receipts(&client).await;
|
||||
let read = store.lock().await.application.set_receipts(receipts).await;
|
||||
|
||||
for (room_id, read_till) in read.into_iter() {
|
||||
if let Some(read_sent) = sent.get(&room_id) {
|
||||
if read_sent == &read_till {
|
||||
// Skip unchanged receipts.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(room) = client.get_joined_room(&room_id) {
|
||||
if room.read_receipt(&read_till).await.is_ok() {
|
||||
sent.insert(room_id, read_till);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.into();
|
||||
|
||||
self.load_handle = tokio::spawn({
|
||||
let client = self.client.clone();
|
||||
|
||||
async move {
|
||||
// Load older messages every 2 seconds.
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(2));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
load_older(&client, &store).await;
|
||||
}
|
||||
let load = load_older_forever(&client, &store);
|
||||
let rcpt = refresh_receipts_forever(&client, &store);
|
||||
let room = refresh_rooms_forever(&client, &store);
|
||||
let ((), (), ()) = tokio::join!(load, rcpt, room);
|
||||
}
|
||||
})
|
||||
.into();
|
||||
|
@ -1002,31 +1014,30 @@ impl ClientWorker {
|
|||
Ok(Some(InfoMessage::from("Successfully logged in!")))
|
||||
}
|
||||
|
||||
async fn direct_message(&mut self, user: OwnedUserId) -> IambResult<FetchedRoom> {
|
||||
for (room, name, tags) in self.direct_messages().await {
|
||||
async fn direct_message(&mut self, user: OwnedUserId) -> IambResult<OwnedRoomId> {
|
||||
for room in self.client.rooms() {
|
||||
if !room.is_direct() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if room.get_member(user.as_ref()).await.map_err(IambError::from)?.is_some() {
|
||||
return Ok((room, name, tags));
|
||||
return Ok(room.room_id().to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let rt = CreateRoomType::Direct(user.clone());
|
||||
let flags = CreateRoomFlags::ENCRYPTED;
|
||||
|
||||
match create_room(&self.client, None, rt, flags).await {
|
||||
Ok(room_id) => self.get_room(room_id).await,
|
||||
Err(e) => {
|
||||
error!(
|
||||
user_id = user.as_str(),
|
||||
err = e.to_string(),
|
||||
"Failed to create direct message room"
|
||||
);
|
||||
create_room(&self.client, None, rt, flags).await.map_err(|e| {
|
||||
error!(
|
||||
user_id = user.as_str(),
|
||||
err = e.to_string(),
|
||||
"Failed to create direct message room"
|
||||
);
|
||||
|
||||
let msg = format!("Could not open a room with {user}");
|
||||
let err = UIError::Failure(msg);
|
||||
|
||||
Err(err)
|
||||
},
|
||||
}
|
||||
let msg = format!("Could not open a room with {user}");
|
||||
UIError::Failure(msg)
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_inviter(&mut self, invited: Invited) -> IambResult<Option<RoomMember>> {
|
||||
|
@ -1058,9 +1069,7 @@ impl ClientWorker {
|
|||
},
|
||||
}
|
||||
} else if let Ok(user) = OwnedUserId::try_from(name.as_str()) {
|
||||
let room = self.direct_message(user).await?.0;
|
||||
|
||||
return Ok(room.room_id().to_owned());
|
||||
self.direct_message(user).await
|
||||
} else {
|
||||
let msg = format!("{:?} is not a valid room or user name", name.as_str());
|
||||
let err = UIError::Failure(msg);
|
||||
|
@ -1069,62 +1078,6 @@ impl ClientWorker {
|
|||
}
|
||||
}
|
||||
|
||||
async fn direct_messages(&self) -> Vec<FetchedRoom> {
|
||||
let mut rooms = vec![];
|
||||
|
||||
for room in self.client.invited_rooms().into_iter() {
|
||||
if !room.is_direct() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push((room.into(), name, tags));
|
||||
}
|
||||
|
||||
for room in self.client.joined_rooms().into_iter() {
|
||||
if !room.is_direct() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push((room.into(), name, tags));
|
||||
}
|
||||
|
||||
return rooms;
|
||||
}
|
||||
|
||||
async fn active_rooms(&self) -> Vec<FetchedRoom> {
|
||||
let mut rooms = vec![];
|
||||
|
||||
for room in self.client.invited_rooms().into_iter() {
|
||||
if room.is_space() || room.is_direct() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push((room.into(), name, tags));
|
||||
}
|
||||
|
||||
for room in self.client.joined_rooms().into_iter() {
|
||||
if room.is_space() || room.is_direct() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
let tags = room.tags().await.unwrap_or_default();
|
||||
|
||||
rooms.push((room.into(), name, tags));
|
||||
}
|
||||
|
||||
return rooms;
|
||||
}
|
||||
|
||||
async fn members(&mut self, room_id: OwnedRoomId) -> IambResult<Vec<RoomMember>> {
|
||||
if let Some(room) = self.client.get_room(room_id.as_ref()) {
|
||||
Ok(room.active_members().await.map_err(IambError::from)?)
|
||||
|
@ -1145,32 +1098,6 @@ impl ClientWorker {
|
|||
Ok(rooms)
|
||||
}
|
||||
|
||||
async fn spaces(&self) -> Vec<(MatrixRoom, DisplayName)> {
|
||||
let mut spaces = vec![];
|
||||
|
||||
for room in self.client.invited_rooms().into_iter() {
|
||||
if !room.is_space() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
|
||||
spaces.push((room.into(), name));
|
||||
}
|
||||
|
||||
for room in self.client.joined_rooms().into_iter() {
|
||||
if !room.is_space() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||
|
||||
spaces.push((room.into(), name));
|
||||
}
|
||||
|
||||
return spaces;
|
||||
}
|
||||
|
||||
async fn typing_notice(&mut self, room_id: OwnedRoomId) {
|
||||
if let Some(room) = self.client.get_joined_room(room_id.as_ref()) {
|
||||
let _ = room.typing_notice(true).await;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue