Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions crates/web/src/components/channel_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use leptos::prelude::*;
use crate::app::WebClientHandle;
use crate::components::{
ConfirmDialog, ContextMenu, StatusDot, StatusDotBorder, StatusDotSize, TempChannelCreateForm,
VoiceControls, TEMP_DEFAULT_DAYS,
ToastStack, VoiceControls, TEMP_DEFAULT_DAYS,
};
use crate::icons;

Expand Down Expand Up @@ -185,13 +185,29 @@ pub fn ChannelSidebar(
} else if let Some(kind) = kind {
let h = handle_create.clone();
let name_owned = name.clone();
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context`
// inside the async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
match kind {
willow_state::ChannelKind::Voice => {
let _ = h.create_voice_channel(&name_owned).await;
if let Err(e) = h.create_voice_channel(&name_owned).await {
crate::handlers::warn_and_toast_with(
"create voice channel",
&e,
toasts.as_ref(),
);
}
}
_ => {
let _ = h.create_channel(&name_owned).await;
if let Err(e) = h.create_channel(&name_owned).await {
crate::handlers::warn_and_toast_with(
"create channel",
&e,
toasts.as_ref(),
);
}
}
}
});
Expand Down Expand Up @@ -658,8 +674,15 @@ pub fn ChannelSidebar(
on_confirm=Callback::new(move |_| {
if let Some(name) = pending_del_channel.get_untracked() {
let h = handle_del_confirm.clone();
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.delete_channel(&name).await;
if let Err(e) = h.delete_channel(&name).await {
crate::handlers::warn_and_toast_with(
"delete channel",
&e,
toasts.as_ref(),
);
}
});
}
set_pending_del_channel.set(None);
Expand Down Expand Up @@ -974,8 +997,18 @@ fn render_channel_row(
let channel = name_for_mute.clone();
let h = handle.clone();
let target = !is_muted.get_untracked();
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context`
// inside the async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.mutate_channel_mute(&channel, target).await;
if let Err(e) = h.mutate_channel_mute(&channel, target).await {
crate::handlers::warn_and_toast_with(
"mute channel",
&e,
toasts.as_ref(),
);
}
});
}
>
Expand Down
37 changes: 32 additions & 5 deletions crates/web/src/components/roles.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use leptos::prelude::*;

use crate::app::WebClientHandle;
use crate::components::ConfirmDialog;
use crate::components::{ConfirmDialog, ToastStack};
use crate::state::AppState;

/// List of all permission names that can be toggled on a role.
Expand Down Expand Up @@ -52,8 +52,14 @@ pub fn RoleManager(
let name = name.trim().to_string();
if !name.is_empty() {
let h = handle_create.clone();
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context` inside
// the async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.create_role(&name).await;
if let Err(e) = h.create_role(&name).await {
crate::handlers::warn_and_toast_with("create role", &e, toasts.as_ref());
}
});
}
set_new_name.set(String::new());
Expand Down Expand Up @@ -197,14 +203,21 @@ pub fn RoleManager(
let h = hp_t.clone();
let rid = rid_t.clone();
let perm = perm_toggle.clone();
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
// Names come from PERMISSION_NAMES which is
// kept in sync with willow_state::Permission;
// an unparsed name is a bug, not user input.
if let Some(parsed) =
willow_state::Permission::from_name(&perm)
{
let _ = h.set_permission(&rid, parsed, granted).await;
if let Err(e) = h.set_permission(&rid, parsed, granted).await {
crate::handlers::warn_and_toast_with(
"set permission",
&e,
toasts.as_ref(),
);
}
}
});
}
Expand Down Expand Up @@ -242,8 +255,15 @@ pub fn RoleManager(
if let Ok(eid) = pid.trim().parse::<willow_identity::EndpointId>() {
let h = ha.clone();
let r = rid.clone();
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.assign_role(eid, &r).await;
if let Err(e) = h.assign_role(eid, &r).await {
crate::handlers::warn_and_toast_with(
"assign role",
&e,
toasts.as_ref(),
);
}
});
}
set_assign_peer.set(String::new());
Expand Down Expand Up @@ -287,8 +307,15 @@ pub fn RoleManager(
on_confirm=Callback::new(move |_| {
if let Some((rid, _)) = pending_del_role.get_untracked() {
let h = handle_del_confirm.clone();
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.delete_role(&rid).await;
if let Err(e) = h.delete_role(&rid).await {
crate::handlers::warn_and_toast_with(
"delete role",
&e,
toasts.as_ref(),
);
}
});
}
set_pending_del_role.set(None);
Expand Down
22 changes: 19 additions & 3 deletions crates/web/src/components/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use leptos::prelude::*;
use willow_client::presence::{PresenceOverride, PresenceState};

use crate::app::WebClientHandle;
use crate::components::{RoleManager, StatusDot, StatusDotBorder, StatusDotSize};
use crate::components::{RoleManager, StatusDot, StatusDotBorder, StatusDotSize, ToastStack};
use crate::icons;
use crate::state::{AppState, SettingsTab};
use crate::util::copy_to_clipboard;
Expand Down Expand Up @@ -54,8 +54,18 @@ pub fn SettingsPanel(
if !name.trim().is_empty() {
let h = handle_save.clone();
let name = name.trim().to_string();
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context` inside
// the async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.set_server_display_name(&name).await;
if let Err(e) = h.set_server_display_name(&name).await {
crate::handlers::warn_and_toast_with(
"set server display name",
&e,
toasts.as_ref(),
);
}
});
}
set_status_msg.set("Saved.".to_string());
Expand Down Expand Up @@ -435,8 +445,14 @@ fn NotificationsTabPlaceholder() -> impl IntoView {
let target = !local_muted.get_untracked();
set_local_muted.set(target);
let h = handle.clone();
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context` inside
// the async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.mutate_grove_mute(target).await;
if let Err(e) = h.mutate_grove_mute(target).await {
crate::handlers::warn_and_toast_with("mute server", &e, toasts.as_ref());
}
});
}
};
Expand Down
8 changes: 7 additions & 1 deletion crates/web/src/components/sync_queue_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,14 @@ pub fn SyncQueueView() -> impl IntoView {
busy.set(false);
return;
};
// Capture toast stack on the outer reactive frame —
// `spawn_local` strips the owner so `use_context` inside the
// async block would return None.
let toasts = use_context::<ToastStack>();
wasm_bindgen_futures::spawn_local(async move {
let _ = h.retry_queue().await;
if let Err(e) = h.retry_queue().await {
crate::handlers::warn_and_toast_with("retry queue", &e, toasts.as_ref());
}
busy.set(false);
});
};
Expand Down