Files
ws-agent/frontend/src/app.rs

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>
}
}