diff --git a/appview/pages/pages.go b/appview/pages/pages.go index a9738f2..6b59034 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -311,28 +311,41 @@ func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error { type ProfilePageParams struct { LoggedInUser *auth.User - UserDid string - UserHandle string Repos []db.Repo CollaboratingRepos []db.Repo - ProfileStats ProfileStats - FollowStatus db.FollowStatus - Profile *db.Profile - AvatarUri string ProfileTimeline *db.ProfileTimeline + Card ProfileCard DidHandleMap map[string]string } -type ProfileStats struct { - Followers int - Following int +type ProfileCard struct { + UserDid string + UserHandle string + FollowStatus db.FollowStatus + AvatarUri string + Followers int + Following int + + Profile *db.Profile } func (p *Pages) ProfilePage(w io.Writer, params ProfilePageParams) error { return p.execute("user/profile", w, params) } +type ReposPageParams struct { + LoggedInUser *auth.User + Repos []db.Repo + Card ProfileCard + + DidHandleMap map[string]string +} + +func (p *Pages) ReposPage(w io.Writer, params ReposPageParams) error { + return p.execute("user/repos", w, params) +} + type FollowFragmentParams struct { UserDid string FollowStatus db.FollowStatus diff --git a/appview/pages/templates/user/fragments/editBio.html b/appview/pages/templates/user/fragments/editBio.html index 8cc182e..b09e44d 100644 --- a/appview/pages/templates/user/fragments/editBio.html +++ b/appview/pages/templates/user/fragments/editBio.html @@ -1,6 +1,6 @@ {{ define "user/fragments/editBio" }}
diff --git a/appview/pages/templates/user/fragments/editPins.html b/appview/pages/templates/user/fragments/editPins.html index 49a64b9..e1c1490 100644 --- a/appview/pages/templates/user/fragments/editPins.html +++ b/appview/pages/templates/user/fragments/editPins.html @@ -1,7 +1,7 @@ {{ define "user/fragments/editPins" }} {{ $profile := .Profile }}
diff --git a/appview/pages/templates/user/fragments/profileCard.html b/appview/pages/templates/user/fragments/profileCard.html new file mode 100644 index 0000000..57cd920 --- /dev/null +++ b/appview/pages/templates/user/fragments/profileCard.html @@ -0,0 +1,98 @@ +{{ define "user/fragments/profileCard" }} +
+
+
+ {{ if .AvatarUri }} + + {{ end }} +
+
+

+ {{ didOrHandle .UserDid .UserHandle }} +

+ +
+ {{ block "followerFollowing" (list .Followers .Following) }} {{ end }} +
+
+
+
+ {{ $profile := .Profile }} + {{ with .Profile }} + + {{ if .Description }} +

{{ .Description }}

+ {{ end }} + + + +
+ {{ if .Location }} +
+ {{ i "map-pin" "size-4" }} + {{ .Location }} +
+ {{ end }} + {{ if .IncludeBluesky }} + + {{ end }} + {{ range $link := .Links }} + {{ if $link }} +
+ {{ i "link" "size-4" }} + {{ $link }} +
+ {{ end }} + {{ end }} + {{ if not $profile.IsStatsEmpty }} +
+ {{ range $stat := .Stats }} + {{ if $stat.Kind }} +
+ {{ $stat.Value }} + {{ $stat.Kind.String }} +
+ {{ end }} + {{ end }} +
+ {{ end }} +
+ {{ end }} + {{ if ne .FollowStatus.String "IsSelf" }} + {{ template "user/fragments/follow" . }} + {{ else }} + + {{ end }} +
+
+
+
+
+{{ end }} + +{{ define "followerFollowing" }} + {{ $followers := index . 0 }} + {{ $following := index . 1 }} +
+ {{ i "users" "size-4" }} + {{ $followers }} followers + + {{ $following }} following +
+{{ end }} + diff --git a/appview/pages/templates/user/profile.html b/appview/pages/templates/user/profile.html index 3d80c00..152b79d 100644 --- a/appview/pages/templates/user/profile.html +++ b/appview/pages/templates/user/profile.html @@ -1,9 +1,9 @@ -{{ define "title" }}{{ or .UserHandle .UserDid }}{{ end }} +{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }} {{ define "content" }}
- {{ block "profileCard" . }}{{ end }} + {{ template "user/fragments/profileCard" .Card }}
{{ block "ownRepos" . }}{{ end }} @@ -225,107 +225,17 @@ {{ end }} {{ end }} -{{ define "profileCard" }} -
-
-
- {{ if .AvatarUri }} - - {{ end }} -
-
-

- {{ didOrHandle .UserDid .UserHandle }} -

- -
- {{ block "followerFollowing" .ProfileStats }} {{ end }} -
-
-
-
- {{ $profile := .Profile }} - {{ with .Profile }} - - {{ if .Description }} -

{{ .Description }}

- {{ end }} - - - -
- {{ if .Location }} -
- {{ i "map-pin" "size-4" }} - {{ .Location }} -
- {{ end }} - {{ if .IncludeBluesky }} - - {{ end }} - {{ range $link := .Links }} - {{ if $link }} -
- {{ i "link" "size-4" }} - {{ $link }} -
- {{ end }} - {{ end }} - {{ if not $profile.IsStatsEmpty }} -
- {{ range $stat := .Stats }} - {{ if $stat.Kind }} -
- {{ $stat.Value }} - {{ $stat.Kind.String }} -
- {{ end }} - {{ end }} -
- {{ end }} -
- {{ end }} - {{ if ne .FollowStatus.String "IsSelf" }} - {{ template "user/fragments/follow" . }} - {{ else }} - - {{ end }} -
-
-
-
-
-{{ end }} - -{{ define "followerFollowing" }} -
- {{ i "users" "size-4" }} - {{ .Followers }} followers - - {{ .Following }} following -
-{{ end }} - {{ define "ownRepos" }}
- PINNED REPOS - {{ if and .LoggedInUser (eq .LoggedInUser.Did .UserDid) }} - @@ -337,7 +247,7 @@ id="repo-card" class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800"> diff --git a/appview/pages/templates/user/repos.html b/appview/pages/templates/user/repos.html new file mode 100644 index 0000000..488553a --- /dev/null +++ b/appview/pages/templates/user/repos.html @@ -0,0 +1,44 @@ +{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }} + +{{ define "content" }} +
+
+ {{ template "user/fragments/profileCard" .Card }} +
+
+ {{ block "ownRepos" . }}{{ end }} +
+
+{{ end }} + +{{ define "ownRepos" }} +

ALL REPOSITORIES

+
+ {{ range .Repos }} +
+ + {{ if .Description }} +
+ {{ .Description }} +
+ {{ end }} +
+ {{ if .RepoStats.StarCount }} +
+ {{ i "star" "w-3 h-3 fill-current" }} + {{ .RepoStats.StarCount }} +
+ {{ end }} +
+
+ {{ else }} +

This user does not have any repos yet.

+ {{ end }} +
+{{ end }} diff --git a/appview/state/profile.go b/appview/state/profile.go index df666b4..a5c3fc6 100644 --- a/appview/state/profile.go +++ b/appview/state/profile.go @@ -20,7 +20,17 @@ import ( "tangled.sh/tangled.sh/core/appview/pages" ) -func (s *State) ProfilePage(w http.ResponseWriter, r *http.Request) { +func (s *State) Profile(w http.ResponseWriter, r *http.Request) { + tabVal := r.URL.Query().Get("tab") + switch tabVal { + case "": + s.profilePage(w, r) + case "repos": + s.reposPage(w, r) + } +} + +func (s *State) profilePage(w http.ResponseWriter, r *http.Request) { didOrHandle := chi.URLParam(r, "user") if didOrHandle == "" { http.Error(w, "Bad request", http.StatusBadRequest) @@ -118,22 +128,67 @@ func (s *State) ProfilePage(w http.ResponseWriter, r *http.Request) { profileAvatarUri := s.GetAvatarUri(ident.Handle.String()) s.pages.ProfilePage(w, pages.ProfilePageParams{ LoggedInUser: loggedInUser, - UserDid: ident.DID.String(), - UserHandle: ident.Handle.String(), Repos: pinnedRepos, CollaboratingRepos: pinnedCollaboratingRepos, - ProfileStats: pages.ProfileStats{ - Followers: followers, - Following: following, + DidHandleMap: didHandleMap, + Card: pages.ProfileCard{ + UserDid: ident.DID.String(), + UserHandle: ident.Handle.String(), + AvatarUri: profileAvatarUri, + Profile: profile, + FollowStatus: followStatus, + Followers: followers, + Following: following, }, - Profile: profile, - FollowStatus: db.FollowStatus(followStatus), - DidHandleMap: didHandleMap, - AvatarUri: profileAvatarUri, ProfileTimeline: timeline, }) } +func (s *State) reposPage(w http.ResponseWriter, r *http.Request) { + ident, ok := r.Context().Value("resolvedId").(identity.Identity) + if !ok { + s.pages.Error404(w) + return + } + + profile, err := db.GetProfile(s.db, ident.DID.String()) + if err != nil { + log.Printf("getting profile data for %s: %s", ident.DID.String(), err) + } + + repos, err := db.GetAllReposByDid(s.db, ident.DID.String()) + if err != nil { + log.Printf("getting repos for %s: %s", ident.DID.String(), err) + } + + loggedInUser := s.auth.GetUser(r) + followStatus := db.IsNotFollowing + if loggedInUser != nil { + followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, ident.DID.String()) + } + + followers, following, err := db.GetFollowerFollowing(s.db, ident.DID.String()) + if err != nil { + log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err) + } + + profileAvatarUri := s.GetAvatarUri(ident.Handle.String()) + + s.pages.ReposPage(w, pages.ReposPageParams{ + LoggedInUser: loggedInUser, + Repos: repos, + Card: pages.ProfileCard{ + UserDid: ident.DID.String(), + UserHandle: ident.Handle.String(), + AvatarUri: profileAvatarUri, + Profile: profile, + FollowStatus: followStatus, + Followers: followers, + Following: following, + }, + }) +} + func (s *State) GetAvatarUri(handle string) string { secret := s.config.AvatarSharedSecret h := hmac.New(sha256.New, []byte(secret)) diff --git a/appview/state/router.go b/appview/state/router.go index 1879990..788ea62 100644 --- a/appview/state/router.go +++ b/appview/state/router.go @@ -53,14 +53,7 @@ func (s *State) UserRouter() http.Handler { r.Use(StripLeadingAt) r.With(ResolveIdent(s)).Route("/{user}", func(r chi.Router) { - r.Get("/", s.ProfilePage) - r.Route("/profile", func(r chi.Router) { - r.Use(middleware.AuthMiddleware(s.auth)) - r.Get("/edit-bio", s.EditBioFragment) - r.Get("/edit-pins", s.EditPinsFragment) - r.Post("/bio", s.UpdateProfileBio) - r.Post("/pins", s.UpdateProfilePins) - }) + r.Get("/", s.Profile) r.With(ResolveRepo(s)).Route("/{repo}", func(r chi.Router) { r.Get("/", s.RepoIndex) @@ -246,6 +239,14 @@ func (s *State) StandardRouter() http.Handler { r.Delete("/", s.Star) }) + r.Route("/profile", func(r chi.Router) { + r.Use(middleware.AuthMiddleware(s.auth)) + r.Get("/edit-bio", s.EditBioFragment) + r.Get("/edit-pins", s.EditPinsFragment) + r.Post("/bio", s.UpdateProfileBio) + r.Post("/pins", s.UpdateProfilePins) + }) + r.Mount("/settings", s.SettingsRouter()) r.Get("/keys/{user}", s.Keys)