"group-data-[collapsible=Icon]:w-(--sidenav-width-icon)",
- SidenavVariant::Floating | SidenavVariant::Inset =>
- "group-data-[collapsible=Icon]:w-[calc(var(--sidenav-width-icon)+(--spacing(4)))]",
- }
- )
- />
-
"left-0 group-data-[collapsible=Offcanvas]:left-[calc(var(--sidenav-width)*-1)]",
- SidenavSide::Right => "right-0 group-data-[collapsible=Offcanvas]:right-[calc(var(--sidenav-width)*-1)]"
- },
- match variant {
- SidenavVariant::Sidenav => "group-data-[collapsible=Icon]:w-(--sidenav-width-icon) group-data-[side=Left]:border-r group-data-[side=Right]:border-l",
- SidenavVariant::Floating | SidenavVariant::Inset =>
- "p-2 group-data-[collapsible=Icon]:w-[calc(var(--sidenav-width-icon)+(--spacing(4))+2px)]",
- },
- )
- >
- // * Act as a Sidenav for the onclick trigger to work with nested Sidenavs.
-
- {children()}
-
-
-
-
- }
- .into_any()
- }}
- }
+ let class_signal = move || {
+ let variant_class = if variant.get() == SidenavMenuButtonVariant::Outline {
+ "border border-input bg-background shadow-xs"
+ } else {
+ ""
+ };
+ tw_merge!(
+ "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
+ variant_class,
+ class.get()
+ )
+ };
+ view! {
}
}
-/* ========================================================== */
-/* ✨ FUNCTIONS ✨ */
-/* ========================================================== */
-
-#[derive(Clone, Copy, PartialEq, Eq, Default, strum::Display)]
-pub enum SidenavState {
- #[default]
- Expanded,
- Collapsed,
+#[component] pub fn SidenavLink(children: Children, #[prop(into)] href: String) -> impl IntoView {
+ view! {
{children()} }
}
-
-const ONCLICK_TRIGGER: &str = "document.querySelector('[data-name=\"Sidenav\"]').setAttribute('data-state', document.querySelector('[data-name=\"Sidenav\"]').getAttribute('data-state') === 'Collapsed' ? 'Expanded' : 'Collapsed')";
-
-#[component]
-pub fn SidenavTrigger(children: Children) -> impl IntoView {
- view! {
- // TODO. Use Button.
-
-
- }
-}
-
-#[component]
-fn SidenavToggleRail() -> impl IntoView {
- view! {
-
- }
-}
\ No newline at end of file
diff --git a/frontend/src/store.rs b/frontend/src/store.rs
index 8618736..9d5ae53 100644
--- a/frontend/src/store.rs
+++ b/frontend/src/store.rs
@@ -153,8 +153,7 @@ pub fn provide_torrent_store() {
pub async fn is_push_subscribed() -> Result
{
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
@@ -162,7 +161,7 @@ pub async fn is_push_subscribed() -> Result {
.dyn_into::()
.map_err(|_| "not a registration")?;
- let push_manager = registration.push_manager();
+ let push_manager = registration.push_manager().map_err(|e| format!("{:?}", e))?;
let subscription = wasm_bindgen_futures::JsFuture::from(push_manager.get_subscription().map_err(|e| format!("{:?}", e))?)
.await
.map_err(|e| format!("{:?}", e))?;
@@ -172,8 +171,7 @@ pub async fn is_push_subscribed() -> Result {
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::().expect("not a reg"),
@@ -181,7 +179,7 @@ pub async fn subscribe_to_push_notifications() {
};
// 1. Get Public Key from Backend
- let public_key = match shared::server_fns::push::get_push_public_key().await {
+ 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; }
};
@@ -192,25 +190,25 @@ pub async fn subscribe_to_push_notifications() {
// 3. Prepare Options
let mut options = web_sys::PushSubscriptionOptionsInit::new();
- options.user_visible_only(true);
- options.application_server_key(Some(&key_array.into()));
+ options.set_user_visible_only(true);
+ options.set_application_server_key(&key_array.into());
// 4. Subscribe
- let push_manager = registration.push_manager();
+ let push_manager = registration.push_manager().expect("no push manager");
match wasm_bindgen_futures::JsFuture::from(push_manager.subscribe_with_options(&options).expect("subscribe failed")).await {
Ok(subscription) => {
- let sub = subscription.dyn_into::().expect("not a sub");
- let json = sub.to_json().expect("sub to json failed");
+ let sub_js = subscription.clone();
- // Extract keys from JSON
- let sub_obj: serde_json::Value = serde_wasm_bindgen::from_value(json).expect("serde from value failed");
+ // Use JS to extract JSON string representation
+ let json_str = js_sys::JSON::stringify(&sub_js).expect("stringify failed").as_string().expect("not a string");
+ let sub_obj: serde_json::Value = serde_json::from_str(&json_str).expect("serde from str failed");
let endpoint = sub_obj["endpoint"].as_str().expect("no endpoint").to_string();
let p256dh = sub_obj["keys"]["p256dh"].as_str().expect("no p256dh").to_string();
let auth = sub_obj["keys"]["auth"].as_str().expect("no auth").to_string();
// 5. Save to Backend
- match shared::server_fns::push::save_push_subscription(endpoint, p256dh, auth).await {
+ match shared::server_fns::push::subscribe_push(endpoint, p256dh, auth).await {
Ok(_) => {
log::info!("Push subscription saved successfully");
toast_success("Bildirimler aktif edildi");
@@ -229,7 +227,7 @@ pub async fn unsubscribe_from_push_notifications() {
let registration = wasm_bindgen_futures::JsFuture::from(sw_container.ready().expect("sw not ready")).await
.unwrap().dyn_into::().unwrap();
- let push_manager = registration.push_manager();
+ let push_manager = registration.push_manager().unwrap();
if let Ok(sub_future) = push_manager.get_subscription() {
if let Ok(subscription) = wasm_bindgen_futures::JsFuture::from(sub_future).await {
if !subscription.is_null() {
@@ -240,7 +238,7 @@ pub async fn unsubscribe_from_push_notifications() {
let _ = wasm_bindgen_futures::JsFuture::from(sub.unsubscribe().unwrap()).await;
// 2. Remove from Backend
- let _ = shared::server_fns::push::remove_push_subscription(endpoint).await;
+ let _ = shared::server_fns::push::unsubscribe_push(endpoint).await;
log::info!("Push subscription removed");
show_toast(NotificationLevel::Info, "Bildirimler kapatıldı");
}
diff --git a/shared/src/server_fns/push.rs b/shared/src/server_fns/push.rs
index 72db4a7..fc5d4b0 100644
--- a/shared/src/server_fns/push.rs
+++ b/shared/src/server_fns/push.rs
@@ -20,3 +20,13 @@ pub async fn subscribe_push(
.await
.map_err(|e| ServerFnError::new(format!("Failed to save subscription: {}", e)))
}
+
+#[server(UnsubscribePush, "/api/server_fns")]
+pub async fn unsubscribe_push(endpoint: String) -> Result<(), ServerFnError> {
+ let db_ctx = expect_context::();
+ db_ctx
+ .db
+ .remove_push_subscription(&endpoint)
+ .await
+ .map_err(|e| ServerFnError::new(format!("Failed to remove subscription: {}", e)))
+}