Compare commits
18 Commits
0c1df908f2
...
438416bec1
Author | SHA1 | Date | |
---|---|---|---|
438416bec1
|
|||
c580fba315
|
|||
a7bccfa779
|
|||
eb81b3252c
|
|||
880195109d
|
|||
11e239714b
|
|||
4261e24cd2
|
|||
9cfc0841df
|
|||
39ff4122c9
|
|||
46ce890718
|
|||
82b15a5509
|
|||
912b67ed23
|
|||
0ec1187fc3
|
|||
f78765e553
|
|||
b26cb1d982
|
|||
fc9411376c
|
|||
df465d99c0
|
|||
491e34903f
|
29
Cargo.toml
29
Cargo.toml
@@ -3,27 +3,26 @@ name = "beau-gosse-du-92"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[features]
|
||||||
|
default = []
|
||||||
|
desktop = ["dioxus/desktop"]
|
||||||
|
web = ["dioxus/web"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus = "0.5.0"
|
dioxus = "0.5.*"
|
||||||
dioxus-desktop = "0.5.0"
|
|
||||||
dioxus-free-icons = { version = "0.8", features = ["material-design-icons-navigation", "ionicons"] }
|
dioxus-free-icons = { version = "0.8", features = ["material-design-icons-navigation", "ionicons"] }
|
||||||
dioxus-std = { git = "https://github.com/DioxusLabs/dioxus-std.git", branch = "master", features = ["utils"] }
|
dioxus-sdk = { version = "0.5.*", features = ["utils"] }
|
||||||
|
|
||||||
# matrix-sdk = { version = "0.6.2", features = ["js"] }
|
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", branch = "main", default-features = false, features = ["js", "rustls-tls"] }
|
||||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", branch = "main" , features = ["js"]}
|
|
||||||
|
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
ctrlc-async = "3.2.2"
|
ctrlc-async = "3.2.2"
|
||||||
tracing-subscriber = "0.3.18"
|
|
||||||
thiserror = "1.0.50"
|
thiserror = "1.0.50"
|
||||||
turf = "0.7.0"
|
turf = "0.7.0"
|
||||||
tokio = "1.34.0"
|
tokio = { version = "1.34.0", default-features = false, features = ["rt", "sync"] }
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
tracing = "0.1.40"
|
|
||||||
futures-util = "0.3.29"
|
futures-util = "0.3.29"
|
||||||
futures = "0.3.29"
|
futures = "0.3.29"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
@@ -31,16 +30,16 @@ reqwest = "0.11.24"
|
|||||||
validator = { version = "0.17.0", features = ["derive"] }
|
validator = { version = "0.17.0", features = ["derive"] }
|
||||||
const_format = "0.2.32"
|
const_format = "0.2.32"
|
||||||
zxcvbn = "2.2.2"
|
zxcvbn = "2.2.2"
|
||||||
|
async-std = "1.12.0"
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-web = "0.1.3"
|
||||||
|
tracing-subscriber = "0.3.18"
|
||||||
|
|
||||||
[build]
|
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||||
target = "x86_64-unknown-linux-gnu"
|
web-sys = { version = "0.3.69" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
regex = "1.10.3"
|
regex = "1.10.3"
|
||||||
|
|
||||||
[package.metadata.turf.class_names]
|
[package.metadata.turf.class_names]
|
||||||
template = "<original_name>--<id>"
|
template = "<original_name>--<id>"
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["desktop"]
|
|
||||||
desktop = ["dioxus/desktop"]
|
|
||||||
|
20
Dioxus.toml
Normal file
20
Dioxus.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[application]
|
||||||
|
name = "beau-gosse-du-92"
|
||||||
|
default_platform = "desktop"
|
||||||
|
|
||||||
|
[web.app]
|
||||||
|
name = "beau-gosse-du-92"
|
||||||
|
|
||||||
|
[web.watcher]
|
||||||
|
reload_html = true
|
||||||
|
watch_path = ["src", "font"]
|
||||||
|
|
||||||
|
[web.resource]
|
||||||
|
script = []
|
||||||
|
|
||||||
|
[web.resource.dev]
|
||||||
|
style = []
|
||||||
|
script = []
|
||||||
|
|
||||||
|
[[web.proxy]]
|
||||||
|
backend = "http://localhost:8000/api/"
|
102
src/base.rs
102
src/base.rs
@@ -2,21 +2,19 @@
|
|||||||
// In order to use/run the rx.next().await statement you will need to extend the [Stream] trait
|
// In order to use/run the rx.next().await statement you will need to extend the [Stream] trait
|
||||||
// (used by [UnboundedReceiver]) by adding 'futures_util' as a dependency to your project
|
// (used by [UnboundedReceiver]) by adding 'futures_util' as a dependency to your project
|
||||||
// and adding the use futures_util::stream::StreamExt;
|
// and adding the use futures_util::stream::StreamExt;
|
||||||
use futures_util::stream::StreamExt;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
|
||||||
|
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
use futures_util::stream::StreamExt;
|
||||||
|
use log::{debug, error, warn};
|
||||||
|
use matrix_sdk::ruma::OwnedRoomId;
|
||||||
|
use tokio::select;
|
||||||
|
|
||||||
|
use crate::domain::model::room::{ByIdRooms, Room};
|
||||||
|
use crate::domain::model::session::Session;
|
||||||
use crate::infrastructure::messaging::matrix::client::{Client, RoomEvent};
|
use crate::infrastructure::messaging::matrix::client::{Client, RoomEvent};
|
||||||
use crate::infrastructure::messaging::matrix::requester::{Receivers, Requester};
|
use crate::infrastructure::messaging::matrix::requester::{Receivers, Requester};
|
||||||
use crate::infrastructure::messaging::matrix::worker_tasks::LoginStyle;
|
use crate::infrastructure::messaging::matrix::worker_tasks::LoginStyle;
|
||||||
use dioxus::prelude::*;
|
|
||||||
use matrix_sdk::{
|
|
||||||
room::{Room as MatrixRoom, RoomMember},
|
|
||||||
ruma::{OwnedRoomId, OwnedUserId},
|
|
||||||
};
|
|
||||||
use tokio::select;
|
|
||||||
use tracing::{debug, error, warn};
|
|
||||||
|
|
||||||
use crate::ui::components::chats_window::interface::Interface as ChatsWinInterface;
|
use crate::ui::components::chats_window::interface::Interface as ChatsWinInterface;
|
||||||
|
|
||||||
// #[derive(Clone, Debug)]
|
// #[derive(Clone, Debug)]
|
||||||
@@ -40,55 +38,6 @@ use crate::ui::components::chats_window::interface::Interface as ChatsWinInterfa
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Room {
|
|
||||||
pub matrix_room: Arc<MatrixRoom>,
|
|
||||||
pub topic: Option<RefCell<String>>,
|
|
||||||
pub members: HashMap<OwnedUserId, RoomMember>,
|
|
||||||
pub is_direct: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Room {
|
|
||||||
pub fn new(
|
|
||||||
matrix_room: Arc<MatrixRoom>,
|
|
||||||
topic: Option<RefCell<String>>,
|
|
||||||
is_direct: Option<bool>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
matrix_room,
|
|
||||||
topic,
|
|
||||||
members: HashMap::new(),
|
|
||||||
is_direct,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self {
|
|
||||||
let room_topic = matrix_room.topic().map(RefCell::new);
|
|
||||||
|
|
||||||
Self::new(
|
|
||||||
Arc::new(matrix_room.to_owned()),
|
|
||||||
room_topic,
|
|
||||||
matrix_room.is_direct().await.ok(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> Option<String> {
|
|
||||||
self.matrix_room.name()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> OwnedRoomId {
|
|
||||||
OwnedRoomId::from(self.matrix_room.room_id())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for Room {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
// TODO: Look for a better way to compare Matrix rooms
|
|
||||||
self.matrix_room.room_id() == other.matrix_room.room_id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
|
|
||||||
// pub type ByIdUserInfos = HashMap<OwnedUserId, UserInfo>;
|
// pub type ByIdUserInfos = HashMap<OwnedUserId, UserInfo>;
|
||||||
|
|
||||||
// #[derive(Clone)]
|
// #[derive(Clone)]
|
||||||
@@ -152,10 +101,7 @@ async fn on_joining_invitation(
|
|||||||
room: Room,
|
room: Room,
|
||||||
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!("You're invited to join the \"{}\" room", room.id());
|
||||||
"You're invited to join the \"{}\" room",
|
|
||||||
room.name().unwrap()
|
|
||||||
);
|
|
||||||
// TODO: Update rooms
|
// TODO: Update rooms
|
||||||
by_id_rooms
|
by_id_rooms
|
||||||
.write()
|
.write()
|
||||||
@@ -165,7 +111,7 @@ async fn on_joining_invitation(
|
|||||||
async fn on_room_topic(room_id: OwnedRoomId, topic: String, by_id_rooms: &GlobalSignal<ByIdRooms>) {
|
async fn on_room_topic(room_id: OwnedRoomId, topic: String, by_id_rooms: &GlobalSignal<ByIdRooms>) {
|
||||||
if let Some(room) = by_id_rooms.read().get(&room_id) {
|
if let Some(room) = by_id_rooms.read().get(&room_id) {
|
||||||
let mut room = room.borrow_mut();
|
let mut room = room.borrow_mut();
|
||||||
room.topic = Some(RefCell::new(topic));
|
room.set_topic(Some(topic));
|
||||||
} else {
|
} else {
|
||||||
warn!("No room found with the \"{}\" id", room_id);
|
warn!("No room found with the \"{}\" id", room_id);
|
||||||
}
|
}
|
||||||
@@ -229,6 +175,7 @@ pub async fn login(
|
|||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Error during login: {err}");
|
error!("Error during login: {err}");
|
||||||
|
// TODO: Handle invalid login
|
||||||
// invalid_login.modify(|_| true);
|
// invalid_login.modify(|_| true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,33 +190,6 @@ pub async fn login(
|
|||||||
error!("=== LOGIN END ===");
|
error!("=== LOGIN END ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Session {
|
|
||||||
pub homeserver_url: Option<String>,
|
|
||||||
pub username: Option<String>,
|
|
||||||
pub password: Option<String>,
|
|
||||||
pub is_logged: bool,
|
|
||||||
}
|
|
||||||
impl Session {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
homeserver_url: None,
|
|
||||||
username: None,
|
|
||||||
password: None,
|
|
||||||
is_logged: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn update(
|
|
||||||
&mut self,
|
|
||||||
homeserver_url: Option<String>,
|
|
||||||
username: Option<String>,
|
|
||||||
password: Option<String>,
|
|
||||||
) {
|
|
||||||
self.homeserver_url = homeserver_url;
|
|
||||||
self.username = username;
|
|
||||||
self.password = password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static APP_SETTINGS: GlobalSignal<AppSettings> = Signal::global(AppSettings::new);
|
pub static APP_SETTINGS: GlobalSignal<AppSettings> = Signal::global(AppSettings::new);
|
||||||
pub static ROOMS: GlobalSignal<ByIdRooms> = Signal::global(ByIdRooms::new);
|
pub static ROOMS: GlobalSignal<ByIdRooms> = Signal::global(ByIdRooms::new);
|
||||||
pub static SESSION: GlobalSignal<Session> = Signal::global(Session::new);
|
pub static SESSION: GlobalSignal<Session> = Signal::global(Session::new);
|
||||||
|
1
src/domain/mod.rs
Normal file
1
src/domain/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub(crate) mod model;
|
2
src/domain/model/mod.rs
Normal file
2
src/domain/model/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub(crate) mod room;
|
||||||
|
pub(crate) mod session;
|
145
src/domain/model/room.rs
Normal file
145
src/domain/model/room.rs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use matrix_sdk::ruma::OwnedRoomId;
|
||||||
|
use matrix_sdk::{Room as MatrixRoom, RoomState as MatrixRoomState};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
pub(crate) type RoomId = OwnedRoomId;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct Room {
|
||||||
|
id: RoomId,
|
||||||
|
name: Option<String>,
|
||||||
|
topic: Option<String>,
|
||||||
|
is_direct: Option<bool>,
|
||||||
|
state: Option<MatrixRoomState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Room {
|
||||||
|
fn new(
|
||||||
|
id: RoomId,
|
||||||
|
name: Option<String>,
|
||||||
|
topic: Option<String>,
|
||||||
|
is_direct: Option<bool>,
|
||||||
|
state: Option<MatrixRoomState>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
topic,
|
||||||
|
is_direct,
|
||||||
|
state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use a factory instead...
|
||||||
|
pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self {
|
||||||
|
// let room_topic = matrix_room.topic().map(RefCell::new);
|
||||||
|
|
||||||
|
let id = RoomId::from(matrix_room.room_id());
|
||||||
|
let name = matrix_room.name();
|
||||||
|
let room_topic = matrix_room.topic();
|
||||||
|
let is_direct = match matrix_room.is_direct().await {
|
||||||
|
Ok(is_direct) => Some(is_direct),
|
||||||
|
Err(err) => {
|
||||||
|
error!("Unable to know if the room \"{id}\" is direct: {err}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let state = Some(matrix_room.state());
|
||||||
|
|
||||||
|
Self::new(id, name, room_topic, is_direct, state)
|
||||||
|
|
||||||
|
// room.timeline.subscribe().await
|
||||||
|
|
||||||
|
// Arc::new(matrix_room.to_owned()),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> &OwnedRoomId {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &Option<String> {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn topic(&self) -> &Option<String> {
|
||||||
|
&self.topic
|
||||||
|
}
|
||||||
|
pub fn set_topic(&mut self, topic: Option<String>) {
|
||||||
|
self.topic = topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_direct(&self) -> &Option<bool> {
|
||||||
|
&self.is_direct
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&self) -> &Option<MatrixRoomState> {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
pub fn is_invited(&self) -> Option<bool> {
|
||||||
|
match self.state {
|
||||||
|
Some(state) => Some(state == MatrixRoomState::Invited),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
|
||||||
|
|
||||||
|
// pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
|
||||||
|
|
||||||
|
// #[derive(Clone)]
|
||||||
|
// pub struct Room {
|
||||||
|
// // pub matrix_room: Arc<MatrixRoom>,
|
||||||
|
// pub topic: Option<RefCell<String>>,
|
||||||
|
// pub members: HashMap<OwnedUserId, RoomMember>,
|
||||||
|
// pub is_direct: Option<bool>,
|
||||||
|
// // pub timeline: Arc<Timeline>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Room {
|
||||||
|
// pub async fn new(
|
||||||
|
// matrix_room: Arc<MatrixRoom>,
|
||||||
|
// topic: Option<RefCell<String>>,
|
||||||
|
// is_direct: Option<bool>,
|
||||||
|
// ) -> Self {
|
||||||
|
// // TODO: Filter events
|
||||||
|
// // let timeline = Arc::new(matrix_room.timeline_builder().build().await.ok().unwrap());
|
||||||
|
// Self {
|
||||||
|
// matrix_room,
|
||||||
|
// topic,
|
||||||
|
// members: HashMap::new(),
|
||||||
|
// is_direct,
|
||||||
|
// // timeline,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self {
|
||||||
|
// let room_topic = matrix_room.topic().map(RefCell::new);
|
||||||
|
|
||||||
|
// Self::new(
|
||||||
|
// Arc::new(matrix_room.to_owned()),
|
||||||
|
// room_topic,
|
||||||
|
// matrix_room.is_direct().await.ok(),
|
||||||
|
// )
|
||||||
|
// .await
|
||||||
|
// // room.timeline.subscribe().await
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn name(&self) -> Option<String> {
|
||||||
|
// self.matrix_room.name()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn id(&self) -> OwnedRoomId {
|
||||||
|
// OwnedRoomId::from(self.matrix_room.room_id())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl PartialEq for Room {
|
||||||
|
// fn eq(&self, other: &Self) -> bool {
|
||||||
|
// // TODO: Look for a better way to compare Matrix rooms
|
||||||
|
// self.matrix_room.room_id() == other.matrix_room.room_id()
|
||||||
|
// }
|
||||||
|
// }
|
26
src/domain/model/session.rs
Normal file
26
src/domain/model/session.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
pub struct Session {
|
||||||
|
pub homeserver_url: Option<String>,
|
||||||
|
pub username: Option<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub is_logged: bool,
|
||||||
|
}
|
||||||
|
impl Session {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
homeserver_url: None,
|
||||||
|
username: None,
|
||||||
|
password: None,
|
||||||
|
is_logged: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn update(
|
||||||
|
&mut self,
|
||||||
|
homeserver_url: Option<String>,
|
||||||
|
username: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
|
) {
|
||||||
|
self.homeserver_url = homeserver_url;
|
||||||
|
self.username = username;
|
||||||
|
self.password = password;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,11 +1,16 @@
|
|||||||
|
use std::borrow::Borrow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use async_std::task;
|
||||||
|
use dioxus::prelude::Task;
|
||||||
|
use log::{debug, error};
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::sync::broadcast::Sender;
|
use tokio::sync::broadcast::Sender;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||||
|
use tokio::sync::oneshot;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tracing::{debug, error};
|
|
||||||
|
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
config::SyncSettings,
|
config::SyncSettings,
|
||||||
@@ -13,25 +18,11 @@ use matrix_sdk::{
|
|||||||
room::Room as MatrixRoom,
|
room::Room as MatrixRoom,
|
||||||
ruma::{
|
ruma::{
|
||||||
events::{
|
events::{
|
||||||
key::verification::{
|
|
||||||
done::{OriginalSyncKeyVerificationDoneEvent, ToDeviceKeyVerificationDoneEvent},
|
|
||||||
key::{OriginalSyncKeyVerificationKeyEvent, ToDeviceKeyVerificationKeyEvent},
|
|
||||||
request::ToDeviceKeyVerificationRequestEvent,
|
|
||||||
start::{OriginalSyncKeyVerificationStartEvent, ToDeviceKeyVerificationStartEvent},
|
|
||||||
},
|
|
||||||
presence::PresenceEvent,
|
|
||||||
reaction::ReactionEventContent,
|
|
||||||
room::{
|
room::{
|
||||||
member::{
|
member::{RoomMemberEventContent, StrippedRoomMemberEvent},
|
||||||
OriginalSyncRoomMemberEvent, RoomMemberEventContent, StrippedRoomMemberEvent,
|
|
||||||
},
|
|
||||||
message::RoomMessageEventContent,
|
|
||||||
name::RoomNameEventContent,
|
|
||||||
redaction::OriginalSyncRoomRedactionEvent,
|
|
||||||
topic::RoomTopicEventContent,
|
topic::RoomTopicEventContent,
|
||||||
},
|
},
|
||||||
typing::SyncTypingEvent,
|
SyncStateEvent,
|
||||||
SyncMessageLikeEvent, SyncStateEvent,
|
|
||||||
},
|
},
|
||||||
OwnedRoomId,
|
OwnedRoomId,
|
||||||
},
|
},
|
||||||
@@ -40,7 +31,7 @@ use matrix_sdk::{
|
|||||||
|
|
||||||
use super::requester::{Receivers, Requester};
|
use super::requester::{Receivers, Requester};
|
||||||
use super::worker_tasks::{LoginStyle, WorkerTask};
|
use super::worker_tasks::{LoginStyle, WorkerTask};
|
||||||
use crate::base::Room;
|
use crate::domain::model::room::Room;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum ClientError {
|
pub enum ClientError {
|
||||||
@@ -57,49 +48,58 @@ pub enum RoomEvent {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Senders {
|
struct Senders {
|
||||||
room_sender: Sender<RoomEvent>,
|
room_events_sender: Sender<RoomEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Senders {
|
impl Senders {
|
||||||
fn new(room_sender: Sender<RoomEvent>) -> Self {
|
fn new(room_events_sender: Sender<RoomEvent>) -> Self {
|
||||||
Self { room_sender }
|
Self { room_events_sender }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
client: Option<Arc<MatrixClient>>,
|
client: Option<Arc<MatrixClient>>,
|
||||||
sync_handle: Option<JoinHandle<()>>,
|
sync_task: Option<Task>,
|
||||||
senders: Senders,
|
senders: Senders,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(client: Arc<MatrixClient>, room_sender: Sender<RoomEvent>) -> Self {
|
pub fn new(client: Arc<MatrixClient>, room_events_sender: Sender<RoomEvent>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
client: Some(client),
|
client: Some(client),
|
||||||
sync_handle: None,
|
sync_task: None,
|
||||||
senders: Senders::new(room_sender),
|
senders: Senders::new(room_events_sender),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_sync_typing_event(_ev: SyncTypingEvent, room: MatrixRoom) {
|
// async fn on_sync_typing_event(_ev: SyncTypingEvent, room: MatrixRoom) {
|
||||||
debug!("== on_sync_typing_event ==");
|
// debug!("== on_sync_typing_event ==");
|
||||||
let room_id = room.room_id().to_owned();
|
// let room_id = room.room_id().to_owned();
|
||||||
dbg!(room_id);
|
// dbg!(room_id);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_presence_event(_ev: PresenceEvent) {
|
// async fn on_presence_event(_ev: PresenceEvent) {
|
||||||
debug!("== on_presence_event ==");
|
// debug!("== on_presence_event ==");
|
||||||
dbg!(_ev);
|
// dbg!(_ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_sync_state_event(ev: SyncStateEvent<RoomNameEventContent>, _room: MatrixRoom) {
|
// async fn on_sync_state_event(ev: SyncStateEvent<RoomNameEventContent>, _room: MatrixRoom) {
|
||||||
error!("== on_sync_state_event ==");
|
// error!("== on_sync_state_event ==");
|
||||||
if let SyncStateEvent::Original(ev) = ev {
|
// if let SyncStateEvent::Original(ev) = ev {
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// async fn on_original_sync_room_message_event(
|
||||||
|
// ev: OriginalSyncRoomMessageEvent,
|
||||||
|
// _matrix_room: MatrixRoom,
|
||||||
|
// _senders: Ctx<Senders>,
|
||||||
|
// ) {
|
||||||
|
// error!("== on_original_sync_room_message_event ==");
|
||||||
|
// error!("ev={:?}", ev.content);
|
||||||
|
// }
|
||||||
|
|
||||||
async fn on_stripped_room_member_event(
|
async fn on_stripped_room_member_event(
|
||||||
ev: StrippedRoomMemberEvent,
|
ev: StrippedRoomMemberEvent,
|
||||||
@@ -107,20 +107,20 @@ impl Client {
|
|||||||
matrix_room: MatrixRoom,
|
matrix_room: MatrixRoom,
|
||||||
senders: Ctx<Senders>,
|
senders: Ctx<Senders>,
|
||||||
) {
|
) {
|
||||||
if ev.state_key == matrix_client.user_id().unwrap() {
|
if ev.state_key == matrix_client.user_id().unwrap()
|
||||||
if matrix_room.state() == MatrixRoomState::Invited {
|
&& matrix_room.state() == MatrixRoomState::Invited
|
||||||
let room_id = matrix_room.room_id();
|
{
|
||||||
let room = Room::from_matrix_room(&matrix_room).await;
|
let room_id = matrix_room.room_id();
|
||||||
|
let room = Room::from_matrix_room(&matrix_room).await;
|
||||||
|
|
||||||
if let Err(err) = senders
|
if let Err(err) = senders
|
||||||
.room_sender
|
.room_events_sender
|
||||||
.send(RoomEvent::InviteEvent(room_id.to_owned(), room))
|
.send(RoomEvent::InviteEvent(room_id.to_owned(), room))
|
||||||
{
|
{
|
||||||
error!(
|
error!(
|
||||||
"Unable to publish the new room with \"{}\" id: {}",
|
"Unable to publish the new room with \"{}\" id: {}",
|
||||||
room_id, err
|
room_id, err
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ impl Client {
|
|||||||
let room_id = matrix_room.room_id();
|
let room_id = matrix_room.room_id();
|
||||||
|
|
||||||
if let Err(err) = senders
|
if let Err(err) = senders
|
||||||
.room_sender
|
.room_events_sender
|
||||||
.send(RoomEvent::TopicEvent(room_id.to_owned(), ev.content.topic))
|
.send(RoomEvent::TopicEvent(room_id.to_owned(), ev.content.topic))
|
||||||
{
|
{
|
||||||
error!("Unable to publish the \"{}\" new topic: {}", room_id, err);
|
error!("Unable to publish the \"{}\" new topic: {}", room_id, err);
|
||||||
@@ -148,12 +148,13 @@ impl Client {
|
|||||||
senders: Ctx<Senders>,
|
senders: Ctx<Senders>,
|
||||||
) {
|
) {
|
||||||
if let SyncStateEvent::Original(_ev) = ev {
|
if let SyncStateEvent::Original(_ev) = ev {
|
||||||
let room_sender = &senders.room_sender;
|
|
||||||
|
|
||||||
let room_id = matrix_room.room_id();
|
let room_id = matrix_room.room_id();
|
||||||
let room = Room::from_matrix_room(&matrix_room).await;
|
let room = Room::from_matrix_room(&matrix_room).await;
|
||||||
|
|
||||||
if let Err(err) = room_sender.send(RoomEvent::MemberEvent(room_id.to_owned(), room)) {
|
if let Err(err) = senders
|
||||||
|
.room_events_sender
|
||||||
|
.send(RoomEvent::MemberEvent(room_id.to_owned(), room))
|
||||||
|
{
|
||||||
error!(
|
error!(
|
||||||
"Unable to publish the new room with \"{}\" id: {}",
|
"Unable to publish the new room with \"{}\" id: {}",
|
||||||
room_id, err
|
room_id, err
|
||||||
@@ -162,103 +163,107 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_sync_message_like_room_message_event(
|
// async fn on_sync_message_like_room_message_event(
|
||||||
ev: SyncMessageLikeEvent<RoomMessageEventContent>,
|
// ev: SyncMessageLikeEvent<RoomMessageEventContent>,
|
||||||
_room: MatrixRoom,
|
// _room: MatrixRoom,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_sync_message_like_room_message_event ==");
|
// debug!("== on_sync_message_like_room_message_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_sync_message_like_reaction_event(
|
// async fn on_sync_message_like_reaction_event(
|
||||||
ev: SyncMessageLikeEvent<ReactionEventContent>,
|
// ev: SyncMessageLikeEvent<ReactionEventContent>,
|
||||||
_room: MatrixRoom,
|
// _room: MatrixRoom,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_sync_message_like_reaction_event ==");
|
// debug!("== on_sync_message_like_reaction_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_original_sync_room_redaction_event(
|
// async fn on_original_sync_room_redaction_event(
|
||||||
ev: OriginalSyncRoomRedactionEvent,
|
// ev: OriginalSyncRoomRedactionEvent,
|
||||||
_room: MatrixRoom,
|
// _room: MatrixRoom,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_original_sync_room_redaction_event ==");
|
// debug!("== on_original_sync_room_redaction_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_original_sync_room_member_event(
|
// async fn on_original_sync_room_member_event(
|
||||||
_ev: OriginalSyncRoomMemberEvent,
|
// _ev: OriginalSyncRoomMemberEvent,
|
||||||
_room: MatrixRoom,
|
// _room: MatrixRoom,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_original_sync_room_member_event ==");
|
// debug!("== on_original_sync_room_member_event ==");
|
||||||
|
|
||||||
// let mut store = store_ctx.read().unwrap().to_owned();
|
// let mut store = store_ctx.read().unwrap().to_owned();
|
||||||
// dbg!(store.rooms.keys());
|
// dbg!(store.rooms.keys());
|
||||||
// let is_direct = room.is_direct().await.ok();
|
// let is_direct = room.is_direct().await.ok();
|
||||||
// store.rooms.insert(
|
// store.rooms.insert(
|
||||||
// OwnedRoomId::from(room_id),
|
// OwnedRoomId::from(room_id),
|
||||||
// Arc::new(RwLock::new(Room::new(Arc::new(room), None, is_direct))),
|
// Arc::new(RwLock::new(Room::new(Arc::new(room), None, is_direct))),
|
||||||
// );
|
// );
|
||||||
// let _ = store_ctx.write(store);
|
// let _ = store_ctx.write(store);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_original_sync_key_verif_start_event(
|
// async fn on_original_sync_key_verif_start_event(
|
||||||
ev: OriginalSyncKeyVerificationStartEvent,
|
// ev: OriginalSyncKeyVerificationStartEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_original_sync_key_verif_start_event ==");
|
// debug!("== on_original_sync_key_verif_start_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_original_sync_key_verif_key_event(
|
// async fn on_original_sync_key_verif_key_event(
|
||||||
ev: OriginalSyncKeyVerificationKeyEvent,
|
// ev: OriginalSyncKeyVerificationKeyEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_original_sync_key_verif_key_event ==");
|
// debug!("== on_original_sync_key_verif_key_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_original_sync_key_verif_done_event(
|
// async fn on_original_sync_key_verif_done_event(
|
||||||
ev: OriginalSyncKeyVerificationDoneEvent,
|
// ev: OriginalSyncKeyVerificationDoneEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_original_sync_key_verif_done_event ==");
|
// debug!("== on_original_sync_key_verif_done_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_device_key_verif_req_event(
|
// async fn on_device_key_verif_req_event(
|
||||||
ev: ToDeviceKeyVerificationRequestEvent,
|
// ev: ToDeviceKeyVerificationRequestEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_device_key_verif_req_event ==");
|
// debug!("== on_device_key_verif_req_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_device_key_verif_start_event(
|
// async fn on_device_key_verif_start_event(
|
||||||
ev: ToDeviceKeyVerificationStartEvent,
|
// ev: ToDeviceKeyVerificationStartEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_device_key_verif_start_event ==");
|
// debug!("== on_device_key_verif_start_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_device_key_verif_key_event(
|
// async fn on_device_key_verif_key_event(
|
||||||
ev: ToDeviceKeyVerificationKeyEvent,
|
// ev: ToDeviceKeyVerificationKeyEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_device_key_verif_key_event ==");
|
// debug!("== on_device_key_verif_key_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn on_device_key_verif_done_event(
|
// async fn on_device_key_verif_done_event(
|
||||||
ev: ToDeviceKeyVerificationDoneEvent,
|
// ev: ToDeviceKeyVerificationDoneEvent,
|
||||||
_client: MatrixClient,
|
// _client: MatrixClient,
|
||||||
) {
|
// ) {
|
||||||
debug!("== on_device_key_verif_done_event ==");
|
// debug!("== on_device_key_verif_done_event ==");
|
||||||
dbg!(ev);
|
// dbg!(ev);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// async fn on_room_event(ev: SomeEvent, _senders: Ctx<Senders>) {
|
||||||
|
// debug!("== on_room_event({}) ==", ev.)
|
||||||
|
// }
|
||||||
|
|
||||||
pub async fn spawn(homeserver_url: String) -> Requester {
|
pub async fn spawn(homeserver_url: String) -> Requester {
|
||||||
let (tx, rx) = unbounded_channel::<WorkerTask>();
|
let (tx, rx) = unbounded_channel::<WorkerTask>();
|
||||||
@@ -275,10 +280,8 @@ impl Client {
|
|||||||
|
|
||||||
let mut client = Client::new(matrix_client.clone(), room_sender);
|
let mut client = Client::new(matrix_client.clone(), room_sender);
|
||||||
|
|
||||||
tokio::spawn({
|
dioxus::prelude::spawn(async move {
|
||||||
async move {
|
client.work(rx).await;
|
||||||
client.work(rx).await;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Requester {
|
Requester {
|
||||||
@@ -291,62 +294,34 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) {
|
fn init(&mut self) {
|
||||||
let client = self.client.clone().unwrap();
|
if let Some(client) = self.client.borrow() {
|
||||||
|
client.add_event_handler_context(self.senders.clone());
|
||||||
|
|
||||||
client.add_event_handler_context(self.senders.clone());
|
let _ = client.add_event_handler(Client::on_stripped_room_member_event);
|
||||||
|
let _ = client.add_event_handler(Client::on_room_topic_event);
|
||||||
|
let _ = client.add_event_handler(Client::on_room_member_event);
|
||||||
|
|
||||||
let _ = client.add_event_handler(Client::on_sync_typing_event);
|
// let _ = client.add_event_handler(Client::on_sync_typing_event);
|
||||||
let _ = client.add_event_handler(Client::on_presence_event);
|
// let _ = client.add_event_handler(Client::on_presence_event);
|
||||||
let _ = client.add_event_handler(Client::on_sync_state_event);
|
// let _ = client.add_event_handler(Client::on_sync_state_event);
|
||||||
let _ = client.add_event_handler(Client::on_stripped_room_member_event);
|
// let _ = client.add_event_handler(Client::on_original_sync_room_message_event);
|
||||||
let _ = client.add_event_handler(Client::on_sync_message_like_room_message_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_sync_message_like_reaction_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_original_sync_room_redaction_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_original_sync_room_member_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_original_sync_key_verif_start_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_original_sync_key_verif_key_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_original_sync_key_verif_done_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_device_key_verif_req_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_device_key_verif_start_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_device_key_verif_key_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_device_key_verif_done_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_room_topic_event);
|
|
||||||
let _ = client.add_event_handler(Client::on_room_member_event);
|
|
||||||
|
|
||||||
self.initialized = true;
|
// let _ = client.add_event_handler(Client::on_sync_message_like_room_message_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_sync_message_like_reaction_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_original_sync_room_redaction_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_original_sync_room_member_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_start_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_key_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_done_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_device_key_verif_req_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_device_key_verif_start_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_device_key_verif_key_event);
|
||||||
|
// let _ = client.add_event_handler(Client::on_device_key_verif_done_event);
|
||||||
|
|
||||||
|
self.initialized = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async fn refresh_rooms(matrix_client: &MatrixClient, room_sender: &Sender<RoomMemberEvent>) {
|
|
||||||
// let joined_matrix_rooms_ref = &matrix_client.joined_rooms();
|
|
||||||
// let invited_matrix_rooms_ref = &matrix_client.invited_rooms();
|
|
||||||
|
|
||||||
// for matrix_rooms in [joined_matrix_rooms_ref, invited_matrix_rooms_ref] {
|
|
||||||
// for matrix_room in matrix_rooms.iter() {
|
|
||||||
// let topic = matrix_room.topic().map(RefCell::new);
|
|
||||||
// let room = Room::new(
|
|
||||||
// Arc::new(matrix_room.to_owned()),
|
|
||||||
// topic,
|
|
||||||
// matrix_room.is_direct().await.ok(),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if let Err(err) = room_sender.send(room) {
|
|
||||||
// warn!("Error: {}", err);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async fn refresh_rooms_forever(matrix_client: &MatrixClient, room_channel: &Sender<RoomEvent>) {
|
|
||||||
// // TODO: Add interval to config
|
|
||||||
// let mut interval = tokio::time::interval(Duration::from_secs(5));
|
|
||||||
|
|
||||||
// loop {
|
|
||||||
// // Self::refresh_rooms(matrix_client, room_channel).await;
|
|
||||||
|
|
||||||
// interval.tick().await;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
async fn login_and_sync(&mut self, style: LoginStyle) -> anyhow::Result<()> {
|
async fn login_and_sync(&mut self, style: LoginStyle) -> anyhow::Result<()> {
|
||||||
let client = self.client.clone().unwrap();
|
let client = self.client.clone().unwrap();
|
||||||
|
|
||||||
@@ -362,62 +337,95 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let (synchronized_tx, synchronized_rx) = oneshot::channel();
|
let (synchronized_tx, synchronized_rx) = oneshot::channel::<bool>();
|
||||||
|
|
||||||
self.sync_handle = tokio::spawn({
|
let task = dioxus::prelude::spawn(async move {
|
||||||
async move {
|
// Sync once so we receive the client state and old messages
|
||||||
// Sync once so we receive the client state and old messages
|
let sync_token_option = match client.sync_once(SyncSettings::default()).await {
|
||||||
let sync_token_option = match client.sync_once(SyncSettings::default()).await {
|
Ok(sync_response) => Some(sync_response.next_batch),
|
||||||
Ok(sync_response) => Some(sync_response.next_batch),
|
Err(err) => {
|
||||||
Err(err) => {
|
error!("Error during sync one: {}", err);
|
||||||
error!("Error during sync one: {}", err);
|
None
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(sync_token) = sync_token_option {
|
|
||||||
let settings = SyncSettings::default().token(sync_token);
|
|
||||||
|
|
||||||
debug!("User connected to the homeserver, start syncing");
|
|
||||||
|
|
||||||
let _ = client.sync(settings).await;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(sync_token) = sync_token_option {
|
||||||
|
let settings = SyncSettings::default().token(sync_token);
|
||||||
|
|
||||||
|
debug!("User connected to the homeserver, start syncing");
|
||||||
|
|
||||||
|
if let Err(err) = synchronized_tx.send(true) {
|
||||||
|
error!("Unable to notify that the Matrix client is now synchronized ({err})");
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = client.sync(settings).await;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.into();
|
self.sync_task = Some(task);
|
||||||
|
|
||||||
// self.start_background_tasks(synchronized_rx);
|
// self.start_background_tasks(synchronized_rx);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// async fn register_room_events(&self, room_id: OwnedRoomId) {
|
||||||
|
// let client = self.client.unwrap();
|
||||||
|
|
||||||
|
// client.add_room_event_handler(&room_id, Client::on_room_event);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async fn refresh_rooms(
|
||||||
|
// matrix_client: &Arc<MatrixClient>,
|
||||||
|
// room_events_sender: &Sender<RoomEvent>,
|
||||||
|
// ) {
|
||||||
|
// let joined_matrix_rooms_ref = &matrix_client.joined_rooms();
|
||||||
|
// let invited_matrix_rooms_ref = &matrix_client.invited_rooms();
|
||||||
|
|
||||||
|
// for matrix_rooms in [joined_matrix_rooms_ref, invited_matrix_rooms_ref] {
|
||||||
|
// for matrix_room in matrix_rooms.iter() {
|
||||||
|
// let room = Room::from_matrix_room(matrix_room).await;
|
||||||
|
// let event = RoomEvent::MemberEvent(room.id().clone(), room);
|
||||||
|
|
||||||
|
// if let Err(err) = room_events_sender.send(event) {
|
||||||
|
// error!("Error: {}", err);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async fn refresh_rooms_forever(
|
||||||
|
// matrix_client: Arc<MatrixClient>,
|
||||||
|
// room_events_sender: &Sender<RoomEvent>,
|
||||||
|
// ) {
|
||||||
|
// // TODO: Add interval to config
|
||||||
|
// let period_sec = Duration::from_secs(5);
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
// Self::refresh_rooms(&matrix_client, room_events_sender).await;
|
||||||
|
|
||||||
|
// task::sleep(period_sec).await;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// fn start_background_tasks(&mut self, synchronized_rx: oneshot::Receiver<bool>) {
|
// fn start_background_tasks(&mut self, synchronized_rx: oneshot::Receiver<bool>) {
|
||||||
// let client = self.client.clone().unwrap();
|
// let client = self.client.clone().unwrap();
|
||||||
// let room_sender_ref = &self.senders.room_sender;
|
// let room_events_sender = self.senders.room_events_sender.clone();
|
||||||
|
|
||||||
// self.load_handle = tokio::spawn({
|
// let task = dioxus::prelude::spawn(async move {
|
||||||
// to_owned![room_sender_ref];
|
// if let Err(err) = synchronized_rx.await {
|
||||||
|
// error!("Unable to setup the rx channel notifying that the Matrix client is now synchronized ({err})");
|
||||||
// async move {
|
|
||||||
// if let Err(err) = synchronized_rx.await {
|
|
||||||
// error!("Unable to setup the rx channel notifying that the Matrix client is now synchronized ({err})");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let rooms_refresh = Self::refresh_rooms_forever(
|
|
||||||
// client.as_ref(),
|
|
||||||
// &room_sender_ref
|
|
||||||
// );
|
|
||||||
// let ((),) = tokio::join!(rooms_refresh);
|
|
||||||
// }
|
// }
|
||||||
// })
|
|
||||||
// .into();
|
// debug!("Start room refreshing forever");
|
||||||
|
|
||||||
|
// let _ = Self::refresh_rooms_forever(client, &room_events_sender).await;
|
||||||
|
// });
|
||||||
|
// self.background_task = Some(task);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
async fn work(&mut self, mut rx: UnboundedReceiver<WorkerTask>) {
|
async fn work(&mut self, mut rx: UnboundedReceiver<WorkerTask>) {
|
||||||
loop {
|
loop {
|
||||||
let task = rx.recv().await;
|
match rx.recv().await {
|
||||||
|
|
||||||
match task {
|
|
||||||
Some(task) => self.run(task).await,
|
Some(task) => self.run(task).await,
|
||||||
None => {
|
None => {
|
||||||
break;
|
break;
|
||||||
@@ -425,8 +433,8 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(handle) = self.sync_handle.take() {
|
if let Some(task) = self.sync_task.take() {
|
||||||
handle.abort();
|
task.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +448,10 @@ impl Client {
|
|||||||
WorkerTask::Login(style, reply) => {
|
WorkerTask::Login(style, reply) => {
|
||||||
assert!(self.initialized);
|
assert!(self.initialized);
|
||||||
reply.send(self.login_and_sync(style).await).await;
|
reply.send(self.login_and_sync(style).await).await;
|
||||||
}
|
} // WorkerTask::registerRoomEvents(room_id, reply) => {
|
||||||
|
// assert!(self.initialized);
|
||||||
|
// reply.send(self.register_room_events(room_id).await).await;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,8 +37,11 @@ impl Requester {
|
|||||||
pub async fn init(&self) -> anyhow::Result<()> {
|
pub async fn init(&self) -> anyhow::Result<()> {
|
||||||
let (reply, mut response) = oneshot();
|
let (reply, mut response) = oneshot();
|
||||||
|
|
||||||
// TODO: Handle error case.
|
if let Err(err) = self.tx.send(WorkerTask::Init(reply)) {
|
||||||
self.tx.send(WorkerTask::Init(reply)).unwrap();
|
let msg = format!("Unable to request the init of the Matrix client: {err}");
|
||||||
|
return Err(anyhow::Error::msg(msg));
|
||||||
|
}
|
||||||
|
|
||||||
match response.recv().await {
|
match response.recv().await {
|
||||||
Some(result) => Ok(result),
|
Some(result) => Ok(result),
|
||||||
None => Err(anyhow::Error::msg("TBD")),
|
None => Err(anyhow::Error::msg("TBD")),
|
||||||
@@ -48,8 +51,11 @@ impl Requester {
|
|||||||
pub async fn login(&self, style: LoginStyle) -> anyhow::Result<()> {
|
pub async fn login(&self, style: LoginStyle) -> anyhow::Result<()> {
|
||||||
let (reply, mut response) = oneshot();
|
let (reply, mut response) = oneshot();
|
||||||
|
|
||||||
// TODO: Handle error case.
|
if let Err(err) = self.tx.send(WorkerTask::Login(style, reply)) {
|
||||||
self.tx.send(WorkerTask::Login(style, reply)).unwrap();
|
let msg = format!("Unable to request login to the Matrix client: {err}");
|
||||||
|
return Err(anyhow::Error::msg(msg));
|
||||||
|
}
|
||||||
|
|
||||||
match response.recv().await {
|
match response.recv().await {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => Err(anyhow::Error::msg("TBD")),
|
None => Err(anyhow::Error::msg("TBD")),
|
||||||
|
@@ -1,12 +1,17 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Result as IoResult;
|
use std::future::Future;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
use std::{collections::HashMap, future::IntoFuture};
|
||||||
|
|
||||||
|
use log::error;
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use reqwest::Result as RequestResult;
|
use reqwest::Result as RequestResult;
|
||||||
|
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
use tokio::fs::read_to_string;
|
use tokio::fs::read_to_string;
|
||||||
use tracing::error;
|
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
use web_sys;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash)]
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
pub enum AvatarFeeling {
|
pub enum AvatarFeeling {
|
||||||
@@ -59,9 +64,9 @@ struct DicebearConfig<'a> {
|
|||||||
lips: Vec<u32>,
|
lips: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dicebear_variants() -> &'static HashMap<AvatarFeeling, DicebearConfig<'static>> {
|
fn avatar_variants() -> &'static HashMap<AvatarFeeling, DicebearConfig<'static>> {
|
||||||
static HASHMAP: OnceLock<HashMap<AvatarFeeling, DicebearConfig>> = OnceLock::new();
|
static VARIANTS: OnceLock<HashMap<AvatarFeeling, DicebearConfig>> = OnceLock::new();
|
||||||
HASHMAP.get_or_init(|| {
|
VARIANTS.get_or_init(|| {
|
||||||
let mut variants = HashMap::new();
|
let mut variants = HashMap::new();
|
||||||
variants.insert(
|
variants.insert(
|
||||||
AvatarFeeling::Alerting,
|
AvatarFeeling::Alerting,
|
||||||
@@ -103,17 +108,16 @@ fn render_dicebear_variants(values: &[u32]) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_text(req: String) -> RequestResult<String> {
|
async fn fetch_text(req: String) -> RequestResult<String> {
|
||||||
reqwest::get(req).await?.text().await
|
match reqwest::get(req).await?.error_for_status() {
|
||||||
}
|
Ok(res) => res.text().await,
|
||||||
|
Err(err) => Err(err),
|
||||||
async fn read_file(path: &str) -> IoResult<String> {
|
}
|
||||||
read_to_string(path).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_dicebear_svg(
|
async fn fetch_dicebear_svg(
|
||||||
r#type: &DicebearType,
|
r#type: &DicebearType,
|
||||||
req_fields: &Vec<String>,
|
req_fields: &Vec<String>,
|
||||||
placeholder_path: Option<&str>,
|
placeholder_fetcher: Option<Box<impl Future<Output = Option<String>>>>,
|
||||||
) -> String {
|
) -> String {
|
||||||
// TODO: Use configuration file
|
// TODO: Use configuration file
|
||||||
let url = "dicebear.tools.adrien.run";
|
let url = "dicebear.tools.adrien.run";
|
||||||
@@ -121,7 +125,7 @@ async fn fetch_dicebear_svg(
|
|||||||
let seed = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
|
let seed = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
|
||||||
let type_str = r#type.to_string();
|
let type_str = r#type.to_string();
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"https://{url}/7.x/{type_str}/svg?seed={seed}{}{}",
|
"https://{url}/8.x/{type_str}/svg?seed={seed}&randomizeIds=true{}{}",
|
||||||
if !req_fields.is_empty() { "&" } else { " " },
|
if !req_fields.is_empty() { "&" } else { " " },
|
||||||
req_fields.join("&")
|
req_fields.join("&")
|
||||||
);
|
);
|
||||||
@@ -130,19 +134,10 @@ async fn fetch_dicebear_svg(
|
|||||||
Ok(text) => Some(text),
|
Ok(text) => Some(text),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Error during placeholder loading: {}", err);
|
error!("Error during placeholder loading: {}", err);
|
||||||
|
if let Some(placeholder_fetcher) = placeholder_fetcher {
|
||||||
match placeholder_path {
|
placeholder_fetcher.into_future().await
|
||||||
Some(placeholder_path) => match read_file(placeholder_path).await {
|
} else {
|
||||||
Ok(content) => Some(content),
|
None
|
||||||
Err(err) => {
|
|
||||||
error!(
|
|
||||||
"Error during to read {placeholder_path} file: {}",
|
|
||||||
err.to_string()
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -150,9 +145,44 @@ async fn fetch_dicebear_svg(
|
|||||||
text.unwrap_or("".to_string())
|
text.unwrap_or("".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
|
fn gen_placeholder_fetcher<'a>(path: &'static str) -> Box<impl Future<Output = Option<String>>> {
|
||||||
|
let path = format!(".{}", &path);
|
||||||
|
Box::new(async move {
|
||||||
|
match read_to_string(&path).await {
|
||||||
|
Ok(content) => Some(content),
|
||||||
|
Err(err) => {
|
||||||
|
error!(
|
||||||
|
"Error during the access to the {path} file: {}",
|
||||||
|
err.to_string()
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
fn gen_placeholder_fetcher<'a>(path: &'static str) -> Box<impl Future<Output = Option<String>>> {
|
||||||
|
Box::new(async move {
|
||||||
|
let url = format!("{}{}", web_sys::window().unwrap().origin(), path);
|
||||||
|
match fetch_text(url).await {
|
||||||
|
Ok(content) => Some(content),
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error during {path} fetching: {}", err.to_string());
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "desktop", feature = "web")))]
|
||||||
|
fn gen_placeholder_fetcher<'a>(_path: &'static str) -> Box<impl Future<Output = Option<String>>> {
|
||||||
|
Box::new(async move { None })
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>) -> String {
|
pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>) -> String {
|
||||||
let (variant, feeling) = match config {
|
let (variant, feeling) = match config {
|
||||||
Some(config) => (dicebear_variants().get(&config.feeling), &config.feeling),
|
Some(config) => (avatar_variants().get(&config.feeling), &config.feeling),
|
||||||
None => (None, &AvatarFeeling::Alerting),
|
None => (None, &AvatarFeeling::Alerting),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,15 +212,15 @@ pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
let placeholder_path = match feeling {
|
let placeholder_path = match feeling {
|
||||||
AvatarFeeling::Ok => "./images/modal-default-ok-icon.svg",
|
AvatarFeeling::Ok => "/images/modal-default-ok-icon.svg",
|
||||||
AvatarFeeling::Warning => "./images/modal-default-warning-icon.svg",
|
AvatarFeeling::Warning => "/images/modal-default-warning-icon.svg",
|
||||||
AvatarFeeling::Alerting => "./images/modal-default-critical-icon.svg",
|
AvatarFeeling::Alerting => "/images/modal-default-critical-icon.svg",
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch_dicebear_svg(
|
fetch_dicebear_svg(
|
||||||
&DicebearType::Notionists,
|
&DicebearType::Notionists,
|
||||||
&req_fields,
|
&req_fields,
|
||||||
Some(placeholder_path),
|
Some(gen_placeholder_fetcher(placeholder_path)),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -227,5 +257,11 @@ pub async fn generate_random_svg_shape<'a>(config: Option<&'a ShapeConfig<'a>>)
|
|||||||
req_fields.push(format!("shape3Color={}", config.shape_3_color));
|
req_fields.push(format!("shape3Color={}", config.shape_3_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch_dicebear_svg(&DicebearType::Shapes, &req_fields, None).await
|
let placeholder_path = "/images/login-profile-placeholder.svg";
|
||||||
|
fetch_dicebear_svg(
|
||||||
|
&DicebearType::Shapes,
|
||||||
|
&req_fields,
|
||||||
|
Some(gen_placeholder_fetcher(placeholder_path)),
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
46
src/main.rs
46
src/main.rs
@@ -1,12 +1,23 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
mod domain;
|
||||||
mod infrastructure;
|
mod infrastructure;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use async_std::task;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tokio::time::{sleep, Duration};
|
|
||||||
use tracing::{debug, Level};
|
#[cfg(feature = "desktop")]
|
||||||
|
use dioxus::desktop::Config;
|
||||||
|
|
||||||
|
use tracing::debug;
|
||||||
|
use tracing_subscriber::prelude::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
use tracing_web::MakeWebConsoleWriter;
|
||||||
|
|
||||||
use crate::base::{login, sync_rooms};
|
use crate::base::{login, sync_rooms};
|
||||||
use crate::base::{APP_SETTINGS, ROOMS, SESSION};
|
use crate::base::{APP_SETTINGS, ROOMS, SESSION};
|
||||||
@@ -24,8 +35,8 @@ fn app() -> Element {
|
|||||||
// Dummy timer simulating the loading of the application
|
// Dummy timer simulating the loading of the application
|
||||||
let _: Coroutine<()> = use_coroutine(|_: UnboundedReceiver<_>| async move {
|
let _: Coroutine<()> = use_coroutine(|_: UnboundedReceiver<_>| async move {
|
||||||
debug!("Not ready");
|
debug!("Not ready");
|
||||||
sleep(Duration::from_secs(3)).await;
|
task::sleep(Duration::from_secs(3)).await;
|
||||||
// sleep(Duration::from_secs(0)).await;
|
// task::sleep(Duration::from_secs(0)).await;
|
||||||
debug!("Ready");
|
debug!("Ready");
|
||||||
ready.set(true);
|
ready.set(true);
|
||||||
});
|
});
|
||||||
@@ -108,10 +119,27 @@ fn app() -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tracing_subscriber::fmt()
|
#[cfg(feature = "desktop")]
|
||||||
// .pretty()
|
{
|
||||||
.with_max_level(Level::DEBUG)
|
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||||
.init();
|
.with_filter(tracing::level_filters::LevelFilter::DEBUG);
|
||||||
|
tracing_subscriber::registry().with(fmt_layer).init();
|
||||||
|
|
||||||
launch(app);
|
let config = Config::new().with_menu(None);
|
||||||
|
let builder = LaunchBuilder::new().with_cfg(config);
|
||||||
|
builder.launch(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
{
|
||||||
|
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||||
|
.with_ansi(false) // Only partially supported across browsers
|
||||||
|
.without_time() // std::time is not available in browsers, see note below
|
||||||
|
.with_writer(MakeWebConsoleWriter::new()) // write events to the console
|
||||||
|
.with_filter(tracing::level_filters::LevelFilter::INFO);
|
||||||
|
tracing_subscriber::registry().with(fmt_layer).init(); // Install these as subscribers to tracing events
|
||||||
|
|
||||||
|
let builder = LaunchBuilder::new();
|
||||||
|
builder.launch(app);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -186,6 +186,12 @@ $geist-font-path: "../fonts/Geist";
|
|||||||
|
|
||||||
$transition-duration: 300ms;
|
$transition-duration: 300ms;
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
src: url("#{$geist-font-path}/Geist-Medium.woff2") format("woff2");
|
||||||
|
font-family: "Geist";
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
src: url("#{$geist-font-path}/Geist-Bold.woff2") format("woff2");
|
src: url("#{$geist-font-path}/Geist-Bold.woff2") format("woff2");
|
||||||
font-family: "Geist";
|
font-family: "Geist";
|
||||||
@@ -205,6 +211,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
font-family: "Geist";
|
font-family: "Geist";
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use log::error;
|
||||||
use matrix_sdk::ruma::OwnedRoomId;
|
use matrix_sdk::ruma::OwnedRoomId;
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
use super::edit_section::EditSection;
|
use super::edit_section::EditSection;
|
||||||
use crate::base::{sync_messages, ROOMS};
|
use crate::base::{sync_messages, ROOMS};
|
||||||
|
@@ -8,11 +8,12 @@ use std::cell::RefCell;
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use log::{debug, error};
|
||||||
use matrix_sdk::ruma::OwnedRoomId;
|
use matrix_sdk::ruma::OwnedRoomId;
|
||||||
use tokio::sync::broadcast::Receiver;
|
use tokio::sync::broadcast::Receiver;
|
||||||
use tracing::{debug, error};
|
|
||||||
|
|
||||||
use crate::base::{sync_rooms, Room, ROOMS};
|
use crate::base::{sync_rooms, ROOMS};
|
||||||
|
use crate::domain::model::room::Room;
|
||||||
use crate::infrastructure::messaging::matrix::requester::Receivers;
|
use crate::infrastructure::messaging::matrix::requester::Receivers;
|
||||||
use conversation::Conversation;
|
use conversation::Conversation;
|
||||||
use navbar::Navbar;
|
use navbar::Navbar;
|
||||||
@@ -35,10 +36,13 @@ fn render_rooms_tabs(
|
|||||||
let displayed_room_ids = displayed_room_ids.read();
|
let displayed_room_ids = displayed_room_ids.read();
|
||||||
rooms_ref
|
rooms_ref
|
||||||
.values()
|
.values()
|
||||||
.filter(|room| displayed_room_ids.contains(&room.borrow().id()))
|
.filter(|room| displayed_room_ids.contains(room.borrow().id()))
|
||||||
.map(|room| {
|
.map(|room| {
|
||||||
let room = room.borrow();
|
let room = room.borrow();
|
||||||
let room_name = room.name().unwrap_or(room.id().to_string());
|
let room_name = match room.name() {
|
||||||
|
Some(room_name) => room_name.clone(),
|
||||||
|
None => room.id().to_string(),
|
||||||
|
};
|
||||||
rsx!(
|
rsx!(
|
||||||
div {
|
div {
|
||||||
class: ClassName::TAB,
|
class: ClassName::TAB,
|
||||||
@@ -62,10 +66,13 @@ fn render_rooms_conversations(
|
|||||||
let displayed_room_ids = displayed_room_ids.read();
|
let displayed_room_ids = displayed_room_ids.read();
|
||||||
rooms_ref
|
rooms_ref
|
||||||
.values()
|
.values()
|
||||||
.filter(|room| displayed_room_ids.contains(&room.borrow().id()))
|
.filter(|room| displayed_room_ids.contains(room.borrow().id()))
|
||||||
.map(|room| {
|
.map(|room| {
|
||||||
let room_id = room.borrow().id();
|
let room = room.borrow();
|
||||||
rsx!(Conversation { room_id: room_id },)
|
let room_id = room.id();
|
||||||
|
rsx!(Conversation {
|
||||||
|
room_id: room_id.clone()
|
||||||
|
},)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
turf::style_sheet!("src/ui/components/chats_window/navbar.scss");
|
turf::style_sheet!("src/ui/components/chats_window/navbar.scss");
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::ui::components::contacts_window::contacts_section::{
|
use crate::ui::components::contacts_window::contacts_section::{
|
||||||
filter_people_conversations, filter_room_conversations, ContactsSection,
|
filter_people_conversations, filter_room_conversations, ContactsSection,
|
||||||
|
@@ -4,10 +4,10 @@ use std::rc::Rc;
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
||||||
use dioxus_free_icons::Icon;
|
use dioxus_free_icons::Icon;
|
||||||
use matrix_sdk::{ruma::OwnedRoomId, RoomState};
|
use log::debug;
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use crate::base::{ByIdRooms, Room, CHATS_WIN_INTERFACE, ROOMS};
|
use crate::base::{CHATS_WIN_INTERFACE, ROOMS};
|
||||||
|
use crate::domain::model::room::{ByIdRooms, Room, RoomId};
|
||||||
use crate::ui::components::chats_window::interface::Interface as ChatsWindowInterface;
|
use crate::ui::components::chats_window::interface::Interface as ChatsWindowInterface;
|
||||||
|
|
||||||
turf::style_sheet!("src/ui/components/contacts_window/contacts_section.scss");
|
turf::style_sheet!("src/ui/components/contacts_window/contacts_section.scss");
|
||||||
@@ -32,7 +32,7 @@ pub(super) fn filter_people_conversations(
|
|||||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
||||||
|
|
||||||
for room in by_id_rooms.values() {
|
for room in by_id_rooms.values() {
|
||||||
let is_direct = room.borrow().is_direct.unwrap();
|
let is_direct = room.borrow().is_direct().unwrap();
|
||||||
if !is_direct {
|
if !is_direct {
|
||||||
filtered_rooms.push(room.to_owned());
|
filtered_rooms.push(room.to_owned());
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ pub(super) fn filter_room_conversations(
|
|||||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
||||||
|
|
||||||
for room in by_id_rooms.values() {
|
for room in by_id_rooms.values() {
|
||||||
let is_direct = room.borrow().is_direct.unwrap();
|
let is_direct = room.borrow().is_direct().unwrap();
|
||||||
if is_direct {
|
if is_direct {
|
||||||
filtered_rooms.push(room.to_owned());
|
filtered_rooms.push(room.to_owned());
|
||||||
}
|
}
|
||||||
@@ -57,10 +57,7 @@ pub(super) fn filter_room_conversations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle errors
|
// TODO: Handle errors
|
||||||
fn on_clicked_room(
|
fn on_clicked_room(room_id: &RoomId, chats_window_interface: &GlobalSignal<ChatsWindowInterface>) {
|
||||||
room_id: &OwnedRoomId,
|
|
||||||
chats_window_interface: &GlobalSignal<ChatsWindowInterface>,
|
|
||||||
) {
|
|
||||||
let _ = chats_window_interface.read().toggle_room(room_id.clone());
|
let _ = chats_window_interface.read().toggle_room(room_id.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,22 +86,19 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element {
|
|||||||
]
|
]
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
let rendered_contacts = contacts.into_iter().map(|room_ref| {
|
let rendered_contacts = contacts.into_iter().map(|room| {
|
||||||
let room = room_ref.borrow();
|
let room = room.borrow();
|
||||||
|
|
||||||
let room_topic = room
|
let topic = room.topic().clone().unwrap_or("".to_string());
|
||||||
.topic
|
let name = match room.name() {
|
||||||
.as_ref()
|
Some(name) => name.clone(),
|
||||||
.unwrap_or(&RefCell::new(NO_SUBJECT_REPR.to_string()))
|
None => NO_NAME_REPR.to_string(),
|
||||||
.borrow()
|
};
|
||||||
.to_owned();
|
let id = room.id().clone();
|
||||||
let room_name = room.name().unwrap_or(NO_NAME_REPR.to_string());
|
let is_invited = room.is_invited().unwrap_or(false);
|
||||||
let room_id = room.id();
|
|
||||||
|
|
||||||
let is_invited = room.matrix_room.state() == RoomState::Invited;
|
|
||||||
|
|
||||||
let formatted = format!(
|
let formatted = format!(
|
||||||
"{room_name} - {}",
|
"{name} - {}",
|
||||||
if is_invited {
|
if is_invited {
|
||||||
"Invited - ".to_string()
|
"Invited - ".to_string()
|
||||||
} else {
|
} else {
|
||||||
@@ -114,7 +108,7 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element {
|
|||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
li {
|
li {
|
||||||
onclick: move |_| on_clicked_room(&room_id, &CHATS_WIN_INTERFACE),
|
onclick: move |_| on_clicked_room(&id, &CHATS_WIN_INTERFACE),
|
||||||
img {
|
img {
|
||||||
src: "./images/status_online.png",
|
src: "./images/status_online.png",
|
||||||
},
|
},
|
||||||
@@ -123,7 +117,7 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element {
|
|||||||
},
|
},
|
||||||
p {
|
p {
|
||||||
style: "color: darkgrey;",
|
style: "color: darkgrey;",
|
||||||
{room_topic},
|
{topic},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ mod contacts_section;
|
|||||||
mod user_infos;
|
mod user_infos;
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::ui::components::contacts_window::contacts::Contacts;
|
use crate::ui::components::contacts_window::contacts::Contacts;
|
||||||
use crate::ui::components::contacts_window::user_infos::UserInfos;
|
use crate::ui::components::contacts_window::user_infos::UserInfos;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::ui::components::avatar_selector::AvatarSelector;
|
use crate::ui::components::avatar_selector::AvatarSelector;
|
||||||
use crate::ui::components::icons::DownArrowIcon;
|
use crate::ui::components::icons::DownArrowIcon;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
use super::spinner::Spinner;
|
use super::spinner::Spinner;
|
||||||
use super::wallpaper::Wallpaper;
|
use super::wallpaper::Wallpaper;
|
||||||
|
@@ -5,11 +5,12 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use const_format::formatcp;
|
use const_format::formatcp;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
use validator::{Validate, ValidateArgs, ValidateEmail, ValidationError, ValidationErrors};
|
use validator::{Validate, ValidateArgs, ValidateEmail, ValidationError, ValidationErrors};
|
||||||
use zxcvbn::zxcvbn;
|
use zxcvbn::zxcvbn;
|
||||||
|
|
||||||
use crate::base::{Session, SESSION};
|
use crate::base::SESSION;
|
||||||
|
use crate::domain::model::session::Session;
|
||||||
use crate::infrastructure::services::random_svg_generators::{
|
use crate::infrastructure::services::random_svg_generators::{
|
||||||
generate_random_svg_shape, ShapeConfig,
|
generate_random_svg_shape, ShapeConfig,
|
||||||
};
|
};
|
||||||
@@ -653,8 +654,6 @@ pub fn Login() -> Element {
|
|||||||
let field_errors = errors.field_errors();
|
let field_errors = errors.field_errors();
|
||||||
on_validation_errors(&field_errors, &handlers);
|
on_validation_errors(&field_errors, &handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
spinner_animated.set(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use tracing::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::base::SESSION;
|
use crate::base::SESSION;
|
||||||
use crate::ui::components::contacts_window::ContactsWindow;
|
use crate::ui::components::contacts_window::ContactsWindow;
|
||||||
|
@@ -68,7 +68,7 @@ $modal-max-height: 55vh;
|
|||||||
|
|
||||||
&__placeholder {
|
&__placeholder {
|
||||||
width: calc(100% + (2 * $border-normal-width));
|
width: calc(100% + (2 * $border-normal-width));
|
||||||
height: calc(100% - (2 * $border-normal-width));
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
|
Reference in New Issue
Block a user