use std::time::Duration;
use feshared::daemon::DaemonState;
use leptos::logging::log;
use leptos::{prelude::*, reactive::spawn_local};
use leptos_router::{
components::{Route, Router, Routes},
path,
};
use serde::{Deserialize, Serialize};
use wasm_bindgen::{prelude::Closure, JsValue};
use crate::bridge::{invoke, listen};
use crate::popup::PopupView;
pub const BTN_PRIMARY: &str = "bg-slate-300 hover:bg-slate-400 dark:bg-slate-800 hover:dark-bg-slate-700 px-4 py-2 rounded-md";
#[component]
pub fn App() -> impl IntoView {
view! {
}
}
#[component]
fn Dashboard() -> impl IntoView {
let on_click = move |_ev: leptos::ev::MouseEvent| {
spawn_local(async move {
let empty_args = serde_wasm_bindgen::to_value(&serde_json::json!({})).unwrap();
invoke("toggle_popup", empty_args).await;
});
};
let toggle_dark_mode = |_ev: leptos::ev::MouseEvent| {
spawn_local(async {
let _ = invoke("toggle_dark_mode", JsValue::UNDEFINED).await;
});
};
view! {
}
}
#[component]
pub fn DarkModeToggle() -> impl IntoView {
let toggle_dark_mode = |_ev: leptos::ev::MouseEvent| {
spawn_local(async {
let _ = invoke("toggle_dark_mode", JsValue::UNDEFINED).await;
});
};
view! {
}
}
#[component]
pub fn DaemonStatusIndicator() -> impl IntoView {
let (poll_count, set_pool_count) = signal(0);
set_interval(
move || set_pool_count.update(|v| *v += 1),
Duration::from_secs(1),
);
let status = LocalResource::new(move || async move {
poll_count.get();
let val = invoke("daemon_state", JsValue::NULL).await;
let s: DaemonState = serde_wasm_bindgen::from_value(val).unwrap();
s
});
let f = |state: Option| {
let color = match state.clone() {
Some(s) => match s.is_ok {
true => "bg-green-600",
false => "bg-red-600",
},
None => "bg-yellow-600",
};
let text = match state {
Some(s) => match s.error {
Some(err) => err,
None => s.message.unwrap_or(String::from("")),
},
None => String::from("Loading..."),
};
view! {
}
};
view! {
{move || f(status.get())}
}
}
#[component]
pub fn DaemonProvider(children: ChildrenFn) -> impl IntoView {
let (poll_count, set_pool_count) = signal(0);
set_interval(
move || set_pool_count.update(|v| *v += 1),
Duration::from_secs(1),
);
let status_res = LocalResource::new(move || async move {
poll_count.get();
let val = invoke("daemon_state", JsValue::NULL).await;
let s: DaemonState = serde_wasm_bindgen::from_value(val).unwrap();
s
});
let is_daemon_ok = Memo::new(move |_| status_res.get().map(|s| (s.is_ok, s.error)));
provide_context(status_res);
move || match is_daemon_ok.get() {
Some((true, _)) => children().into_any(),
Some((false, err)) => view! { }.into_any(),
None => view! { Connecting...
}.into_any(),
}
}
#[component]
fn DaemonErrorStatus(error: Option) -> impl IntoView {
view! {
{ error.unwrap_or("Daemon error!".to_string()) }
}
}
#[derive(Deserialize, Serialize, Clone)]
struct DarkMode {
is_dark_mode: bool,
}
#[component]
pub fn ThemeProvider(children: Children) -> impl IntoView {
let (is_dark, set_dark) = signal(false);
Effect::new(move |_| {
spawn_local(async move {
let handler = Closure::wrap(Box::new(move |evt: JsValue| {
log!("Received!!!");
#[derive(Deserialize)]
struct TauriEvent {
payload: T,
}
if let Ok(wrapper) = serde_wasm_bindgen::from_value::>(evt) {
set_dark.set(wrapper.payload.is_dark_mode);
}
}) as Box);
let unlisten = listen("dark-mode-changed", &handler).await;
// TODO use on_cleanup to call the unlisten JS function.
handler.forget()
});
});
Effect::new(move |_| {
let el = document()
.document_element()
.expect("HTML element not found!");
if is_dark.get() {
let _ = el.set_attribute("class", "dark");
} else {
let _ = el.set_attribute("class", "");
}
});
view! {
{children()}
}
}