Write on the margins of the internet. Powered by the AT Protocol.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix notifications linking to the wrong thing again...

scanash00 1247426a 14adba53

+50 -15
+1 -1
backend/internal/api/handler.go
··· 515 515 return 516 516 } 517 517 518 - enriched, err := hydrateNotifications(notifications) 518 + enriched, err := hydrateNotifications(h.db, notifications) 519 519 if err != nil { 520 520 log.Printf("Failed to hydrate notifications: %v\n", err) 521 521 }
+40 -8
backend/internal/api/hydration.go
··· 118 118 } 119 119 120 120 type APINotification struct { 121 - ID int `json:"id"` 122 - Recipient Author `json:"recipient"` 123 - Actor Author `json:"actor"` 124 - Type string `json:"type"` 125 - SubjectURI string `json:"subjectUri"` 126 - CreatedAt time.Time `json:"createdAt"` 127 - ReadAt *time.Time `json:"readAt,omitempty"` 121 + ID int `json:"id"` 122 + Recipient Author `json:"recipient"` 123 + Actor Author `json:"actor"` 124 + Type string `json:"type"` 125 + SubjectURI string `json:"subjectUri"` 126 + Subject interface{} `json:"subject,omitempty"` 127 + CreatedAt time.Time `json:"createdAt"` 128 + ReadAt *time.Time `json:"readAt,omitempty"` 128 129 } 129 130 130 131 func hydrateAnnotations(annotations []db.Annotation) ([]APIAnnotation, error) { ··· 498 499 return result, nil 499 500 } 500 501 501 - func hydrateNotifications(notifications []db.Notification) ([]APINotification, error) { 502 + func hydrateNotifications(database *db.DB, notifications []db.Notification) ([]APINotification, error) { 502 503 if len(notifications) == 0 { 503 504 return []APINotification{}, nil 504 505 } ··· 518 519 519 520 profiles := fetchProfilesForDIDs(dids) 520 521 522 + replyURIs := make([]string, 0) 523 + for _, n := range notifications { 524 + if n.Type == "reply" { 525 + replyURIs = append(replyURIs, n.SubjectURI) 526 + } 527 + } 528 + 529 + replyMap := make(map[string]APIReply) 530 + if len(replyURIs) > 0 { 531 + var replies []db.Reply 532 + for _, uri := range replyURIs { 533 + r, err := database.GetReplyByURI(uri) 534 + if err == nil { 535 + replies = append(replies, *r) 536 + } 537 + } 538 + 539 + hydratedReplies, _ := hydrateReplies(replies) 540 + for _, r := range hydratedReplies { 541 + replyMap[r.ID] = r 542 + } 543 + } 544 + 521 545 result := make([]APINotification, len(notifications)) 522 546 for i, n := range notifications { 547 + var subject interface{} 548 + if n.Type == "reply" { 549 + if val, ok := replyMap[n.SubjectURI]; ok { 550 + subject = val 551 + } 552 + } 553 + 523 554 result[i] = APINotification{ 524 555 ID: n.ID, 525 556 Recipient: profiles[n.RecipientDID], 526 557 Actor: profiles[n.ActorDID], 527 558 Type: n.Type, 528 559 SubjectURI: n.SubjectURI, 560 + Subject: subject, 529 561 CreatedAt: n.CreatedAt, 530 562 ReadAt: n.ReadAt, 531 563 }
+9 -6
web/src/pages/Notifications.jsx
··· 4 4 import { getNotifications, markNotificationsRead } from "../api/client"; 5 5 import { BellIcon, HeartIcon, ReplyIcon } from "../components/Icons"; 6 6 7 - function getContentRoute(subjectUri) { 8 - if (!subjectUri) return "/"; 9 - if (subjectUri.includes("at.margin.bookmark")) { 7 + function getNotificationRoute(n) { 8 + if (n.type === "reply" && n.subject?.inReplyTo) { 9 + return `/annotation/${encodeURIComponent(n.subject.inReplyTo)}`; 10 + } 11 + if (!n.subjectUri) return "/"; 12 + if (n.subjectUri.includes("at.margin.bookmark")) { 10 13 return `/bookmarks`; 11 14 } 12 - if (subjectUri.includes("at.margin.highlight")) { 15 + if (n.subjectUri.includes("at.margin.highlight")) { 13 16 return `/highlights`; 14 17 } 15 - return `/annotation/${encodeURIComponent(subjectUri)}`; 18 + return `/annotation/${encodeURIComponent(n.subjectUri)}`; 16 19 } 17 20 18 21 export default function Notifications() { ··· 163 166 {notifications.map((n, i) => ( 164 167 <Link 165 168 key={n.id || i} 166 - to={getContentRoute(n.subjectUri)} 169 + to={getNotificationRoute(n)} 167 170 className="notification-item card" 168 171 style={{ alignItems: "center" }} 169 172 >