From f711cdb011bdfbdd5a46148db28d415dae484b50 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 12 Nov 2018 14:24:00 +0900 Subject: [PATCH] Seperated global and followed activity feed --- pages/activity/activity.go | 32 ++++++++++++++++--- pages/activity/activity.pixy | 29 +++++++++++++---- pages/activity/activity.scarlet | 9 +++++- pages/forum/forum.pixy | 2 +- pages/forum/forum.scarlet | 4 +-- pages/index/coreroutes/coreroutes.go | 3 +- .../activity-recreate-from-log.go | 10 ++++-- scripts/Actions/Activity.ts | 6 ++++ scripts/Actions/index.ts | 1 + scripts/ServerEvents.ts | 22 +++++++++++++ scripts/Utils/plural.ts | 14 +++++++- utils/routetests/All.go | 2 +- 12 files changed, 114 insertions(+), 20 deletions(-) create mode 100644 scripts/Actions/Activity.ts diff --git a/pages/activity/activity.go b/pages/activity/activity.go index 63222266..9940cff6 100644 --- a/pages/activity/activity.go +++ b/pages/activity/activity.go @@ -9,11 +9,33 @@ import ( const maxActivitiesPerPage = 40 -// Get activity page. -func Get(ctx *aero.Context) string { +// Global activity page. +func Global(ctx *aero.Context) string { user := utils.GetUser(ctx) + activities := fetchActivities(user, false) + return ctx.HTML(components.ActivityFeed(activities, user)) +} + +// Followed activity page. +func Followed(ctx *aero.Context) string { + user := utils.GetUser(ctx) + activities := fetchActivities(user, true) + return ctx.HTML(components.ActivityFeed(activities, user)) +} + +// fetchActivities filters the activities by the given filters. +func fetchActivities(user *arn.User, followedOnly bool) []arn.Activity { + var followedUserIDs []string + + if followedOnly && user != nil { + followedUserIDs = user.Follows().Items + } activities := arn.FilterActivities(func(activity arn.Activity) bool { + if followedOnly && !arn.Contains(followedUserIDs, activity.GetCreatedBy()) { + return false + } + if activity.Type() == "ActivityCreate" { obj := activity.(*arn.ActivityCreate).Object() @@ -21,8 +43,8 @@ func Get(ctx *aero.Context) string { return false } - draft, isDraftable := obj.(arn.HasDraft) - return !isDraftable || !draft.IsDraft + draft, isDraftable := obj.(arn.Draftable) + return !isDraftable || !draft.GetIsDraft() } if activity.Type() == "ActivityConsumeAnime" { @@ -38,5 +60,5 @@ func Get(ctx *aero.Context) string { activities = activities[:maxActivitiesPerPage] } - return ctx.HTML(components.ActivityFeed(activities, user)) + return activities } diff --git a/pages/activity/activity.pixy b/pages/activity/activity.pixy index 60337cde..fa15215a 100644 --- a/pages/activity/activity.pixy +++ b/pages/activity/activity.pixy @@ -1,12 +1,25 @@ component ActivityFeed(entries []arn.Activity, user *arn.User) - h1 Activity + h1.page-title Activity + + .tabs + Tab("Global", "globe", "/activity") + Tab("Followed", "user-plus", "/activity/followed") .activities - each entry in entries - Activity(entry, user) + if len(entries) == 0 + p.no-data.mountable No activity here. + else + each entry in entries + Activity(entry, user) + + #load-new-activities(data-count="0") + .buttons + button.page-main-action.action(data-action="reloadContent", data-trigger="click") + Icon("refresh") + span#load-new-activities-text 0 new activities component Activity(activity arn.Activity, user *arn.User) - .activity.post-parent(id=fmt.Sprintf("activity-%s", activity.GetID())) + .activity.post-parent.mountable(id=fmt.Sprintf("activity-%s", activity.GetID())) .post-author Avatar(activity.Creator()) .post-content @@ -29,19 +42,23 @@ component ActivityConsumeAnimeTitle(activity *arn.ActivityConsumeAnime, user *ar component ActivityConsumeAnimeText(activity *arn.ActivityConsumeAnime, user *arn.User) if activity.ToEpisode > activity.FromEpisode - em= fmt.Sprintf("watched episodes %d - %d", activity.FromEpisode, activity.ToEpisode) + em.actvity-text-consume-anime= fmt.Sprintf("watched episodes %d - %d", activity.FromEpisode, activity.ToEpisode) else - em= fmt.Sprintf("watched episode %d", activity.ToEpisode) + em.actvity-text-consume-anime= fmt.Sprintf("watched episode %d", activity.ToEpisode) component ActivityCreateTitle(activity *arn.ActivityCreate, user *arn.User) if activity.ObjectType == "Post" a(href=activity.Postable().Parent().Link())= activity.Postable().Parent().TitleByUser(user) else if activity.ObjectType == "Thread" a(href=activity.Postable().Link())= activity.Postable().TitleByUser(user) + else if activity.ObjectType == "AMV" || activity.ObjectType == "SoundTrack" || activity.ObjectType == "Quote" + a(href=activity.Object().(arn.PostParent).Link())= activity.Object().(arn.PostParent).TitleByUser(user) component ActivityCreateText(activity *arn.ActivityCreate, user *arn.User) if activity.ObjectType == "Post" || activity.ObjectType == "Thread" div!= activity.Postable().HTML() + else + em.actvity-text-create= "new " + strings.ToLower(activity.ObjectType) //- component ActivityFeed(entries []*arn.EditLogEntry, user *arn.User) //- h1 Activity diff --git a/pages/activity/activity.scarlet b/pages/activity/activity.scarlet index b19f5fb8..d139d014 100644 --- a/pages/activity/activity.scarlet +++ b/pages/activity/activity.scarlet @@ -14,4 +14,11 @@ flex 1 .activity-date - color hsla(text-color-h, text-color-s, text-color-l, 0.5) \ No newline at end of file + color hsla(text-color-h, text-color-s, text-color-l, 0.5) + +.actvity-text-create + opacity 0.8 + +#load-new-activities + [data-count="0"] + display none \ No newline at end of file diff --git a/pages/forum/forum.pixy b/pages/forum/forum.pixy index a0eab6be..3ffe966c 100644 --- a/pages/forum/forum.pixy +++ b/pages/forum/forum.pixy @@ -7,7 +7,7 @@ component Forum(tag string, threads []*arn.Thread, threadsPerPage int) ThreadList(threads) .buttons - button#new-thread.action(data-action="load", data-trigger="click", data-url="/new/thread") + button#new-thread.page-main-action.action(data-action="load", data-trigger="click", data-url="/new/thread") Icon("plus") span New thread //- if len(threads) == threadsPerPage diff --git a/pages/forum/forum.scarlet b/pages/forum/forum.scarlet index 68aba8a8..a91ec9c9 100644 --- a/pages/forum/forum.scarlet +++ b/pages/forum/forum.scarlet @@ -1,13 +1,13 @@ .forum vertical align-items center - + .thread-link width 100% max-width forum-width > 1250px - #new-thread + .page-main-action position fixed right content-padding bottom content-padding diff --git a/pages/index/coreroutes/coreroutes.go b/pages/index/coreroutes/coreroutes.go index 60276157..3b573faa 100644 --- a/pages/index/coreroutes/coreroutes.go +++ b/pages/index/coreroutes/coreroutes.go @@ -20,7 +20,8 @@ func Register(l *layout.Layout) { l.Page("/login", login.Get) // Activity - l.Page("/activity", activity.Get) + l.Page("/activity", activity.Global) + l.Page("/activity/followed", activity.Followed) // Calendar l.Page("/calendar", calendar.Get) diff --git a/patches/activity-recreate-from-log/activity-recreate-from-log.go b/patches/activity-recreate-from-log/activity-recreate-from-log.go index 9508d5cc..664e2302 100644 --- a/patches/activity-recreate-from-log/activity-recreate-from-log.go +++ b/patches/activity-recreate-from-log/activity-recreate-from-log.go @@ -16,9 +16,15 @@ func main() { continue } - draft, isDraftable := obj.(arn.HasDraft) + draft, isDraftable := obj.(arn.Draftable) - if isDraftable && draft.IsDraft { + if isDraftable && draft.GetIsDraft() { + continue + } + + // We don't create activity entries for anything + // other than posts and threads. + if entry.ObjectType != "Post" && entry.ObjectType != "Thread" { continue } diff --git a/scripts/Actions/Activity.ts b/scripts/Actions/Activity.ts new file mode 100644 index 00000000..a3f06325 --- /dev/null +++ b/scripts/Actions/Activity.ts @@ -0,0 +1,6 @@ +import AnimeNotifier from "scripts/AnimeNotifier" + +// Reload content of current page +export function reloadContent(arn: AnimeNotifier) { + return arn.reloadContent() +} \ No newline at end of file diff --git a/scripts/Actions/index.ts b/scripts/Actions/index.ts index 226d5f6f..feede10f 100644 --- a/scripts/Actions/index.ts +++ b/scripts/Actions/index.ts @@ -1,3 +1,4 @@ +export * from "./Activity" export * from "./Audio" export * from "./AnimeList" export * from "./Diff" diff --git a/scripts/ServerEvents.ts b/scripts/ServerEvents.ts index 09f957cc..38b061bd 100644 --- a/scripts/ServerEvents.ts +++ b/scripts/ServerEvents.ts @@ -1,4 +1,5 @@ import AnimeNotifier from "./AnimeNotifier" +import { plural } from "./Utils" const reconnectDelay = 3000 @@ -35,6 +36,7 @@ export default class ServerEvents { this.eventSource.addEventListener("ping", (e: any) => this.ping(e)) this.eventSource.addEventListener("etag", (e: any) => this.etag(e)) + this.eventSource.addEventListener("activity", (e: any) => this.activity(e)) this.eventSource.addEventListener("notificationCount", (e: any) => this.notificationCount(e)) this.eventSource.onerror = () => { @@ -58,6 +60,26 @@ export default class ServerEvents { this.etags.set(data.url, newETag) } + activity(e: ServerEvent) { + if(!location.pathname.startsWith("/activity")) { + return + } + + let isFollowingUser = JSON.parse(e.data) + + // If we're on the followed only feed and we receive an activity + // about a user we don't follow, ignore the message. + if(location.pathname.startsWith("/activity/followed") && !isFollowingUser) { + return + } + + let button = document.getElementById("load-new-activities") + let buttonText = document.getElementById("load-new-activities-text") + let newCount = parseInt(button.dataset.count) + 1 + button.dataset.count = newCount.toString() + buttonText.textContent = plural(newCount, "new activity") + } + notificationCount(e: ServerEvent) { this.arn.notificationManager.setCounter(parseInt(e.data)) } diff --git a/scripts/Utils/plural.ts b/scripts/Utils/plural.ts index 8bb26612..f52a45f6 100644 --- a/scripts/Utils/plural.ts +++ b/scripts/Utils/plural.ts @@ -1,3 +1,15 @@ +const specialized = { + "new activity": "new activities" +} + export function plural(count: number, singular: string): string { - return (count === 1 || count === -1) ? (count + " " + singular) : (count + " " + singular + "s") + if(count === 1 || count === -1) { + return count + " " + singular + } + + if(specialized[singular]) { + return count + " " + specialized[singular] + } + + return count + " " + singular + "s" } \ No newline at end of file diff --git a/utils/routetests/All.go b/utils/routetests/All.go index 5ddc387d..ceb74462 100644 --- a/utils/routetests/All.go +++ b/utils/routetests/All.go @@ -67,7 +67,7 @@ var routeTests = map[string][]string{ }, "/user/:nick/animelist/watching/from/:index": []string{ - "/+Akyoto/animelist/watching/from/3", + "/+Akyoto/animelist/watching/from/1", }, "/user/:nick/animelist/completed": []string{