Show unread notifications count bubble in web UI; add background scraping of notifications every 10s
This commit is contained in:
parent
72b547f6aa
commit
14ea626014
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -945,8 +945,12 @@ main {
|
||||
* Notifications
|
||||
******************************************************/
|
||||
|
||||
.notifications-header {
|
||||
border-bottom: 1px solid var(--color-outline-gray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifications module
|
||||
* Notification module
|
||||
*/
|
||||
.notification {
|
||||
.notification__users {
|
||||
|
@ -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()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -21,8 +21,11 @@
|
||||
</a>
|
||||
{{if (not (eq (active_user).Handle "[nobody]"))}}
|
||||
<a href="/notifications">
|
||||
<li class="button labelled-icon">
|
||||
<li class="nav-sidebar__notifications button labelled-icon">
|
||||
<img class="svg-icon" src="/static/icons/notifications.svg" width="24" height="24" />
|
||||
{{if .NumRegularNotifications}}
|
||||
<span class="nav-sidebar__notifications-count">{{.NumRegularNotifications}}</span>
|
||||
{{end}}
|
||||
<label class="nav-sidebar__button-label">Notifications</label>
|
||||
</li>
|
||||
</a>
|
||||
|
@ -2,7 +2,18 @@
|
||||
|
||||
{{define "main"}}
|
||||
<div class="notifications-header">
|
||||
<h2>Notifications</h2>
|
||||
<div class="row row--spread">
|
||||
<div class="dummy"></div> {{/* Extra div to take up a slot in the `row` */}}
|
||||
<h1>Notifications</h1>
|
||||
<div class="row">
|
||||
<a class="button" target="_blank" href="https://twitter.com/notifications" title="Open on twitter.com">
|
||||
<img class="svg-icon" src="/static/icons/external-link.svg" width="24" height="24" />
|
||||
</a>
|
||||
<a class="button" hx-get="?scrape" hx-target="body" hx-indicator=".search-header" title="Refresh">
|
||||
<img class="svg-icon" src="/static/icons/refresh.svg" width="24" height="24" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline">
|
||||
|
Loading…
x
Reference in New Issue
Block a user