Auto-dismiss error toasts after 10 seconds
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
pub mod card;
|
||||
pub mod summary;
|
||||
pub mod toast;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//! Auto-dismissing error toast.
|
||||
use gloo_timers::callback::Timeout;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
const TOAST_MS: u32 = 10_000;
|
||||
|
||||
/// Renders the error from `error` as a toast; hides it after `TOAST_MS`.
|
||||
/// A new error replaces the message and restarts the timer.
|
||||
pub fn toast(error: Signal<Option<String>>) -> View {
|
||||
create_effect(move || {
|
||||
if error.get_clone().is_some() {
|
||||
// Held until cleanup; dropped (cancelled) when the effect re-runs.
|
||||
let timeout = Timeout::new(TOAST_MS, move || error.set(None));
|
||||
on_cleanup(move || drop(timeout));
|
||||
}
|
||||
});
|
||||
view! {
|
||||
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use sycamore::prelude::*;
|
||||
|
||||
use crate::components::card::{card_back, card_img};
|
||||
use crate::components::summary::{hand_summary_modal, summary_rows};
|
||||
use crate::components::toast::toast;
|
||||
use crate::model::{card_label, GameView, MoveView, PlayerView, Scores, ServerMessage};
|
||||
use crate::ws::{self, GameSocket};
|
||||
|
||||
@@ -123,7 +124,7 @@ pub fn GamePage(id: String) -> View {
|
||||
|
||||
view! {
|
||||
div(class="game-page") {
|
||||
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
|
||||
(toast(error))
|
||||
(move || match game.get_clone() {
|
||||
None => {
|
||||
let status = if closed.get() {
|
||||
|
||||
@@ -3,6 +3,7 @@ use wasm_bindgen_futures::spawn_local;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
use crate::api;
|
||||
use crate::components::toast::toast;
|
||||
use crate::model::MatchesPage;
|
||||
|
||||
#[component]
|
||||
@@ -45,7 +46,7 @@ pub fn HistoryPage() -> View {
|
||||
a(href="/leaderboard") { "Leaderboard" }
|
||||
}
|
||||
h1 { "My matches" }
|
||||
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
|
||||
(toast(error))
|
||||
(move || match page.get_clone() {
|
||||
None => view! { p(class="status") { "Loading…" } },
|
||||
Some(_) if rows.get_clone().is_empty() => view! {
|
||||
|
||||
@@ -3,6 +3,7 @@ use wasm_bindgen_futures::spawn_local;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
use crate::api;
|
||||
use crate::components::toast::toast;
|
||||
use crate::model::LeaderboardPage;
|
||||
|
||||
#[component]
|
||||
@@ -24,7 +25,7 @@ pub fn LeaderboardPage() -> View {
|
||||
a(href="/history") { "My matches" }
|
||||
}
|
||||
h1 { "Leaderboard" }
|
||||
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
|
||||
(toast(error))
|
||||
(move || match page.get_clone() {
|
||||
None => view! { p(class="status") { "Loading…" } },
|
||||
Some(p) => {
|
||||
|
||||
@@ -4,6 +4,7 @@ use sycamore::prelude::*;
|
||||
use sycamore_router::navigate;
|
||||
|
||||
use crate::api;
|
||||
use crate::components::toast::toast;
|
||||
use crate::model::{GameTypeInfo, User};
|
||||
|
||||
/// Used when the game-types fetch fails: match creation must still work.
|
||||
@@ -70,7 +71,7 @@ pub fn LobbyPage() -> View {
|
||||
view! {
|
||||
div(class="lobby") {
|
||||
h1 { "Scopone scientifico" }
|
||||
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
|
||||
(toast(error))
|
||||
(move || match user.get_clone() {
|
||||
None => view! { p(class="status") { "Loading…" } },
|
||||
Some(None) => view! {
|
||||
|
||||
Reference in New Issue
Block a user