This repository has no description
1package state
2
3import (
4 "net/http"
5 "strconv"
6
7 "tangled.org/core/appview/db"
8 "tangled.org/core/appview/models"
9 "tangled.org/core/appview/pages"
10)
11
12func onboardingStepURL(step int) string {
13 switch step {
14 case models.OnboardingStepProfile:
15 return "/welcome/profile"
16 case models.OnboardingStepKeys:
17 return "/welcome/keys"
18 case models.OnboardingStepSocial:
19 return "/welcome/social"
20 case models.OnboardingStepRepo:
21 return "/welcome/repo"
22 default:
23 return "/"
24 }
25}
26
27func (s *State) OnboardingResume(w http.ResponseWriter, r *http.Request) {
28 did := s.oauth.GetDid(r)
29 ob, err := db.GetOnboarding(s.db, did)
30 if err != nil {
31 s.logger.Error("failed to get onboarding", "did", did, "err", err)
32 }
33 if ob == nil || ob.Status != models.OnboardingInProgress {
34 http.Redirect(w, r, "/", http.StatusFound)
35 return
36 }
37 http.Redirect(w, r, onboardingStepURL(ob.Step), http.StatusFound)
38}
39
40func (s *State) OnboardingNext(w http.ResponseWriter, r *http.Request) {
41 did := s.oauth.GetDid(r)
42 step, _ := strconv.Atoi(r.FormValue("step"))
43
44 if step >= models.OnboardingStepDone {
45 if err := db.CompleteOnboarding(s.db, did); err != nil {
46 s.logger.Error("failed to complete onboarding", "did", did, "err", err)
47 }
48 s.pages.HxRedirect(w, "/")
49 return
50 }
51
52 if step == models.OnboardingStepRepo {
53 if err := db.CompleteOnboarding(s.db, did); err != nil {
54 s.logger.Error("failed to complete onboarding", "did", did, "err", err)
55 }
56 s.pages.HxRedirect(w, onboardingStepURL(step))
57 return
58 }
59
60 if err := db.AdvanceOnboardingStep(s.db, did, step); err != nil {
61 s.logger.Error("failed to advance onboarding", "did", did, "err", err)
62 }
63 s.pages.HxRedirect(w, onboardingStepURL(step))
64}
65
66func (s *State) OnboardingSkip(w http.ResponseWriter, r *http.Request) {
67 did := s.oauth.GetDid(r)
68 if err := db.SkipOnboarding(s.db, did); err != nil {
69 s.logger.Error("failed to skip onboarding", "did", did, "err", err)
70 }
71 s.pages.HxRedirect(w, "/")
72}
73
74func (s *State) OnboardingComplete(w http.ResponseWriter, r *http.Request) {
75 did := s.oauth.GetDid(r)
76 if err := db.CompleteOnboarding(s.db, did); err != nil {
77 s.logger.Error("failed to complete onboarding", "did", did, "err", err)
78 }
79 s.pages.HxRedirect(w, "/")
80}
81
82func (s *State) OnboardingProfile(w http.ResponseWriter, r *http.Request) {
83 user := s.oauth.GetMultiAccountUser(r)
84
85 profile, err := db.GetProfile(s.db, user.Did)
86 if err != nil {
87 s.logger.Error("getting profile data", "did", user.Did, "err", err)
88 }
89 if profile == nil {
90 profile = &models.Profile{Did: user.Did}
91 }
92
93 var alsoKnownAs []string
94 if ident, err := s.idResolver.ResolveIdent(r.Context(), user.Did); err == nil {
95 alsoKnownAs = ident.AlsoKnownAs
96 }
97
98 bp := pages.BaseParamsFromContext(r.Context())
99 s.pages.Onboarding(w, pages.OnboardingParams{
100 BaseParams: bp,
101 Step: models.OnboardingStepProfile,
102 EditBio: pages.EditBioParams{
103 BaseParams: bp,
104 Profile: profile,
105 AlsoKnownAs: alsoKnownAs,
106 Action: "/welcome/profile",
107 },
108 })
109}
110
111func (s *State) OnboardingSaveProfile(w http.ResponseWriter, r *http.Request) {
112 did := s.oauth.GetDid(r)
113
114 if err := r.ParseForm(); err != nil {
115 s.pages.Notice(w, "update-profile", "Invalid form.")
116 return
117 }
118
119 profile, err := s.bioFormToProfile(r)
120 if err != nil {
121 s.pages.Notice(w, "update-profile", err.Error())
122 return
123 }
124
125 if err := s.writeProfile(r, profile); err != nil {
126 s.logger.Error("onboarding: failed to write profile", "did", did, "err", err)
127 s.pages.Notice(w, "update-profile", "Failed to update profile, try again later.")
128 return
129 }
130
131 if err := db.AdvanceOnboardingStep(s.db, did, models.OnboardingStepSocial); err != nil {
132 s.logger.Error("failed to advance onboarding", "did", did, "err", err)
133 }
134 s.pages.HxRedirect(w, "/welcome/social")
135}
136
137func (s *State) OnboardingKeys(w http.ResponseWriter, r *http.Request) {
138 user := s.oauth.GetMultiAccountUser(r)
139
140 pubKeys, err := db.GetPublicKeysForDid(s.db, user.Did)
141 if err != nil {
142 s.logger.Error("getting public keys", "did", user.Did, "err", err)
143 }
144
145 s.pages.Onboarding(w, pages.OnboardingParams{
146 BaseParams: pages.BaseParamsFromContext(r.Context()),
147 Step: models.OnboardingStepKeys,
148 PubKeys: pubKeys,
149 })
150}
151
152const onboardingSocialLimit = 4
153
154func (s *State) OnboardingSocial(w http.ResponseWriter, r *http.Request) {
155 user := s.oauth.GetMultiAccountUser(r)
156 bp := pages.BaseParamsFromContext(r.Context())
157
158 var people []pages.FollowCard
159 mostFollowed, err := db.GetMostFollowed(s.db, onboardingSocialLimit+2)
160 if err != nil {
161 s.logger.Error("failed to get most followed", "err", err)
162 }
163 var dids []string
164 for _, did := range mostFollowed {
165 if did == user.Did {
166 continue
167 }
168 dids = append(dids, did)
169 if len(dids) >= onboardingSocialLimit {
170 break
171 }
172 }
173 if len(dids) > 0 {
174 statuses, _ := db.GetFollowStatuses(s.db, user.Did, dids)
175 counts, _ := db.GetFollowerFollowingCounts(s.db, dids)
176 for _, did := range dids {
177 profile, _ := db.GetProfile(s.db, did)
178 if profile == nil {
179 profile = &models.Profile{Did: did}
180 }
181 people = append(people, pages.FollowCard{
182 BaseParams: bp,
183 UserDid: did,
184 Profile: profile,
185 FollowStatus: statuses[did],
186 FollowersCount: counts[did].Followers,
187 FollowingCount: counts[did].Following,
188 })
189 }
190 }
191
192 repos, err := db.GetTopStarredReposLastWeek(s.db)
193 if err != nil {
194 s.logger.Error("failed to get trending repos", "err", err)
195 }
196 trending := make([]models.Repo, 0, onboardingSocialLimit)
197 for _, repo := range repos {
198 if repo.RepoDid == "" {
199 continue
200 }
201 trending = append(trending, repo)
202 if len(trending) >= onboardingSocialLimit {
203 break
204 }
205 }
206
207 starStatuses := map[string]bool{}
208 if len(trending) > 0 {
209 repoDids := make([]string, 0, len(trending))
210 for _, repo := range trending {
211 repoDids = append(repoDids, repo.RepoDid)
212 }
213 starStatuses, _ = db.GetStarStatuses(s.db, user.Did, repoDids)
214 }
215
216 s.pages.Onboarding(w, pages.OnboardingParams{
217 BaseParams: bp,
218 Step: models.OnboardingStepSocial,
219 People: people,
220 TrendingRepos: trending,
221 StarStatuses: starStatuses,
222 })
223}
224
225func (s *State) OnboardingRepo(w http.ResponseWriter, r *http.Request) {
226 s.pages.Onboarding(w, pages.OnboardingParams{
227 BaseParams: pages.BaseParamsFromContext(r.Context()),
228 Step: models.OnboardingStepRepo,
229 })
230}