forked from tangled.org/core
this repo has no description
1package notifications 2 3import ( 4 "log" 5 "net/http" 6 "strconv" 7 8 "github.com/go-chi/chi/v5" 9 "tangled.org/core/appview/db" 10 "tangled.org/core/appview/middleware" 11 "tangled.org/core/appview/oauth" 12 "tangled.org/core/appview/pages" 13) 14 15type Notifications struct { 16 db *db.DB 17 oauth *oauth.OAuth 18 pages *pages.Pages 19} 20 21func New(database *db.DB, oauthHandler *oauth.OAuth, pagesHandler *pages.Pages) *Notifications { 22 return &Notifications{ 23 db: database, 24 oauth: oauthHandler, 25 pages: pagesHandler, 26 } 27} 28 29func (n *Notifications) Router(mw *middleware.Middleware) http.Handler { 30 r := chi.NewRouter() 31 32 r.Use(middleware.AuthMiddleware(n.oauth)) 33 34 r.Get("/", n.notificationsPage) 35 36 r.Get("/count", n.getUnreadCount) 37 r.Post("/{id}/read", n.markRead) 38 r.Post("/read-all", n.markAllRead) 39 r.Delete("/{id}", n.deleteNotification) 40 41 return r 42} 43 44func (n *Notifications) notificationsPage(w http.ResponseWriter, r *http.Request) { 45 userDid := n.oauth.GetDid(r) 46 47 limitStr := r.URL.Query().Get("limit") 48 offsetStr := r.URL.Query().Get("offset") 49 50 limit := 20 // default 51 if limitStr != "" { 52 if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 { 53 limit = l 54 } 55 } 56 57 offset := 0 // default 58 if offsetStr != "" { 59 if o, err := strconv.Atoi(offsetStr); err == nil && o >= 0 { 60 offset = o 61 } 62 } 63 64 notifications, err := n.db.GetNotificationsWithEntities(r.Context(), userDid, limit+1, offset) 65 if err != nil { 66 log.Println("failed to get notifications:", err) 67 n.pages.Error500(w) 68 return 69 } 70 71 hasMore := len(notifications) > limit 72 if hasMore { 73 notifications = notifications[:limit] 74 } 75 76 err = n.db.MarkAllNotificationsRead(r.Context(), userDid) 77 if err != nil { 78 log.Println("failed to mark notifications as read:", err) 79 } 80 81 unreadCount := 0 82 83 user := n.oauth.GetUser(r) 84 if user == nil { 85 http.Error(w, "Failed to get user", http.StatusInternalServerError) 86 return 87 } 88 89 params := pages.NotificationsParams{ 90 LoggedInUser: user, 91 Notifications: notifications, 92 UnreadCount: unreadCount, 93 HasMore: hasMore, 94 NextOffset: offset + limit, 95 Limit: limit, 96 } 97 98 err = n.pages.Notifications(w, params) 99 if err != nil { 100 log.Println("failed to load notifs:", err) 101 n.pages.Error500(w) 102 return 103 } 104} 105 106func (n *Notifications) getUnreadCount(w http.ResponseWriter, r *http.Request) { 107 userDid := n.oauth.GetDid(r) 108 109 count, err := n.db.GetUnreadNotificationCount(r.Context(), userDid) 110 if err != nil { 111 http.Error(w, "Failed to get unread count", http.StatusInternalServerError) 112 return 113 } 114 115 params := pages.NotificationCountParams{ 116 Count: count, 117 } 118 err = n.pages.NotificationCount(w, params) 119 if err != nil { 120 http.Error(w, "Failed to render count", http.StatusInternalServerError) 121 return 122 } 123} 124 125func (n *Notifications) markRead(w http.ResponseWriter, r *http.Request) { 126 userDid := n.oauth.GetDid(r) 127 128 idStr := chi.URLParam(r, "id") 129 notificationID, err := strconv.ParseInt(idStr, 10, 64) 130 if err != nil { 131 http.Error(w, "Invalid notification ID", http.StatusBadRequest) 132 return 133 } 134 135 err = n.db.MarkNotificationRead(r.Context(), notificationID, userDid) 136 if err != nil { 137 http.Error(w, "Failed to mark notification as read", http.StatusInternalServerError) 138 return 139 } 140 141 w.WriteHeader(http.StatusNoContent) 142} 143 144func (n *Notifications) markAllRead(w http.ResponseWriter, r *http.Request) { 145 userDid := n.oauth.GetDid(r) 146 147 err := n.db.MarkAllNotificationsRead(r.Context(), userDid) 148 if err != nil { 149 http.Error(w, "Failed to mark all notifications as read", http.StatusInternalServerError) 150 return 151 } 152 153 http.Redirect(w, r, "/notifications", http.StatusSeeOther) 154} 155 156func (n *Notifications) deleteNotification(w http.ResponseWriter, r *http.Request) { 157 userDid := n.oauth.GetDid(r) 158 159 idStr := chi.URLParam(r, "id") 160 notificationID, err := strconv.ParseInt(idStr, 10, 64) 161 if err != nil { 162 http.Error(w, "Invalid notification ID", http.StatusBadRequest) 163 return 164 } 165 166 err = n.db.DeleteNotification(r.Context(), notificationID, userDid) 167 if err != nil { 168 http.Error(w, "Failed to delete notification", http.StatusInternalServerError) 169 return 170 } 171 172 w.WriteHeader(http.StatusOK) 173}