appview: allow timeline db queries to be filterable by users follows #626

closed
opened by willdot.net targeting master from willdot.net/tangled-core: feat/filter-user-timeline

Signed-off-by: Will Andrews did:plc:dadhhalkfcq3gucaq25hjqon

Changed files
+57 -12
appview
db
pages
templates
timeline
fragments
+38 -10
appview/db/timeline.go
···
// 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
}
···
return isStarred, starCount
}
-
func getTimelineRepos(e Execer, limit int, loggedInUserDid string) ([]models.TimelineEvent, error) {
-
repos, err := GetRepos(e, limit)
+
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, filters...)
if err != nil {
return nil, err
}
···
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
}
···
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
}
+1
appview/pages/pages.go
···
LoggedInUser *oauth.User
Timeline []models.TimelineEvent
Repos []models.Repo
+
Filtered bool
}
func (p *Pages) Timeline(w io.Writer, params TimelineParams) error {
+18 -2
appview/pages/templates/timeline/fragments/timeline.html
···
{{ define "timeline/fragments/timeline" }}
<div class="py-4">
-
<div class="px-6 pb-4">
-
<p class="text-xl font-bold dark:text-white">Timeline</p>
+
+
<div class="flex gap-2 px-6 pb-4">
+
<div>
+
<p class="text-xl font-bold dark:text-white">Timeline</p>
+
</div>
+
{{ if .LoggedInUser }}
+
<div>
+
{{ if .Filtered }}
+
<a href="/timeline" class="hover:underline text-sm">
+
Show All
+
</a>
+
{{ else }}
+
<a href="/timeline?filtered=true" class="hover:underline text-sm">
+
Show following only
+
</a>
+
{{ end }}
+
</div>
+
{{ end }}
</div>
<div class="flex flex-col gap-4">