96 lines
2.8 KiB
Rust
96 lines
2.8 KiB
Rust
use std::time::Duration;
|
|
|
|
use feshared::{chatmessage::TauriCommand, daemon::DaemonState};
|
|
use leptos::{prelude::*, reactive::spawn_local};
|
|
use leptos_router::{
|
|
components::{Route, Router, Routes},
|
|
path,
|
|
};
|
|
use wasm_bindgen::JsValue;
|
|
|
|
use crate::popup::PopupView;
|
|
use crate::{bridge::invoke, components::DarkModeToggle};
|
|
use crate::{
|
|
bridge::invoke_typed,
|
|
components::{DaemonProvider, ThemeProvider},
|
|
};
|
|
|
|
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! {
|
|
<Router>
|
|
<Routes fallback=|| view! { "Page not found."}>
|
|
<Route path=path!("/") view=Dashboard />
|
|
<Route path=path!("/popup") view=PopupView />
|
|
</Routes>
|
|
</Router>
|
|
}
|
|
}
|
|
|
|
#[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(TauriCommand::TogglePopup.as_str(), empty_args).await;
|
|
});
|
|
};
|
|
view! {
|
|
<ThemeProvider>
|
|
<DaemonProvider>
|
|
<div class="min-h-screen w-screen bg-white dark:bg-zinc-900 text-gray-950 dark:text-white">
|
|
<button class=BTN_PRIMARY on:click=on_click>Open chat</button>
|
|
</div>
|
|
</DaemonProvider>
|
|
<div class="fixed bottom-0 right-0 p-2">
|
|
<DarkModeToggle />
|
|
</div>
|
|
</ThemeProvider>
|
|
}
|
|
}
|
|
|
|
#[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 s: DaemonState = invoke_typed(TauriCommand::DaemonState, JsValue::NULL).await;
|
|
s
|
|
});
|
|
|
|
let f = |state: Option<DaemonState>| {
|
|
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! {
|
|
<div class="flex">
|
|
<div class={format!("mt-1 h-4 w-4 rounded-full flex-none {color}")}></div>
|
|
<span class="ml-2 flex-none text-gray-400 dark:text-gray-600">{ text }</span>
|
|
</div>
|
|
}
|
|
};
|
|
|
|
view! {
|
|
<div>
|
|
{move || f(status.get())}
|
|
</div>
|
|
}
|
|
}
|