fix: centralize sidenav state in store and resolve all component property issues
Some checks failed
Build MIPS Binary / build (push) Failing after 45s
Some checks failed
Build MIPS Binary / build (push) Failing after 45s
This commit is contained in:
@@ -1,23 +1,20 @@
|
||||
use leptos::prelude::*;
|
||||
use crate::components::layout::sidebar::Sidebar;
|
||||
use crate::components::layout::toolbar::Toolbar;
|
||||
use crate::components::ui::sidenav::{SidenavWrapper, Sidenav, SidenavInset, SidenavState, SidenavCollapsible};
|
||||
use crate::components::ui::sidenav::{SidenavWrapper, Sidenav, SidenavInset};
|
||||
|
||||
#[component]
|
||||
pub fn ProtectedLayout(children: Children) -> impl IntoView {
|
||||
let sidenav_state = RwSignal::new(SidenavState::Expanded);
|
||||
let store = use_context::<crate::store::TorrentStore>().expect("store not provided");
|
||||
|
||||
view! {
|
||||
<SidenavWrapper attr:style="--sidenav-width:16rem; --sidenav-width-icon:3.5rem;">
|
||||
<Sidenav
|
||||
data_state=Signal::from(sidenav_state)
|
||||
data_collapsible=SidenavCollapsible::Icon
|
||||
>
|
||||
<SidenavWrapper attr:style="--sidenav-width:16rem; --sidenav-width-icon:4rem;">
|
||||
<Sidenav data_state=Signal::from(store.sidenav_state)>
|
||||
<Sidebar />
|
||||
</Sidenav>
|
||||
|
||||
<SidenavInset class="flex flex-col h-screen overflow-hidden">
|
||||
<Toolbar sidenav_state=sidenav_state />
|
||||
<Toolbar sidenav_state=store.sidenav_state />
|
||||
<main class="flex-1 overflow-auto bg-muted/30">
|
||||
{children()}
|
||||
</main>
|
||||
|
||||
@@ -109,9 +109,48 @@ pub fn Sidebar() -> impl IntoView {
|
||||
icon="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
|
||||
label="Tümü"
|
||||
count=Signal::derive(total_count)
|
||||
is_collapsed=is_collapsed.into()
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
<SidebarItem
|
||||
active=Signal::derive(move || is_active(crate::store::FilterStatus::Downloading))
|
||||
on_click=move |_| set_filter(crate::store::FilterStatus::Downloading)
|
||||
icon="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"
|
||||
label="İndirilenler"
|
||||
count=Signal::derive(downloading_count)
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
<SidebarItem
|
||||
active=Signal::derive(move || is_active(crate::store::FilterStatus::Seeding))
|
||||
on_click=move |_| set_filter(crate::store::FilterStatus::Seeding)
|
||||
icon="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"
|
||||
label="Gönderilenler"
|
||||
count=Signal::derive(seeding_count)
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
<SidebarItem
|
||||
active=Signal::derive(move || is_active(crate::store::FilterStatus::Completed))
|
||||
on_click=move |_| set_filter(crate::store::FilterStatus::Completed)
|
||||
icon="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
label="Tamamlananlar"
|
||||
count=Signal::derive(completed_count)
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
<SidebarItem
|
||||
active=Signal::derive(move || is_active(crate::store::FilterStatus::Paused))
|
||||
on_click=move |_| set_filter(crate::store::FilterStatus::Paused)
|
||||
icon="M15.75 5.25v13.5m-7.5-13.5v13.5"
|
||||
label="Durdurulanlar"
|
||||
count=Signal::derive(paused_count)
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
<SidebarItem
|
||||
active=Signal::derive(move || is_active(crate::store::FilterStatus::Inactive))
|
||||
on_click=move |_| set_filter(crate::store::FilterStatus::Inactive)
|
||||
icon="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"
|
||||
label="Pasif"
|
||||
count=Signal::derive(inactive_count)
|
||||
is_collapsed=is_collapsed
|
||||
/>
|
||||
// ... (aynı mantık diğer itemler için de geçerli olacak)
|
||||
</SidenavMenu>
|
||||
</SidenavGroupContent>
|
||||
</SidenavGroup>
|
||||
@@ -119,7 +158,6 @@ pub fn Sidebar() -> impl IntoView {
|
||||
|
||||
<SidenavFooter>
|
||||
<div class="flex flex-col gap-4 p-2">
|
||||
// Push Toggle - Hide text when collapsed
|
||||
<div class="flex items-center justify-between px-2 py-1 bg-muted/20 rounded-md border border-border/50">
|
||||
<div class="flex flex-col gap-0.5" class:hidden=is_collapsed>
|
||||
<span class="text-[10px] font-bold uppercase tracking-wider text-foreground/70">"Bildirimler"</span>
|
||||
@@ -169,15 +207,18 @@ pub fn Sidebar() -> impl IntoView {
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn SidebarItem(
|
||||
fn SidebarItem<F>(
|
||||
active: Signal<bool>,
|
||||
on_click: impl Fn(web_sys::MouseEvent) + 'static + Send,
|
||||
on_click: F,
|
||||
#[prop(into)] icon: String,
|
||||
#[prop(into)] label: &'static str,
|
||||
count: Signal<usize>,
|
||||
) -> impl IntoView {
|
||||
#[prop(into)] is_collapsed: Signal<bool>,
|
||||
) -> impl IntoView
|
||||
where F: Fn(web_sys::MouseEvent) + 'static + Send
|
||||
{
|
||||
let variant = move || if active.get() { SidenavMenuButtonVariant::Outline } else { SidenavMenuButtonVariant::Default };
|
||||
let class = move || if active.get() { "bg-accent/50 border-accent text-foreground".to_string() } else { "text-muted-foreground hover:text-foreground".to_string() };
|
||||
let class = move || if active.get() { "bg-accent/50 border-accent text-foreground font-bold".to_string() } else { "text-muted-foreground hover:text-foreground".to_string() };
|
||||
|
||||
view! {
|
||||
<SidenavMenuItem>
|
||||
@@ -189,8 +230,8 @@ fn SidebarItem(
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4 shrink-0">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d=icon.clone() />
|
||||
</svg>
|
||||
<span class="flex-1 truncate">{label}</span>
|
||||
<span class="text-[10px] font-mono opacity-50">{count}</span>
|
||||
<span class="flex-1 truncate" class:hidden=is_collapsed>{label}</span>
|
||||
<span class="text-[10px] font-mono opacity-50" class:hidden=is_collapsed>{count}</span>
|
||||
</SidenavMenuButton>
|
||||
</SidenavMenuItem>
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64};
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
use crate::components::ui::toast::{ToastType, toast};
|
||||
use crate::components::ui::sidenav::SidenavState;
|
||||
|
||||
pub fn show_toast(level: NotificationLevel, message: impl Into<String>) {
|
||||
let msg = message.into();
|
||||
@@ -55,6 +56,7 @@ pub struct TorrentStore {
|
||||
pub user: RwSignal<Option<String>>,
|
||||
pub selected_torrent: RwSignal<Option<String>>,
|
||||
pub push_enabled: RwSignal<bool>,
|
||||
pub sidenav_state: RwSignal<SidenavState>,
|
||||
}
|
||||
|
||||
pub fn provide_torrent_store() {
|
||||
@@ -65,10 +67,11 @@ pub fn provide_torrent_store() {
|
||||
let user = RwSignal::new(Option::<String>::None);
|
||||
let selected_torrent = RwSignal::new(Option::<String>::None);
|
||||
let push_enabled = RwSignal::new(false);
|
||||
let sidenav_state = RwSignal::new(SidenavState::Expanded);
|
||||
|
||||
let show_browser_notification = crate::utils::notification::use_app_notification();
|
||||
|
||||
let store = TorrentStore { torrents, filter, search_query, global_stats, user, selected_torrent, push_enabled };
|
||||
let store = TorrentStore { torrents, filter, search_query, global_stats, user, selected_torrent, push_enabled, sidenav_state };
|
||||
provide_context(store);
|
||||
|
||||
// Initial check for push status
|
||||
@@ -134,7 +137,7 @@ pub fn provide_torrent_store() {
|
||||
}
|
||||
if was_connected && !disconnect_notified {
|
||||
show_toast(NotificationLevel::Warning, "Sunucu bağlantısı kesildi, yeniden bağlanılıyor...");
|
||||
disconnect_notified = true;
|
||||
disconnect_notified = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,8 +156,7 @@ pub fn provide_torrent_store() {
|
||||
|
||||
pub async fn is_push_subscribed() -> Result<bool, String> {
|
||||
let window = web_sys::window().ok_or("no window")?;
|
||||
let navigator = window.navigator();
|
||||
let sw_container = navigator.service_worker();
|
||||
let sw_container = window.navigator().service_worker();
|
||||
|
||||
let registration = wasm_bindgen_futures::JsFuture::from(sw_container.ready().map_err(|e| format!("{:?}", e))?)
|
||||
.await
|
||||
@@ -172,8 +174,7 @@ pub async fn is_push_subscribed() -> Result<bool, String> {
|
||||
|
||||
pub async fn subscribe_to_push_notifications() {
|
||||
let window = web_sys::window().expect("no window");
|
||||
let navigator = window.navigator();
|
||||
let sw_container = navigator.service_worker();
|
||||
let sw_container = window.navigator().service_worker();
|
||||
|
||||
let registration = match wasm_bindgen_futures::JsFuture::from(sw_container.ready().expect("sw not ready")).await {
|
||||
Ok(reg) => reg.dyn_into::<web_sys::ServiceWorkerRegistration>().expect("not a reg"),
|
||||
@@ -181,8 +182,7 @@ pub async fn subscribe_to_push_notifications() {
|
||||
};
|
||||
|
||||
// 1. Get Public Key from Backend
|
||||
let public_key_res: Result<String, _> = shared::server_fns::push::get_public_key().await;
|
||||
let public_key = match public_key_res {
|
||||
let public_key = match shared::server_fns::push::get_public_key().await {
|
||||
Ok(key) => key,
|
||||
Err(e) => { log::error!("Failed to get public key: {:?}", e); return; }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user