From a593f04d7fcdeacbf4f2629ec7d979f896a3fa47 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 2 Jul 2026 14:34:02 -0400 Subject: [PATCH] feat: auto-subscribe push on login, better push logging - Auto-subscribe to push on login, register, and session restore - Guard against nil db in SendChannelNotification - Log push send count per channel message - Bump SW cache to v5 --- internal/push/handlers.go | 9 ++++++++- web/public/sw.js | 2 +- web/src/stores/auth.ts | 13 +++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/internal/push/handlers.go b/internal/push/handlers.go index 83cd9f7..85f9be7 100644 --- a/internal/push/handlers.go +++ b/internal/push/handlers.go @@ -185,7 +185,7 @@ func (h *Handler) SendPush(ctx context.Context, userID string, payload map[strin // SendChannelNotification sends a push notification to all server members (except the author) // when a new message is posted in a channel. func (h *Handler) SendChannelNotification(ctx context.Context, channelID, authorID, channelName, content string) { - if h.vapidPub == "" || h.vapidPriv == "" { + if h.vapidPub == "" || h.vapidPriv == "" || h.db == nil { return } @@ -196,6 +196,8 @@ func (h *Handler) SendChannelNotification(ctx context.Context, channelID, author return } + h.logger.Info("sending push notifications", "channel", channelName, "author", authorID) + body := content if len(body) > 200 { body = body[:200] + "..." @@ -221,6 +223,7 @@ func (h *Handler) SendChannelNotification(ctx context.Context, channelID, author } defer rows.Close() + sent := 0 for rows.Next() { var userID, endpoint, p256dh, auth string if err := rows.Scan(&userID, &endpoint, &p256dh, &auth); err != nil { @@ -250,8 +253,12 @@ func (h *Handler) SendChannelNotification(ctx context.Context, channelID, author } if resp != nil { resp.Body.Close() + if resp.StatusCode < 300 { + sent++ + } } } + h.logger.Info("push notifications sent", "count", sent, "channel", channelName) } // GenerateVAPIDKeys is in cmd/keygen. Use github.com/SherClockHolmes/webpush-go directly. diff --git a/web/public/sw.js b/web/public/sw.js index dc9e656..de4216d 100644 --- a/web/public/sw.js +++ b/web/public/sw.js @@ -1,6 +1,6 @@ // Dumpster PWA Service Worker // Bump CACHE_VERSION on each deploy to force re-cache of hashed assets. -const CACHE_VERSION = 'dumpster-v4'; +const CACHE_VERSION = 'dumpster-v5'; const OFFLINE_URL = '/offline.html'; // Assets to pre-cache on install (shell files) diff --git a/web/src/stores/auth.ts b/web/src/stores/auth.ts index 614ed3c..b0f0506 100644 --- a/web/src/stores/auth.ts +++ b/web/src/stores/auth.ts @@ -71,6 +71,16 @@ interface AuthState { clearError: () => void; } +// ponytail: auto-subscribe to push notifications on auth +function autoSubscribePush() { + import("../stores/push.ts").then(({ usePushStore }) => { + const ps = usePushStore.getState(); + if (ps.isSupported && Notification.permission !== 'denied' && !ps.isSubscribed) { + ps.subscribe(); + } + }); +} + export const useAuthStore = create((set) => ({ user: null, isAuthenticated: false, @@ -86,6 +96,7 @@ export const useAuthStore = create((set) => ({ }); const user = await api.get("/auth/me"); set({ user, isAuthenticated: true, isLoading: false }); + autoSubscribePush(); } catch (error) { set({ isLoading: false, @@ -106,6 +117,7 @@ export const useAuthStore = create((set) => ({ }); const user = await api.get("/auth/me"); set({ user, isAuthenticated: true, isLoading: false }); + autoSubscribePush(); } catch (error) { set({ isLoading: false, @@ -135,6 +147,7 @@ export const useAuthStore = create((set) => ({ try { const user = await api.get(`/auth/me?t=${Date.now()}`); set({ user, isAuthenticated: true, isLoading: false }); + autoSubscribePush(); } catch (error) { set({ user: null,