daydream

A small matrix web client written in rust
git clone git://archive.git.mtrnord.blog/daydream-mx/daydream.git
Log | Files | Refs | README | LICENSE

commit 08043c7675856803b5a0976a71effc84edc246de
parent d14a8be9394e9c32f1c847663b5f8ec7cdf28c2d
Author: Marcel <mtrnord1@gmail.com>
Date:   Wed, 27 May 2020 01:54:43 +0200

Add unread badges

Took 18 minutes

Diffstat:
MCargo.toml | 1+
Msrc/app/matrix.rs | 23++++++++++++++---------
Msrc/app/matrix/sync.rs | 17+++++++++++------
Msrc/app/matrix/types.rs | 7+++++--
Msrc/app/views/main_view.rs | 51++++++++++++++++++++++++++++++++-------------------
Mstatic/style.scss | 4++++
6 files changed, 67 insertions(+), 36 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -30,6 +30,7 @@ url = "2.1.1" yew_styles = "0.3.1" thiserror = "1.0" futures-locks = { git = "https://github.com/asomers/futures-locks", default-features = false } +js_int = "0.1.5" [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/src/app/matrix.rs b/src/app/matrix.rs @@ -1,10 +1,9 @@ -use std::collections::{HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::sync::{Arc, Mutex}; -use std::sync::RwLock as SyncRwLock; use log::*; -use matrix_sdk::{Client, ClientConfig, Session, SyncSettings, Room, identifiers::RoomId}; +use matrix_sdk::{identifiers::RoomId, Client, ClientConfig, Room, Session}; use serde::{Deserialize, Serialize}; use url::Url; use wasm_bindgen_futures::spawn_local; @@ -12,11 +11,10 @@ use yew::format::Json; use yew::services::{storage::Area, StorageService}; use yew::worker::*; +use crate::app::matrix::types::{MessageWrapper, SmallRoom}; use crate::constants::AUTH_KEY; use crate::errors::MatrixError; use futures_locks::RwLock; -use crate::app::matrix::types::{SmallRoom, MessageWrapper}; -use yew_styles::button::Size::Small; mod sync; pub mod types; @@ -137,7 +135,7 @@ impl Agent for MatrixAgent { user_id: matrix_sdk::identifiers::UserId::try_from( stored_session.user_id.as_str(), ) - .unwrap(), + .unwrap(), device_id: stored_session.device_id, }; client.restore_login(session).await; @@ -206,14 +204,21 @@ impl Agent for MatrixAgent { let client = agent.matrix_client.clone().unwrap(); spawn_local(async move { for sub in agent.subscribers.iter() { - let rooms: Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> = client.clone().joined_rooms(); + let rooms: Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>> = + client.clone().joined_rooms(); let mut rooms_list_hack = HashMap::new(); for (id, room) in rooms.read().await.iter() { let small_room = SmallRoom { name: room.read().await.display_name(), - id: id.clone() + unread_notifications: room + .read() + .await + .unread_notifications + .clone(), + unread_highlight: room.read().await.unread_highlight.clone(), + id: id.clone(), }; - rooms_list_hack.insert(id.clone(),small_room); + rooms_list_hack.insert(id.clone(), small_room); } let resp = Response::JoinedRoomList(rooms_list_hack); diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs @@ -1,7 +1,13 @@ +use crate::app::matrix::types::MessageWrapper; use crate::app::matrix::Response; use log::*; -use matrix_sdk::{api::r0::sync::sync_events::Response as SyncResponse, events::collections::all::RoomEvent, events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, identifiers::RoomId, Client, SyncSettings, Error}; -use crate::app::matrix::types::MessageWrapper; +use matrix_sdk::{ + api::r0::sync::sync_events::Response as SyncResponse, + events::collections::all::RoomEvent, + events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, + identifiers::RoomId, + Client, SyncSettings, +}; pub struct Sync<F> where @@ -22,8 +28,8 @@ where Ok(_) => { let resp = Response::FinishedFirstSync; (self.callback)(resp); - }, - _ => {}, + } + _ => {} } let settings = SyncSettings::default().token(client.clone().sync_token().await.unwrap()); @@ -34,7 +40,6 @@ where } async fn on_sync_response(&self, response: SyncResponse) { - for (room_id, room) in response.rooms.join { for event in room.timeline.events { if let Ok(event) = event.deserialize() { @@ -58,7 +63,7 @@ where let wrapper = MessageWrapper { room_id: room_id.clone(), - content: msg_body + content: msg_body, }; let resp = Response::Sync(wrapper); diff --git a/src/app/matrix/types.rs b/src/app/matrix/types.rs @@ -1,10 +1,13 @@ +use js_int::UInt; use matrix_sdk::identifiers::RoomId; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SmallRoom { pub(crate) name: String, - pub(crate) id: RoomId + pub(crate) unread_notifications: Option<UInt>, + pub(crate) unread_highlight: Option<UInt>, + pub(crate) id: RoomId, } #[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)] diff --git a/src/app/views/main_view.rs b/src/app/views/main_view.rs @@ -1,16 +1,15 @@ +use std::collections::{HashMap, HashSet}; +use std::convert::TryFrom; + +use js_int::UInt; use log::*; +use matrix_sdk::identifiers::RoomId; use serde::{Deserialize, Serialize}; use yew::prelude::*; use yew::ComponentLink; +use crate::app::matrix::types::{MessageWrapper, SmallRoom}; use crate::app::matrix::{MatrixAgent, Request, Response}; -use std::collections::{HashSet, HashMap}; -use matrix_sdk::{Client, ClientConfig, Session}; -use url::Url; -use std::convert::TryFrom; -use wasm_bindgen_futures::spawn_local; -use crate::app::matrix::types::{SmallRoom, MessageWrapper}; -use matrix_sdk::identifiers::RoomId; pub struct MainView { link: ComponentLink<Self>, @@ -20,7 +19,7 @@ pub struct MainView { pub enum Msg { NewMessage(Response), - ChangeRoom(String) + ChangeRoom(String), } #[derive(Serialize, Deserialize, Default)] @@ -28,7 +27,7 @@ pub struct State { // TODO handle all events pub events: HashSet<MessageWrapper>, pub rooms: HashMap<RoomId, SmallRoom>, - pub current_room: Option<RoomId> + pub current_room: Option<RoomId>, } impl Component for MainView { @@ -42,7 +41,7 @@ impl Component for MainView { let state = State { events: Default::default(), rooms: Default::default(), - current_room: None + current_room: None, }; MainView { @@ -63,15 +62,12 @@ impl Component for MainView { // TODO handle all events self.state.events.insert(msg); } - Response::JoinedRoomList(rooms) => { - self.state.rooms = rooms - } + Response::JoinedRoomList(rooms) => self.state.rooms = rooms, _ => {} } } Msg::ChangeRoom(room) => { self.state.current_room = Some(RoomId::try_from(room).unwrap()); - } } true @@ -99,7 +95,7 @@ impl Component for MainView { </div> </div> </div> - } + }; } else { return html! { <div class="uk-flex uk-height-1-1 non-scrollable-container"> @@ -117,9 +113,8 @@ impl Component for MainView { </div> </div> </div> - } + }; } - } else { return html! { <div class="container"> @@ -127,7 +122,7 @@ impl Component for MainView { <span uk-spinner="ratio: 4.5"></span> </div> </div> - } + }; } } } @@ -144,7 +139,25 @@ impl MainView { let room_id = room.clone().id.to_string(); html! { - <li><a href="#" onclick=self.link.callback(move |e: MouseEvent| Msg::ChangeRoom(room_id.clone()))>{room.name.clone()}</a></li> + <li> + <a href="#" onclick=self.link.callback(move |e: MouseEvent| Msg::ChangeRoom(room_id.clone()))> + {room.name.clone()} + { + if room.unread_notifications.is_some() && room.unread_notifications.unwrap() != UInt::from(0u32) { + html! { <span class="uk-badge uk-margin-small-left">{room.unread_notifications.unwrap()}</span> } + } else { + html! {} + } + } + { + if room.unread_highlight.is_some() && room.unread_highlight.unwrap() != UInt::from(0u32) { + html! { <span class="uk-badge red uk-margin-small-left">{room.unread_highlight.unwrap()}</span> } + } else { + html! {} + } + } + </a> + </li> } } } diff --git a/static/style.scss b/static/style.scss @@ -8,6 +8,10 @@ overflow: hidden; } +.uk-badge.red { + background: #f0506e; +} + .h-100 { height: 100% !important; }