Skip to content

Commit

Permalink
feat(client): Add notification
Browse files Browse the repository at this point in the history
  • Loading branch information
nazo6 committed Dec 11, 2024
1 parent 45f7f26 commit 86d6895
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 11 deletions.
1 change: 1 addition & 0 deletions tools/rktk-client/src/app/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod notification;
pub mod selector;
pub mod topbar;
83 changes: 83 additions & 0 deletions tools/rktk-client/src/app/components/notification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::time::Duration;

use dioxus::prelude::*;

#[derive(Default)]
pub enum NotificationLevel {
#[default]
Info,
Success,

Check warning on line 9 in tools/rktk-client/src/app/components/notification.rs

View workflow job for this annotation

GitHub Actions / check

variants `Success` and `Warning` are never constructed
Warning,
Error,
}

impl NotificationLevel {
fn to_class(&self) -> &str {
match self {
NotificationLevel::Info => "alert-info",
NotificationLevel::Success => "alert-success",
NotificationLevel::Warning => "alert-warning",
NotificationLevel::Error => "alert-error",
}
}
}

#[derive(Default)]
pub struct Notification {
pub title: Option<String>,
pub message: String,
pub level: NotificationLevel,
pub duration: Option<Duration>,
}

struct NotificationData {
id: usize,
record: Notification,
}

static NOTFICATIONS: GlobalSignal<Vec<NotificationData>> = GlobalSignal::new(|| vec![]);

Check warning on line 38 in tools/rktk-client/src/app/components/notification.rs

View workflow job for this annotation

GitHub Actions / check

redundant closure
static NOTIFICATION_ID: GlobalSignal<usize> = GlobalSignal::new(|| 0);

pub fn push_notification(notification: Notification) {
NOTIFICATION_ID.with_mut(|id| {
*id += 1;
});
let notification = NotificationData {
id: *NOTIFICATION_ID.read(),
record: notification,
};

spawn_forever(async move {
gloo_timers::future::TimeoutFuture::new(
notification
.record
.duration
.unwrap_or_else(|| Duration::from_secs(3))
.as_millis() as u32,
)
.await;
NOTFICATIONS.with_mut(|notifications| {
notifications.retain(|n| n.id != notification.id);
});
});

NOTFICATIONS.write().push(notification);
}

#[component]
pub fn NotificationProvider() -> Element {
rsx! {
div { class: "fixed right-10 bottom-10 flex flex-col-reverse gap-2",
for notification in NOTFICATIONS.read().iter() {
div {
class: "alert",
class: "{notification.record.level.to_class()}",
if let Some(title) = &notification.record.title {
h3 { "{title}" }
}
"{notification.record.message}"
}
}
}
}
}
12 changes: 10 additions & 2 deletions tools/rktk-client/src/app/components/topbar.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use dioxus::prelude::*;

use crate::app::{disconnect::disconnect, state::CONN};
use crate::app::{
components::notification::{push_notification, Notification, NotificationLevel},
disconnect::disconnect,
state::CONN,
};

#[component]
pub fn Topbar() -> Element {
Expand All @@ -20,7 +24,11 @@ pub fn Topbar() -> Element {
*CONN.write() = None;
}
Err(e) => {
dioxus::logger::tracing::info!("{:?}", e);
push_notification(Notification {
message: format!("Cannot disconnect from device: {:?}", e),
level: NotificationLevel::Error,
..Default::default()
});
}
}
});
Expand Down
1 change: 1 addition & 0 deletions tools/rktk-client/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn App() -> Element {
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "stylesheet", href: TAILWIND_CSS }
document::Title { "RKTK Client" }
components::notification::NotificationProvider {}
div { class: "h-full bg-base flex flex-col",
components::topbar::Topbar {}
Home {}
Expand Down
18 changes: 14 additions & 4 deletions tools/rktk-client/src/app/page/connect.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use dioxus::prelude::*;

use crate::app::state::CONN;
use crate::app::{
components::notification::{push_notification, Notification, NotificationLevel},
state::CONN,
};

#[component]
pub fn Connect() -> Element {
Expand All @@ -20,10 +23,19 @@ pub fn Connect() -> Element {
spawn(async move {
match conn::connect(hid.clone()).await {
Ok(state) => {
push_notification(Notification {
message: format!("Connected to device: {}", state.keyboard.name),
level: NotificationLevel::Info,
..Default::default()
});
*CONN.write() = Some(state);
}
Err(e) => {
dioxus::logger::tracing::info!("{:?}", e);
push_notification(Notification {
message: format!("Cannot connect to device: {:?}", e),
level: NotificationLevel::Error,
..Default::default()
});
}
}
});
Expand Down Expand Up @@ -75,8 +87,6 @@ mod conn {

let client = Client::new(&device);

web_sys::console::log_1(&device);

let keyboard = client
.client
.lock()
Expand Down
13 changes: 12 additions & 1 deletion tools/rktk-client/src/app/page/connected/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use dioxus::prelude::*;
use rktk_keymanager::state::config::StateConfig;

use crate::app::components::notification::{push_notification, Notification, NotificationLevel};

#[component]
pub fn Config() -> Element {
let mut config_res = use_resource(fetcher::get_config);
Expand Down Expand Up @@ -96,8 +98,17 @@ pub fn ConfigInner(initial_config: StateConfig, refetch: Callback<()>) -> Elemen
spawn(async move {
let result = fetcher::set_config(config).await;
if let Err(e) = result {
dioxus::logger::tracing::error!("{:?}", e);
push_notification(Notification {
message: format!("Could not set config: {:?}", e),
level: NotificationLevel::Error,
..Default::default()
});
} else {
push_notification(Notification {
message: "Config updated".to_string(),
level: NotificationLevel::Info,
..Default::default()
});
refetch(());
}
});
Expand Down
29 changes: 25 additions & 4 deletions tools/rktk-client/src/app/page/connected/remap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ use dioxus::prelude::*;
use fetcher::KeymapData;
use rktk_rrp::endpoints::{get_keyboard_info::KeyboardInfo, rktk_keymanager::keycode::KeyAction};

use crate::app::{components::selector::key_action::KeyActionSelector, state::CONN};
use crate::app::{
components::{
notification::{push_notification, Notification, NotificationLevel},
selector::key_action::KeyActionSelector,
},
state::CONN,
};

mod bar;
mod fetcher;
Expand Down Expand Up @@ -47,11 +53,12 @@ pub fn Remap() -> Element {
}
}
Some((Err(e), _)) => {
dioxus::logger::tracing::error!("{:?}", e);
rsx! {
div {
h1 { "Error" }
p { "Failed to load keymap" }
p { "{e:?}" }

}
}
}
Expand All @@ -72,8 +79,22 @@ pub fn RemapInner(keyboard: KeyboardInfo, keymap: KeymapData, refetch: Callback<
changes: keymap_changes.read().clone(),
apply: Callback::new(move |_| {
spawn(async move {
if fetcher::set_keymap(&keymap_changes.read()).await.is_ok() {
refetch(());
match fetcher::set_keymap(&keymap_changes.read()).await {
Ok(_) => {
push_notification(Notification {
message: "Keymap updated".to_string(),
level: NotificationLevel::Info,
..Default::default()
});
refetch(())
}
Err(e) => {
push_notification(Notification {
message: format!("Cannot connect to device: {:?}", e),
level: NotificationLevel::Error,
..Default::default()
});
}
}
});
}),
Expand Down

0 comments on commit 86d6895

Please sign in to comment.