mirror of
https://gitea.mizah.xyz/mizah/dergchat
synced 2024-11-21 05:44:59 -05:00
Add message timestamps and room sorting capability
This commit is contained in:
parent
d11daee5df
commit
53ad01ed41
56
Cargo.lock
generated
56
Cargo.lock
generated
@ -38,6 +38,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
@ -455,6 +470,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
name = "chatclient"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"confy",
|
||||
"dioxus",
|
||||
"dioxus-desktop",
|
||||
@ -475,7 +491,12 @@ version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1748,6 +1769,29 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@ -4301,6 +4345,15 @@ dependencies = [
|
||||
"windows-tokens",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.44.0"
|
||||
@ -4625,8 +4678,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "xmpp"
|
||||
version = "0.5.0"
|
||||
source = "git+https://gitlab.com/xmpp-rs/xmpp-rs.git?rev=2b433d7036209f35ff7daf033a7b7692e58ab6c3#2b433d7036209f35ff7daf033a7b7692e58ab6c3"
|
||||
source = "git+https://gitlab.com/werner.kroneman/xmpp-rs.git?rev=b75e0047837c33eb0cd9c405c859e46be4f4bc09#b75e0047837c33eb0cd9c405c859e46be4f4bc09"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
"log",
|
||||
"reqwest",
|
||||
|
@ -28,9 +28,10 @@ env_logger = "0.10.1"
|
||||
dioxus="0.4.3"
|
||||
dioxus-desktop="0.4.3"
|
||||
futures-util = "0.3.29"
|
||||
xmpp = { git = "https://gitlab.com/xmpp-rs/xmpp-rs.git", rev="2b433d7036209f35ff7daf033a7b7692e58ab6c3" }
|
||||
xmpp = { git = "https://gitlab.com/werner.kroneman/xmpp-rs.git", rev="b75e0047837c33eb0cd9c405c859e46be4f4bc09" }
|
||||
keyring = "2.1.0"
|
||||
jid = { version = "0.10.0", features = ["serde"] }
|
||||
confy = "0.5.1"
|
||||
serde = "1.0.193"
|
||||
serde_derive = "1.0"
|
||||
chrono="0.4.31"
|
@ -17,6 +17,7 @@
|
||||
use crate::passwords::Password;
|
||||
use jid::BareJid;
|
||||
use std::fmt::Debug;
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Room {
|
||||
@ -27,6 +28,7 @@ pub struct Room {
|
||||
pub struct Message {
|
||||
pub sender: String,
|
||||
pub body: String,
|
||||
pub timestamp: DateTime<FixedOffset>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -24,6 +24,7 @@ use crate::{
|
||||
no_room_open::NoRoomPlaceholder,
|
||||
room_view::RoomView,
|
||||
sidebar::SideBar,
|
||||
room_list::RoomMeta,
|
||||
},
|
||||
xmpp_interface,
|
||||
xmpp_interface::NetworkCommand,
|
||||
@ -83,7 +84,12 @@ pub fn App(cx: Scope) -> Element {
|
||||
// Sidebar.
|
||||
SideBar {
|
||||
current_user: user.clone(),
|
||||
rooms: messages.read().keys().cloned().collect(),
|
||||
rooms: messages.read().iter().map(|(k, v)| {
|
||||
RoomMeta {
|
||||
room: k.clone(),
|
||||
last_update_time: v.last().map(|x| x.timestamp),
|
||||
}
|
||||
}).collect(),
|
||||
on_room_picked: move |x: BareJid| {
|
||||
current_room.set(Some(x.clone()));
|
||||
coroutine.send(NetworkCommand::JoinRoom { room: x });
|
||||
|
@ -14,20 +14,24 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::time::Instant;
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use dioxus::core::{Element, Scope};
|
||||
use dioxus::core_macro::Props;
|
||||
use dioxus::html::button;
|
||||
use dioxus::prelude::*;
|
||||
use jid::BareJid;
|
||||
|
||||
/// The props for the room list widget, including:
|
||||
/// * The list of rooms to show.
|
||||
/// * The event handler for when the user clicks a room.
|
||||
/// * The event handler for when the user clicks the "leave" button for a room.
|
||||
#[derive(Props)]
|
||||
pub struct RoomListProps<'a> {
|
||||
rooms: Vec<BareJid>, // TODO: Should this be a reference of some kind?
|
||||
on_room_picked: EventHandler<'a, BareJid>,
|
||||
on_room_left: EventHandler<'a, BareJid>,
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct RoomMeta {
|
||||
pub room: BareJid,
|
||||
pub last_update_time: Option<DateTime<FixedOffset>>
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Copy)]
|
||||
pub enum SortMethod {
|
||||
Alphabetical,
|
||||
Recency,
|
||||
}
|
||||
|
||||
/// A widget that shows a list of rooms known to the client.
|
||||
@ -36,8 +40,41 @@ pub struct RoomListProps<'a> {
|
||||
/// select a room or to leave it.
|
||||
///
|
||||
/// How "selecting" and "leaving" a room is handled is up to the context.
|
||||
pub fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||
#[component]
|
||||
pub fn RoomList<'a>(cx: Scope<'a>,
|
||||
rooms: Vec<RoomMeta>, // TODO: Should this be a reference of some kind?
|
||||
on_room_picked: EventHandler<'a, BareJid>,
|
||||
on_room_left: EventHandler<'a, BareJid>) -> Element<'a> {
|
||||
|
||||
|
||||
let sort_method = use_state(cx, || SortMethod::Recency);
|
||||
|
||||
let sorted_rooms = use_memo(cx, (rooms,sort_method), |(mut rooms, sort_method)| {
|
||||
|
||||
match *sort_method.current() {
|
||||
SortMethod::Alphabetical => rooms.sort_by_key(|room| room.room.to_string()),
|
||||
SortMethod::Recency => rooms.sort_by_key(|room| room.last_update_time),
|
||||
}
|
||||
|
||||
rooms
|
||||
});
|
||||
|
||||
render! {
|
||||
|
||||
button {
|
||||
onclick: move |_| {
|
||||
match *sort_method.current() {
|
||||
SortMethod::Alphabetical => sort_method.set(SortMethod::Recency),
|
||||
SortMethod::Recency => sort_method.set(SortMethod::Alphabetical),
|
||||
}
|
||||
},
|
||||
"Sort by: ",
|
||||
match *sort_method.current() {
|
||||
SortMethod::Alphabetical => "alphabetical",
|
||||
SortMethod::Recency => "recency",
|
||||
}
|
||||
}
|
||||
|
||||
// An <ul> with a list of <li> elements, each containing a room name and a button.
|
||||
ul {
|
||||
list_style: "none",
|
||||
@ -51,12 +88,12 @@ pub fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||
display: "flex",
|
||||
flex_direction: "row",
|
||||
|
||||
onclick: |_evt| cx.props.on_room_picked.call(room.to_owned()),
|
||||
onclick: |_evt| cx.props.on_room_picked.call(room.room.clone()),
|
||||
|
||||
// The room name inside a <div>.
|
||||
div {
|
||||
flex_grow: 1,
|
||||
"{room}"
|
||||
"{room.room}"
|
||||
}
|
||||
|
||||
// A button to leave the room.
|
||||
@ -64,7 +101,7 @@ pub fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||
|
||||
onclick: |evt| {
|
||||
evt.stop_propagation();
|
||||
cx.props.on_room_left.call(room.to_owned());
|
||||
cx.props.on_room_left.call(room.room.clone());
|
||||
},
|
||||
"X"
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::widgets::room_join_widget::RoomJoinWidget;
|
||||
use crate::widgets::room_list::RoomList;
|
||||
use crate::widgets::room_list::{RoomList, RoomMeta};
|
||||
use dioxus::core::{Element, Scope};
|
||||
use dioxus::core_macro::Props;
|
||||
use dioxus::html::text;
|
||||
@ -26,7 +26,7 @@ use jid::BareJid;
|
||||
#[component]
|
||||
pub fn SideBar<'a>(cx: Scope<'a, SideBarProps>,
|
||||
current_user: BareJid,
|
||||
rooms: Vec<BareJid>,
|
||||
rooms: Vec<RoomMeta>,
|
||||
on_room_picked: EventHandler<'a, BareJid>,
|
||||
on_room_left: EventHandler<'a, BareJid>,
|
||||
on_join_room: EventHandler<'a, BareJid>,
|
||||
|
@ -21,6 +21,7 @@ use jid::BareJid;
|
||||
use log::{error, info};
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::widgets::login_screen::LoginStatus;
|
||||
use tokio::select;
|
||||
@ -69,16 +70,17 @@ async fn handle_event(
|
||||
m.remove(&room_jid);
|
||||
});
|
||||
}
|
||||
xmpp::Event::ChatMessage(_id, sender, body) => {
|
||||
xmpp::Event::ChatMessage(_id, sender, body, timestamp) => {
|
||||
println!("Message from {}: {}", &sender, &body.0);
|
||||
messages.with_mut(move |m| {
|
||||
m.entry(sender.clone()).or_insert(vec![]).push(Message {
|
||||
sender: sender.to_string(),
|
||||
body: body.0,
|
||||
timestamp,
|
||||
});
|
||||
});
|
||||
}
|
||||
xmpp::Event::RoomMessage(_id, room_jid, sender_nick, body) => {
|
||||
xmpp::Event::RoomMessage(_id, room_jid, sender_nick, body, timestamp) => {
|
||||
println!(
|
||||
"Message in {} from {}: {}",
|
||||
&room_jid, &sender_nick, &body.0
|
||||
@ -87,10 +89,11 @@ async fn handle_event(
|
||||
m.entry(room_jid.clone()).or_insert(vec![]).push(Message {
|
||||
sender: sender_nick,
|
||||
body: body.0,
|
||||
timestamp,
|
||||
})
|
||||
});
|
||||
}
|
||||
xmpp::Event::RoomPrivateMessage(_id, room_jid, sender_nick, body) => {
|
||||
xmpp::Event::RoomPrivateMessage(_id, room_jid, sender_nick, body, timestamp) => {
|
||||
println!(
|
||||
"Private message in {} from {}: {}",
|
||||
&room_jid, &sender_nick, &body.0
|
||||
@ -99,6 +102,7 @@ async fn handle_event(
|
||||
m.entry(room_jid.clone()).or_insert(vec![]).push(Message {
|
||||
sender: sender_nick,
|
||||
body: body.0,
|
||||
timestamp,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user