This repository has no description
1package xrpc
2
3import (
4 "encoding/json"
5 "net/http"
6
7 "tangled.org/core/api/tangled"
8 "tangled.org/core/appview/db"
9 "tangled.org/core/appview/models"
10 xrpcerr "tangled.org/core/xrpc/errors"
11)
12
13func (x *Xrpc) FocusBegin(w http.ResponseWriter, r *http.Request) {
14 l := x.Logger.With("handler", "FocusBegin")
15
16 did, ok := actorDid(r)
17 if !ok {
18 writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden)
19 return
20 }
21
22 if err := db.BeginFocus(x.DB, did); err != nil {
23 l.Error("failed to begin focus", "err", err)
24 writeError(w, errInternal, http.StatusInternalServerError)
25 return
26 }
27
28 item, err := db.GetNextFocusItem(x.DB, did)
29 if err != nil {
30 l.Error("failed to get first focus item", "err", err)
31 _ = db.EndFocus(x.DB, did)
32 writeError(w, errInternal, http.StatusInternalServerError)
33 return
34 }
35
36 if item == nil {
37 _ = db.EndFocus(x.DB, did)
38 x.writeJSON(w, &tangled.TempFocusBeginSession_Output{})
39 return
40 }
41
42 out := &tangled.TempFocusBeginSession_Output{NotificationId: &item.ID}
43 setFocusSubject(item, &out.RepoDid, &out.IssueAt, &out.PullAt)
44
45 x.writeJSON(w, out)
46}
47
48func (x *Xrpc) FocusNext(w http.ResponseWriter, r *http.Request) {
49 l := x.Logger.With("handler", "FocusNext")
50
51 did, ok := actorDid(r)
52 if !ok {
53 writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden)
54 return
55 }
56
57 var input tangled.TempFocusNextItem_Input
58 if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
59 writeError(w, errBadRequestBody, http.StatusBadRequest)
60 return
61 }
62
63 if err := db.MarkNotificationRead(x.DB, input.CurrentId, did); err != nil {
64 l.Warn("failed to mark notification read", "id", input.CurrentId, "err", err)
65 }
66
67 item, err := db.GetNextFocusItem(x.DB, did)
68 if err != nil {
69 l.Error("failed to get next focus item", "err", err)
70 writeError(w, errInternal, http.StatusInternalServerError)
71 return
72 }
73
74 if item == nil {
75 _ = db.EndFocus(x.DB, did)
76 x.writeJSON(w, &tangled.TempFocusNextItem_Output{})
77 return
78 }
79
80 out := &tangled.TempFocusNextItem_Output{NotificationId: &item.ID}
81 setFocusSubject(item, &out.RepoDid, &out.IssueAt, &out.PullAt)
82
83 x.writeJSON(w, out)
84}
85
86func (x *Xrpc) FocusEnd(w http.ResponseWriter, r *http.Request) {
87 l := x.Logger.With("handler", "FocusEnd")
88
89 did, ok := actorDid(r)
90 if !ok {
91 writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden)
92 return
93 }
94
95 if err := db.EndFocus(x.DB, did); err != nil {
96 l.Error("failed to end focus", "err", err)
97 writeError(w, errInternal, http.StatusInternalServerError)
98 return
99 }
100
101 w.WriteHeader(http.StatusOK)
102}
103
104// setFocusSubject fills the repo did and (issue|pull) at-uri of a focus item so
105// the client can navigate to it.
106func setFocusSubject(n *models.NotificationWithEntity, repoDid, issueAt, pullAt **string) {
107 if n.Repo != nil {
108 s := n.Repo.RepoDid
109 *repoDid = &s
110 }
111 if n.Issue != nil {
112 s := n.Issue.AtUri().String()
113 *issueAt = &s
114 }
115 if n.Pull != nil {
116 s := n.Pull.AtUri().String()
117 *pullAt = &s
118 }
119}