feat: notifications modal, admin dedup, and in-app notification preferences
- Replace bell dropdown with full-screen NotificationsModal (mirrors SearchModal pattern) - Notifications visible to all logged-in users (not just admin) - Admin users excluded from new-chapter fan-out (dedup vs Scrape Complete notification) - Users with notify_new_chapters=false opted out of new-chapter in-app notifications - Toggle in profile page to enable/disable in-app new-chapter notifications - PATCH /api/profile endpoint to save notification preferences - User-facing /notifications page (admin redirects to /admin/notifications)
This commit is contained in:
@@ -539,7 +539,21 @@ func (r *Runner) runScrapeTask(ctx context.Context, task domain.ScrapeTask) {
|
||||
fmt.Sprintf("Scraped %d chapters, skipped %d (%s)", result.ChaptersScraped, result.ChaptersSkipped, task.Kind),
|
||||
"/admin/tasks")
|
||||
}
|
||||
// Send push notifications to users who have this book in their library.
|
||||
// Fan-out in-app new-chapter notification to all users who have this book
|
||||
// in their library. Runs in background so it doesn't block the task loop.
|
||||
if r.deps.Store != nil && result.ChaptersScraped > 0 &&
|
||||
result.Slug != "" && task.Kind != "catalogue" {
|
||||
go func() {
|
||||
notifyCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
title := result.Slug
|
||||
_ = r.deps.Store.NotifyUsersWithBook(notifyCtx, result.Slug,
|
||||
"New chapters available",
|
||||
fmt.Sprintf("%d new chapter(s) added to %s", result.ChaptersScraped, title),
|
||||
"/books/"+result.Slug)
|
||||
}()
|
||||
}
|
||||
// Send Web Push notifications to subscribed browsers.
|
||||
if r.deps.WebPush != nil && r.deps.Store != nil &&
|
||||
result.ChaptersScraped > 0 && result.Slug != "" && task.Kind != "catalogue" {
|
||||
go r.deps.WebPush.SendToBook(context.Background(), r.deps.Store, result.Slug, webpush.Payload{
|
||||
|
||||
Reference in New Issue
Block a user