diff --git a/internal/webserver/handler_login.go b/internal/webserver/handler_login.go index f75e160..1ea7ff3 100644 --- a/internal/webserver/handler_login.go +++ b/internal/webserver/handler_login.go @@ -118,6 +118,13 @@ func (app *Application) ChangeSession(w http.ResponseWriter, r *http.Request) { app.error_400_with_message(w, r, fmt.Sprintf("User not in database: %s", form.AccountName)) return } - data := NotificationBubbles{NumMessageNotifications: len(app.Profile.GetUnreadConversations(app.ActiveUser.ID))} + app.LastReadNotificationSortIndex = 0 // Clear unread notifications + go app.background_notifications_scrape() // Update notifications info in background (avoid latency when switching users) + data := NotificationBubbles{ + NumMessageNotifications: len(app.Profile.GetUnreadConversations(app.ActiveUser.ID)), + } + if app.LastReadNotificationSortIndex != 0 { + data.NumRegularNotifications = app.Profile.GetUnreadNotificationsCount(app.ActiveUser.ID, app.LastReadNotificationSortIndex) + } app.buffered_render_htmx(w, "nav-sidebar", PageGlobalData{}, data) } diff --git a/internal/webserver/handler_sidebar.go b/internal/webserver/handler_sidebar.go index 81d10a5..f3adda1 100644 --- a/internal/webserver/handler_sidebar.go +++ b/internal/webserver/handler_sidebar.go @@ -13,6 +13,11 @@ func (app *Application) NavSidebarPollUpdates(w http.ResponseWriter, r *http.Req return } - data := NotificationBubbles{NumMessageNotifications: len(app.Profile.GetUnreadConversations(app.ActiveUser.ID))} + data := NotificationBubbles{ + NumMessageNotifications: len(app.Profile.GetUnreadConversations(app.ActiveUser.ID)), + } + if app.LastReadNotificationSortIndex != 0 { + data.NumRegularNotifications = app.Profile.GetUnreadNotificationsCount(app.ActiveUser.ID, app.LastReadNotificationSortIndex) + } app.buffered_render_htmx(w, "nav-sidebar", PageGlobalData{}, data) } diff --git a/internal/webserver/renderer_helpers.go b/internal/webserver/renderer_helpers.go index 3c3d4a8..6e1bfd6 100644 --- a/internal/webserver/renderer_helpers.go +++ b/internal/webserver/renderer_helpers.go @@ -17,6 +17,7 @@ import ( type NotificationBubbles struct { NumMessageNotifications int + NumRegularNotifications int } // TODO: this name sucks @@ -99,6 +100,12 @@ func (app *Application) buffered_render_page(w http.ResponseWriter, tpl_file str partials := append(glob("tpl/includes/*.tpl"), glob("tpl/tweet_page_includes/*.tpl")...) global_data.NotificationBubbles.NumMessageNotifications = len(app.Profile.GetUnreadConversations(app.ActiveUser.ID)) + if app.LastReadNotificationSortIndex != 0 { + global_data.NotificationBubbles.NumRegularNotifications = app.Profile.GetUnreadNotificationsCount( + app.ActiveUser.ID, + app.LastReadNotificationSortIndex, + ) + } r := renderer{ Funcs: app.make_funcmap(global_data), diff --git a/internal/webserver/server.go b/internal/webserver/server.go index c36761c..18ef85a 100644 --- a/internal/webserver/server.go +++ b/internal/webserver/server.go @@ -28,10 +28,11 @@ type Application struct { Middlewares []Middleware - Profile persistence.Profile - ActiveUser scraper.User - IsScrapingDisabled bool - API scraper.API + Profile persistence.Profile + ActiveUser scraper.User + IsScrapingDisabled bool + API scraper.API + LastReadNotificationSortIndex int64 } func NewApp(profile persistence.Profile) Application { diff --git a/internal/webserver/static/styles.css b/internal/webserver/static/styles.css index 4339211..d21f7e0 100644 --- a/internal/webserver/static/styles.css +++ b/internal/webserver/static/styles.css @@ -945,8 +945,12 @@ main { * Notifications ******************************************************/ +.notifications-header { + border-bottom: 1px solid var(--color-outline-gray); +} + /** - * Notifications module + * Notification module */ .notification { .notification__users { diff --git a/internal/webserver/stopwatch.go b/internal/webserver/stopwatch.go index 30921fb..8dda08c 100644 --- a/internal/webserver/stopwatch.go +++ b/internal/webserver/stopwatch.go @@ -118,6 +118,41 @@ func (app *Application) background_dm_polling_scrape() { fmt.Println("Scraping DMs succeeded.") } +func (app *Application) background_notifications_scrape() { + // Avoid crashing the thread if a scrape fails + defer func() { + if r := recover(); r != nil { + // TODO + fmt.Println("Background notifications thread: panicked!") + if err, ok := r.(error); ok { + fmt.Println(err.Error()) + } else { + fmt.Println(r) + } + } + }() + + fmt.Println("Starting notifications scrape...") + + // Do nothing if scraping is currently disabled + if app.IsScrapingDisabled { + fmt.Println("Skipping notifications scrape!") + return + } + + fmt.Println("Scraping user notifications...") + trove, last_unread_notification_sort_index, err := app.API.GetNotifications(1) // Just 1 page + if err != nil { + panic(err) + } + // Jot down the unread notifs info in the application object (to render notification count bubble) + app.LastReadNotificationSortIndex = last_unread_notification_sort_index + fmt.Println("Saving notification results...") + app.Profile.SaveTweetTrove(trove, false, &app.API) + go app.Profile.SaveTweetTrove(trove, true, &app.API) + fmt.Println("Scraping notification succeeded.") +} + func (app *Application) start_background() { fmt.Println("Starting background") @@ -163,4 +198,16 @@ func (app *Application) start_background() { app.background_dm_polling_scrape() } }() + + // Scrape notifications every 10 seconds + go func() { + app.background_notifications_scrape() + + interval := 10 * time.Second + timer := time.NewTicker(interval) + defer timer.Stop() + for range timer.C { + app.background_notifications_scrape() + } + }() } diff --git a/internal/webserver/tpl/includes/nav_sidebar.tpl b/internal/webserver/tpl/includes/nav_sidebar.tpl index bd7804d..53dd247 100644 --- a/internal/webserver/tpl/includes/nav_sidebar.tpl +++ b/internal/webserver/tpl/includes/nav_sidebar.tpl @@ -21,8 +21,11 @@ {{if (not (eq (active_user).Handle "[nobody]"))}} -
  • +
  • diff --git a/internal/webserver/tpl/notifications.tpl b/internal/webserver/tpl/notifications.tpl index c462ac8..1ef8664 100644 --- a/internal/webserver/tpl/notifications.tpl +++ b/internal/webserver/tpl/notifications.tpl @@ -2,7 +2,18 @@ {{define "main"}}
    -

    Notifications

    +
    +
    {{/* Extra div to take up a slot in the `row` */}} +

    Notifications

    + +