Monorepo for Tangled tangled.org
8

Configure Feed

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

1package state 2 3import ( 4 "net/http" 5 6 "github.com/bluesky-social/indigo/atproto/syntax" 7 "tangled.org/core/appview/db" 8 "tangled.org/core/appview/models" 9 "tangled.org/core/appview/oauth" 10 "tangled.org/core/appview/pages" 11 "tangled.org/core/orm" 12) 13 14func (s *State) Home(w http.ResponseWriter, r *http.Request) { 15 // TODO: set this flag based on the UI 16 filtered := false 17 18 user := s.oauth.GetMultiAccountUser(r) 19 20 timeline, err := db.MakeTimeline(s.db, 50, "", filtered) 21 if err != nil { 22 s.logger.Error("failed to make timeline", "err", err) 23 s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") 24 return 25 } 26 27 blueskyPosts, err := db.GetBlueskyPosts(s.db, 8) 28 if err != nil { 29 s.logger.Error("failed to get bluesky posts", "err", err) 30 } 31 32 s.pages.Home(w, pages.TimelineParams{ 33 LoggedInUser: user, 34 Timeline: timeline, 35 BlueskyPosts: blueskyPosts, 36 ShowNewsletter: s.showNewsletter(user), 37 }) 38} 39func (s *State) HomeOrTimeline(w http.ResponseWriter, r *http.Request) { 40 if s.oauth.GetMultiAccountUser(r) != nil { 41 s.Timeline(w, r) 42 return 43 } 44 s.Home(w, r) 45} 46 47func (s *State) Timeline(w http.ResponseWriter, r *http.Request) { 48 user := s.oauth.GetMultiAccountUser(r) 49 50 // TODO: set this flag based on the UI 51 filtered := false 52 53 var userDid string 54 if user != nil { 55 userDid = user.Did 56 } 57 timeline, err := db.MakeTimeline(s.db, 50, userDid, filtered) 58 if err != nil { 59 s.logger.Error("failed to make timeline", "err", err) 60 s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") 61 } 62 63 repos, err := db.GetTopStarredReposLastWeek(s.db) 64 if err != nil { 65 s.logger.Error("failed to get top starred repos", "err", err) 66 s.pages.Notice(w, "topstarredrepos", "Unable to load.") 67 return 68 } 69 70 gfiLabel, err := db.GetLabelDefinition(s.db, orm.FilterEq("at_uri", s.config.Label.GoodFirstIssue)) 71 if err != nil { 72 // non-fatal 73 } 74 75 var vouchSuggestions []models.VouchSuggestion 76 if user != nil { 77 vouchSuggestions, err = db.GetVouchSuggestions(s.db, user.Did, 3) 78 if err != nil { 79 s.logger.Error("failed to get vouch suggestions", "err", err) 80 } 81 if len(vouchSuggestions) > 0 { 82 suggestionDids := make([]syntax.DID, len(vouchSuggestions)) 83 for i, sv := range vouchSuggestions { 84 suggestionDids[i] = syntax.DID(sv.Did) 85 } 86 relationships, err := db.GetVouchRelationshipsBatch(s.db, syntax.DID(user.Did), suggestionDids) 87 if err != nil { 88 s.logger.Error("failed to get vouch relationships for suggestions", "err", err) 89 } else { 90 for i := range vouchSuggestions { 91 vouchSuggestions[i].VouchRelationship = relationships[vouchSuggestions[i].Did] 92 } 93 } 94 } 95 } 96 97 s.pages.Timeline(w, pages.TimelineParams{ 98 LoggedInUser: user, 99 Timeline: timeline, 100 Repos: repos, 101 GfiLabel: gfiLabel, 102 VouchSuggestions: vouchSuggestions, 103 ShowNewsletter: s.showNewsletter(user), 104 }) 105} 106 107// showNewsletter decides whether the newsletter widget/CTA should render. 108// Anonymous visitors always see it (they can dismiss via localStorage); 109// logged-in users whose newsletter_preferences row exists (either 110// subscribed or dismissed) do not. 111func (s *State) showNewsletter(user *oauth.MultiAccountUser) bool { 112 if user == nil { 113 return true 114 } 115 pref, err := db.GetNewsletterPref(s.db, user.Did) 116 if err != nil { 117 s.logger.Error("failed to read newsletter preference", "did", user.Did, "err", err) 118 return true 119 } 120 return pref == nil 121}