feat: Add push notification support with VAPID keys

- Backend: web-push integration with VAPID keys
- Push subscription endpoints (GET /api/push/public-key, POST /api/push/subscribe)
- In-memory subscription store
- Frontend: Auto-subscribe to push after notification permission granted
- Service Worker: Push event handler
- Send push notifications when torrents complete
- Works even when browser is closed
This commit is contained in:
spinline
2026-02-05 23:53:23 +03:00
parent 60fc887327
commit 373da566be
9 changed files with 1632 additions and 65 deletions

View File

@@ -10,6 +10,31 @@ use leptos_router::*;
pub fn App() -> impl IntoView {
crate::store::provide_torrent_store();
// Initialize push notifications after user grants permission
create_effect(move |_| {
spawn_local(async {
// Wait a bit for service worker to be ready
gloo_timers::future::TimeoutFuture::new(2000).await;
// Check if Notification API is available and permission is granted
let window = web_sys::window().expect("window should exist");
if let Ok(notification_class) = js_sys::Reflect::get(&window, &"Notification".into()) {
if !notification_class.is_undefined() {
if let Ok(permission) = js_sys::Reflect::get(&notification_class, &"permission".into()) {
if let Some(perm_str) = permission.as_string() {
if perm_str == "granted" {
tracing::info!("Notification permission granted, subscribing to push...");
crate::store::subscribe_to_push_notifications().await;
} else {
tracing::info!("Notification permission not granted yet: {}", perm_str);
}
}
}
}
}
});
});
view! {
// Main app wrapper - ensures proper stacking context
<div class="relative w-full h-screen" style="height: 100dvh;">