diff --git a/Cargo.lock b/Cargo.lock index deb8862..e626722 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1185,6 +1185,7 @@ version = "0.1.0" dependencies = [ "anyhow", "console_log", + "gloo-timers", "js-sys", "lan_party_core", "log", diff --git a/web/Cargo.toml b/web/Cargo.toml index 8dccf32..75182c0 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -27,6 +27,6 @@ sycamore-router = "0.8.0" reqwasm = "0.5" console_log = "0.2" log = "0.4" - +gloo-timers = "0.2" diff --git a/web/dist/index.html b/web/dist/index.html index fe8688f..2653ece 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -2,11 +2,11 @@ - + LAN Party - - + + - \ No newline at end of file + \ No newline at end of file diff --git a/web/src/components/messages.rs b/web/src/components/messages.rs new file mode 100644 index 0000000..dd31d00 --- /dev/null +++ b/web/src/components/messages.rs @@ -0,0 +1,85 @@ +use gloo_timers::future::TimeoutFuture; +use log::debug; +use sycamore::{futures::spawn_local_scoped, prelude::*}; +use wasm_bindgen_futures::spawn_local; + +const MESSAGE_TIME: u32 = 5000; + +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Message { + id: usize, + title: String, + text: String, +} + +impl Message { + pub fn new(title: String, text: String) -> Self { + Self { id: 0, title, text } + } +} + +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Messenger { + counter: RcSignal, + messages: RcSignal>, +} + +impl Messenger { + pub fn add_message(&self, mut message: Message) { + message.id = *self.counter.get_untracked(); + self.counter.set(*self.counter.get_untracked() + 1); + self.messages.modify().push(message); + } + + pub fn info(&self, title: impl Into, text: impl Into) { + self.add_message(Message::new(title.into(), text.into())); + } + + pub fn remove_message(&self) { + self.messages.modify().remove(0); + } + + pub fn len(&self) -> usize { + self.messages.get_untracked().len() + } +} + +#[component] +pub fn Messages<'a, G: Html>(cx: Scope<'a>) -> View { + let messages = use_context::(cx); + + create_effect(cx, move || { + messages.messages.track(); + + if messages.len() > 0 { + spawn_local_scoped(cx, async move { + debug!("Spawn"); + TimeoutFuture::new(MESSAGE_TIME).await; + + debug!("Remove"); + messages.remove_message(); + }); + } + }); + + view! { cx, + div(class="messages") { + Keyed( + iterable=&messages.messages, + view=move |cx, message| { + view! { cx, + div(class="message") { + p(class="message-title") { + (message.title) + } + p(class="message-text") { + (message.text) + } + } + } + }, + key=|message| (message.id), + ) + } + } +} diff --git a/web/src/components/mod.rs b/web/src/components/mod.rs index 310d6e7..cf38d8a 100644 --- a/web/src/components/mod.rs +++ b/web/src/components/mod.rs @@ -1,3 +1,5 @@ +pub mod messages; + use sycamore::prelude::*; use web_sys::Event; diff --git a/web/src/main.rs b/web/src/main.rs index f0389bb..ae0923a 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -2,6 +2,7 @@ mod components; mod pages; pub mod util; +use components::messages::{Messages, Messenger}; use pages::{EventsPage, UsersPage}; use sycamore::prelude::*; use sycamore_router::{HistoryIntegration, Route, Router}; @@ -62,11 +63,32 @@ fn main() { ]; sycamore::render(move |cx| { + let messenger = Messenger::default(); + provide_context(cx, messenger); + + /* + let messages = use_context::(cx); + + spawn_local_scoped(cx, async move { + TimeoutFuture::new(1000).await; + + messages.add_message(Message::new( + "Hello there".into(), + "This is a message".into(), + )); + + TimeoutFuture::new(1000).await; + + messages.add_message(Message::new("Oh look!".into(), "Another message".into())); + }); + */ + view! { cx, Router( integration=HistoryIntegration::new(), view=|cx, route: &ReadSignal| { view! { cx, + Messages() header { Navbar(pages=pages) { diff --git a/web/src/pages/events.rs b/web/src/pages/events.rs index a324784..1fe272b 100644 --- a/web/src/pages/events.rs +++ b/web/src/pages/events.rs @@ -8,12 +8,14 @@ use reqwasm::http::Method; use sycamore::{futures::spawn_local_scoped, prelude::*}; use crate::{ - components::{Block, Button}, + components::{messages::Messenger, Block, Button}, util::api_request, }; #[component] pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View { + let messenger = use_context::(cx); + let event_spec = create_signal(cx, EventSpec::default()); let event_update = create_signal(cx, EventUpdate::default()); @@ -35,10 +37,20 @@ pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View { "/event", Some((*event_spec).get().as_ref().clone()), ) - .await - .unwrap(); - debug!("{:#?}", new_event); - events.modify().push(new_event.unwrap()); + .await; + + if let Ok(Some(new_event)) = new_event { + messenger.info( + "Added new event", + format!( + "Successfully created a new event with name \"{}\"", + new_event.name + ), + ); + events.modify().push(new_event); + } else { + messenger.info("Error when adding an event", "Unable to create a new event"); + } }); }; diff --git a/web/style.css b/web/style.css index 76294ed..57a3544 100644 --- a/web/style.css +++ b/web/style.css @@ -66,3 +66,28 @@ textarea:focus, input:focus{ body { grid-template-columns: 1fr min(60rem, 90%) 1fr; } + +.messages { + position: fixed; + z-index: 10; + top: 0.5em; + left: 0.5em; +} + +.message { + margin: 0.5em; + background-color: var(--accent); + padding: 0.5em; + border-radius: 5px; + min-width: 30em; + max-width: 30em; +} + +.message-title { + margin-top: 0; +} + +.message-text { + margin-bottom: 0; + font-size: 1rem; +}