From 90dfc335cfa2227f5b3184c80a04cce3410e55cb Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Mon, 29 Sep 2025 05:41:46 +0100 Subject: [PATCH] appview: allow limiting timeline queries to just users that the requesting user is following Signed-off-by: Will Andrews --- appview/db/timeline.go | 44 +++++++++++++++++++++++++++++++++--------- appview/state/state.go | 4 ++-- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/appview/db/timeline.go b/appview/db/timeline.go index c74b1e4e..4ddf51f7 100644 --- a/appview/db/timeline.go +++ b/appview/db/timeline.go @@ -9,20 +9,33 @@ import ( // TODO: this gathers heterogenous events from different sources and aggregates // them in code; if we did this entirely in sql, we could order and limit and paginate easily -func MakeTimeline(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { +func MakeTimeline(e Execer, limit int, loggedInUserDid string, limitToUsersIsFollowing bool) ([]models.TimelineEvent, error) { var events []models.TimelineEvent - repos, err := getTimelineRepos(e, limit, loggedInUserDid) + var userIsFollowing []string + if limitToUsersIsFollowing { + following, err := GetFollowing(e, loggedInUserDid) + if err != nil { + return nil, err + } + + userIsFollowing = make([]string, 0, len(following)) + for _, follow := range following { + userIsFollowing = append(userIsFollowing, follow.SubjectDid) + } + } + + repos, err := getTimelineRepos(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } - stars, err := getTimelineStars(e, limit, loggedInUserDid) + stars, err := getTimelineStars(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } - follows, err := getTimelineFollows(e, limit, loggedInUserDid) + follows, err := getTimelineFollows(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } @@ -70,7 +83,11 @@ func getRepoStarInfo(repo *models.Repo, starStatuses map[string]bool) (bool, int return isStarred, starCount } -func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { +func getTimelineRepos(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("did", userIsFollowing)) + } repos, err := GetRepos(e, limit) if err != nil { return nil, err @@ -125,8 +142,13 @@ func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.Tim return events, nil } -func getTimelineStars(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { - stars, err := GetStars(e, limit) +func getTimelineStars(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("starred_by_did", userIsFollowing)) + } + + stars, err := GetStars(e, limit, filters...) if err != nil { return nil, err } @@ -166,8 +188,12 @@ func getTimelineStars(e Execer, limit int, loggedInUserDid string) ([]models.Tim return events, nil } -func getTimelineFollows(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { - follows, err := GetFollows(e, limit) +func getTimelineFollows(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("user_did", userIsFollowing)) + } + follows, err := GetFollows(e, limit, filters...) if err != nil { return nil, err } diff --git a/appview/state/state.go b/appview/state/state.go index 3658bfb7..ab4e6ce4 100644 --- a/appview/state/state.go +++ b/appview/state/state.go @@ -227,7 +227,7 @@ func (s *State) Timeline(w http.ResponseWriter, r *http.Request) { if user != nil { userDid = user.Did } - timeline, err := db.MakeTimeline(s.db, 50, userDid) + timeline, err := db.MakeTimeline(s.db, 50, userDid, false) if err != nil { log.Println(err) s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") @@ -286,7 +286,7 @@ func (s *State) UpgradeBanner(w http.ResponseWriter, r *http.Request) { } func (s *State) Home(w http.ResponseWriter, r *http.Request) { - timeline, err := db.MakeTimeline(s.db, 5, "") + timeline, err := db.MakeTimeline(s.db, 5, "", false) if err != nil { log.Println(err) s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") -- 2.43.0 From 315e38bf6c731dc7379f8058d20d28bf5fb25080 Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Mon, 29 Sep 2025 05:41:46 +0100 Subject: [PATCH] appview: allow limiting timeline queries to just users that the requesting user is following Signed-off-by: Will Andrews Signed-off-by: Will Andrews --- appview/db/timeline.go | 44 +++++++++++++++++++++++++++++++++--------- appview/state/state.go | 4 ++-- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/appview/db/timeline.go b/appview/db/timeline.go index c74b1e4e..4ddf51f7 100644 --- a/appview/db/timeline.go +++ b/appview/db/timeline.go @@ -9,20 +9,33 @@ import ( // TODO: this gathers heterogenous events from different sources and aggregates // them in code; if we did this entirely in sql, we could order and limit and paginate easily -func MakeTimeline(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { +func MakeTimeline(e Execer, limit int, loggedInUserDid string, limitToUsersIsFollowing bool) ([]models.TimelineEvent, error) { var events []models.TimelineEvent - repos, err := getTimelineRepos(e, limit, loggedInUserDid) + var userIsFollowing []string + if limitToUsersIsFollowing { + following, err := GetFollowing(e, loggedInUserDid) + if err != nil { + return nil, err + } + + userIsFollowing = make([]string, 0, len(following)) + for _, follow := range following { + userIsFollowing = append(userIsFollowing, follow.SubjectDid) + } + } + + repos, err := getTimelineRepos(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } - stars, err := getTimelineStars(e, limit, loggedInUserDid) + stars, err := getTimelineStars(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } - follows, err := getTimelineFollows(e, limit, loggedInUserDid) + follows, err := getTimelineFollows(e, limit, loggedInUserDid, userIsFollowing) if err != nil { return nil, err } @@ -70,7 +83,11 @@ func getRepoStarInfo(repo *models.Repo, starStatuses map[string]bool) (bool, int return isStarred, starCount } -func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { +func getTimelineRepos(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("did", userIsFollowing)) + } repos, err := GetRepos(e, limit) if err != nil { return nil, err @@ -125,8 +142,13 @@ func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.Tim return events, nil } -func getTimelineStars(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { - stars, err := GetStars(e, limit) +func getTimelineStars(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("starred_by_did", userIsFollowing)) + } + + stars, err := GetStars(e, limit, filters...) if err != nil { return nil, err } @@ -166,8 +188,12 @@ func getTimelineStars(e Execer, limit int, loggedInUserDid string) ([]models.Tim return events, nil } -func getTimelineFollows(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) { - follows, err := GetFollows(e, limit) +func getTimelineFollows(e Execer, limit int, loggedInUserDid string, userIsFollowing []string) ([]models.TimelineEvent, error) { + filters := make([]filter, 0) + if userIsFollowing != nil { + filters = append(filters, FilterIn("user_did", userIsFollowing)) + } + follows, err := GetFollows(e, limit, filters...) if err != nil { return nil, err } diff --git a/appview/state/state.go b/appview/state/state.go index 3658bfb7..ab4e6ce4 100644 --- a/appview/state/state.go +++ b/appview/state/state.go @@ -227,7 +227,7 @@ func (s *State) Timeline(w http.ResponseWriter, r *http.Request) { if user != nil { userDid = user.Did } - timeline, err := db.MakeTimeline(s.db, 50, userDid) + timeline, err := db.MakeTimeline(s.db, 50, userDid, false) if err != nil { log.Println(err) s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") @@ -286,7 +286,7 @@ func (s *State) UpgradeBanner(w http.ResponseWriter, r *http.Request) { } func (s *State) Home(w http.ResponseWriter, r *http.Request) { - timeline, err := db.MakeTimeline(s.db, 5, "") + timeline, err := db.MakeTimeline(s.db, 5, "", false) if err != nil { log.Println(err) s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.") -- 2.43.0