From 9dd8ecf708d379238e5515480ecc3d270411188a Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Tue, 19 Aug 2025 11:26:06 +0300 Subject: [PATCH] appview/pages: show trending repos in the timeline Change-Id: zxovstvplnokulqzlusxlmokosyqzkqy Signed-off-by: Anirudh Oppiliappan --- appview/db/db.go | 4 + appview/db/star.go | 75 ++++++++++++++++++- appview/pages/pages.go | 11 ++- .../timeline/fragments/topStarredRepos.html | 25 +++++++ .../templates/{ => timeline}/timeline.html | 32 +++++++- .../templates/user/fragments/repoCard.html | 4 +- appview/state/router.go | 1 + appview/state/state.go | 13 ++++ 8 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 appview/pages/templates/timeline/fragments/topStarredRepos.html rename appview/pages/templates/{ => timeline}/timeline.html (86%) diff --git a/appview/db/db.go b/appview/db/db.go index afb4fe95..45cafa30 100644 --- a/appview/db/db.go +++ b/appview/db/db.go @@ -470,6 +470,10 @@ func Make(dbPath string) (*DB, error) { id integer primary key autoincrement, name text unique ); + + -- indexes for better star query performance + create index if not exists idx_stars_created on stars(created); + create index if not exists idx_stars_repo_at_created on stars(repo_at, created); `) if err != nil { return nil, err diff --git a/appview/db/star.go b/appview/db/star.go index 7a005f3b..fa2655a8 100644 --- a/appview/db/star.go +++ b/appview/db/star.go @@ -47,7 +47,7 @@ func AddStar(e Execer, star *Star) error { // Get a star record func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*Star, error) { query := ` - select starred_by_did, repo_at, created, rkey + select starred_by_did, repo_at, created, rkey from stars where starred_by_did = ? and repo_at = ?` row := e.QueryRow(query, starredByDid, repoAt) @@ -119,7 +119,7 @@ func GetStars(e Execer, limit int, filters ...filter) ([]Star, error) { } repoQuery := fmt.Sprintf( - `select starred_by_did, repo_at, created, rkey + `select starred_by_did, repo_at, created, rkey from stars %s order by created desc @@ -187,7 +187,7 @@ func GetAllStars(e Execer, limit int) ([]Star, error) { var stars []Star rows, err := e.Query(` - select + select s.starred_by_did, s.repo_at, s.rkey, @@ -244,3 +244,72 @@ func GetAllStars(e Execer, limit int) ([]Star, error) { return stars, nil } + +// GetTopStarredReposLastWeek returns the top 8 most starred repositories from the last week +func GetTopStarredReposLastWeek(e Execer) ([]Repo, error) { + // first, get the top repo URIs by star count from the last week + query := ` + with recent_starred_repos as ( + select distinct repo_at + from stars + where created >= datetime('now', '-7 days') + ), + repo_star_counts as ( + select + s.repo_at, + count(*) as star_count + from stars s + join recent_starred_repos rsr on s.repo_at = rsr.repo_at + group by s.repo_at + ) + select rsc.repo_at + from repo_star_counts rsc + order by rsc.star_count desc + limit 8 + ` + + rows, err := e.Query(query) + if err != nil { + return nil, err + } + defer rows.Close() + + var repoUris []string + for rows.Next() { + var repoUri string + err := rows.Scan(&repoUri) + if err != nil { + return nil, err + } + repoUris = append(repoUris, repoUri) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + if len(repoUris) == 0 { + return []Repo{}, nil + } + + // get full repo data + repos, err := GetRepos(e, 0, FilterIn("at_uri", repoUris)) + if err != nil { + return nil, err + } + + // sort repos by the original trending order + repoMap := make(map[string]Repo) + for _, repo := range repos { + repoMap[repo.RepoAt().String()] = repo + } + + orderedRepos := make([]Repo, 0, len(repoUris)) + for _, uri := range repoUris { + if repo, exists := repoMap[uri]; exists { + orderedRepos = append(orderedRepos, repo) + } + } + + return orderedRepos, nil +} diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 24c46689..93fa441b 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -302,7 +302,16 @@ type TimelineParams struct { } func (p *Pages) Timeline(w io.Writer, params TimelineParams) error { - return p.execute("timeline", w, params) + return p.execute("timeline/timeline", w, params) +} + +type TopStarredReposLastWeekParams struct { + LoggedInUser *oauth.User + Repos []db.Repo +} + +func (p *Pages) TopStarredReposLastWeek(w io.Writer, params TopStarredReposLastWeekParams) error { + return p.executePlain("timeline/fragments/topStarredRepos", w, params) } type SettingsParams struct { diff --git a/appview/pages/templates/timeline/fragments/topStarredRepos.html b/appview/pages/templates/timeline/fragments/topStarredRepos.html new file mode 100644 index 00000000..e3fa2608 --- /dev/null +++ b/appview/pages/templates/timeline/fragments/topStarredRepos.html @@ -0,0 +1,25 @@ +{{ define "timeline/fragments/topStarredRepos" }} +
+
+

