Messages
This commit is contained in:
parent
667f2c5bbf
commit
44745b252a
|
@ -1185,6 +1185,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"console_log",
|
"console_log",
|
||||||
|
"gloo-timers",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"lan_party_core",
|
"lan_party_core",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
@ -27,6 +27,6 @@ sycamore-router = "0.8.0"
|
||||||
reqwasm = "0.5"
|
reqwasm = "0.5"
|
||||||
console_log = "0.2"
|
console_log = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
gloo-timers = "0.2"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<!--<link data-trunk href="tailwind.css" rel="css">-->
|
<!--<link data-trunk href="tailwind.css" rel="css">-->
|
||||||
<link rel="stylesheet" href="/simple.min-d15f5ff500b4c62a.css">
|
<link rel="stylesheet" href="/simple.min-d15f5ff500b4c62a.css">
|
||||||
<link rel="stylesheet" href="/style-5e1a36be9e479fbe.css">
|
<link rel="stylesheet" href="/style-d252283caa890f82.css">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
|
||||||
<title>LAN Party</title>
|
<title>LAN Party</title>
|
||||||
|
|
||||||
<link rel="preload" href="/index-61979c95126900f4_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
|
<link rel="preload" href="/index-50210a46cec614af_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
|
||||||
<link rel="modulepreload" href="/index-61979c95126900f4.js"></head>
|
<link rel="modulepreload" href="/index-50210a46cec614af.js"></head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module">import init from '/index-61979c95126900f4.js';init('/index-61979c95126900f4_bg.wasm');</script></body></html>
|
<script type="module">import init from '/index-50210a46cec614af.js';init('/index-50210a46cec614af_bg.wasm');</script></body></html>
|
|
@ -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<usize>,
|
||||||
|
messages: RcSignal<Vec<Message>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<String>, text: impl Into<String>) {
|
||||||
|
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<G> {
|
||||||
|
let messages = use_context::<Messenger>(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),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub mod messages;
|
||||||
|
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use web_sys::Event;
|
use web_sys::Event;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ mod components;
|
||||||
mod pages;
|
mod pages;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
use components::messages::{Messages, Messenger};
|
||||||
use pages::{EventsPage, UsersPage};
|
use pages::{EventsPage, UsersPage};
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use sycamore_router::{HistoryIntegration, Route, Router};
|
use sycamore_router::{HistoryIntegration, Route, Router};
|
||||||
|
@ -62,11 +63,32 @@ fn main() {
|
||||||
];
|
];
|
||||||
|
|
||||||
sycamore::render(move |cx| {
|
sycamore::render(move |cx| {
|
||||||
|
let messenger = Messenger::default();
|
||||||
|
provide_context(cx, messenger);
|
||||||
|
|
||||||
|
/*
|
||||||
|
let messages = use_context::<MessagesState>(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,
|
view! { cx,
|
||||||
Router(
|
Router(
|
||||||
integration=HistoryIntegration::new(),
|
integration=HistoryIntegration::new(),
|
||||||
view=|cx, route: &ReadSignal<AppRoutes>| {
|
view=|cx, route: &ReadSignal<AppRoutes>| {
|
||||||
view! { cx,
|
view! { cx,
|
||||||
|
Messages()
|
||||||
header {
|
header {
|
||||||
Navbar(pages=pages) {
|
Navbar(pages=pages) {
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,14 @@ use reqwasm::http::Method;
|
||||||
use sycamore::{futures::spawn_local_scoped, prelude::*};
|
use sycamore::{futures::spawn_local_scoped, prelude::*};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Block, Button},
|
components::{messages::Messenger, Block, Button},
|
||||||
util::api_request,
|
util::api_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
|
pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
|
||||||
|
let messenger = use_context::<Messenger>(cx);
|
||||||
|
|
||||||
let event_spec = create_signal(cx, EventSpec::default());
|
let event_spec = create_signal(cx, EventSpec::default());
|
||||||
let event_update = create_signal(cx, EventUpdate::default());
|
let event_update = create_signal(cx, EventUpdate::default());
|
||||||
|
|
||||||
|
@ -35,10 +37,20 @@ pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
|
||||||
"/event",
|
"/event",
|
||||||
Some((*event_spec).get().as_ref().clone()),
|
Some((*event_spec).get().as_ref().clone()),
|
||||||
)
|
)
|
||||||
.await
|
.await;
|
||||||
.unwrap();
|
|
||||||
debug!("{:#?}", new_event);
|
if let Ok(Some(new_event)) = new_event {
|
||||||
events.modify().push(new_event.unwrap());
|
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");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -66,3 +66,28 @@ textarea:focus, input:focus{
|
||||||
body {
|
body {
|
||||||
grid-template-columns: 1fr min(60rem, 90%) 1fr;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue