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]"))}}
-
+ {{if .NumRegularNotifications}}
+
+ {{end}}