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:
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;
}