+ Trending + {{ i "trending-up" "size-4 flex-shrink-0" }} +

+
+
+ {{ range $index, $repo := .Repos }} +
+
+ {{ template "user/fragments/repoCard" (list $ $repo true) }} +
+
+ {{ else }} +
+
+ No trending repositories this week +
+
+ {{ end }} +
+
+{{ end }} diff --git a/appview/pages/templates/timeline.html b/appview/pages/templates/timeline/timeline.html similarity index 86% rename from appview/pages/templates/timeline.html rename to appview/pages/templates/timeline/timeline.html index ada04091..483de7b0 100644 --- a/appview/pages/templates/timeline.html +++ b/appview/pages/templates/timeline/timeline.html @@ -4,22 +4,46 @@ - + {{ end }} -{{ define "topbar" }} - {{ template "layouts/topbar" $ }} -{{ end }} + + {{ define "content" }} {{ with .LoggedInUser }} + {{ block "trending" . }}{{ end }} {{ block "timeline" $ }}{{ end }} {{ else }} {{ block "hero" $ }}{{ end }} + {{ block "trending" . }}{{ end }} {{ block "timeline" $ }}{{ end }} {{ end }} {{ end }} +{{ define "trending" }} + +
+ +
+
+

+ Trending + {{ i "trending-up" "size-4 flex-shrink-0" }} +

+
+
+
+ Loading... +
+
+
+{{ end }} + {{ define "hero" }}
tightly-knit
social coding.
diff --git a/appview/pages/templates/user/fragments/repoCard.html b/appview/pages/templates/user/fragments/repoCard.html index 9932d3bf..e5800dc3 100644 --- a/appview/pages/templates/user/fragments/repoCard.html +++ b/appview/pages/templates/user/fragments/repoCard.html @@ -14,9 +14,9 @@ {{ $repoOwner := resolve .Did }} {{- if $fullName -}} - {{ $repoOwner }}/{{ .Name }} + {{ $repoOwner }}/{{ .Name }} {{- else -}} - {{ .Name }} + {{ .Name }} {{- end -}}
{{ with .Description }} diff --git a/appview/state/router.go b/appview/state/router.go index cfb5e8cf..798c13e6 100644 --- a/appview/state/router.go +++ b/appview/state/router.go @@ -109,6 +109,7 @@ func (s *State) StandardRouter(mw *middleware.Middleware) http.Handler { r.Handle("/static/*", s.pages.Static()) r.Get("/", s.Timeline) + r.Get("/timeline/trending", s.TopStarredReposLastWeek) r.Route("/repo", func(r chi.Router) { r.Route("/new", func(r chi.Router) { diff --git a/appview/state/state.go b/appview/state/state.go index 89a59aae..2b9f4a26 100644 --- a/appview/state/state.go +++ b/appview/state/state.go @@ -199,6 +199,19 @@ func (s *State) Timeline(w http.ResponseWriter, r *http.Request) { }) } +func (s *State) TopStarredReposLastWeek(w http.ResponseWriter, r *http.Request) { + repos, err := db.GetTopStarredReposLastWeek(s.db) + if err != nil { + log.Println(err) + s.pages.Notice(w, "topstarredrepos", "Unable to load.") + return + } + + s.pages.TopStarredReposLastWeek(w, pages.TopStarredReposLastWeekParams{ + Repos: repos, + }) +} + func (s *State) Keys(w http.ResponseWriter, r *http.Request) { user := chi.URLParam(r, "user") user = strings.TrimPrefix(user, "@") -- 2.43.0