Implemented activity grid on user profiles
This commit is contained in:
parent
755081d1ed
commit
5a56183e1b
@ -2,6 +2,7 @@ package profile
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/aerogo/aero"
|
||||
"github.com/animenotifier/arn"
|
||||
@ -68,6 +69,39 @@ func Profile(ctx *aero.Context, viewUser *arn.User) string {
|
||||
friends = friends[:maxFriends]
|
||||
}
|
||||
|
||||
// Activities
|
||||
activities := arn.FilterActivities(func(activity arn.Activity) bool {
|
||||
return activity.GetCreatedBy() == viewUser.ID
|
||||
})
|
||||
|
||||
// Time zone offset
|
||||
var timeZoneOffset time.Duration
|
||||
analytics := viewUser.Analytics()
|
||||
|
||||
if analytics != nil {
|
||||
timeZoneOffset = time.Duration(-analytics.General.TimezoneOffset) * time.Minute
|
||||
}
|
||||
|
||||
now := time.Now().UTC().Add(timeZoneOffset)
|
||||
weekDay := int(now.Weekday())
|
||||
currentYearDay := int(now.YearDay())
|
||||
|
||||
// Day offset is the number of days we need to reach Sunday
|
||||
dayOffset := 0
|
||||
|
||||
if weekDay > 0 {
|
||||
dayOffset = 7 - weekDay
|
||||
}
|
||||
|
||||
dayToActivityCount := map[int]int{}
|
||||
|
||||
for _, activity := range activities {
|
||||
activityTime := activity.GetCreatedTime().Add(timeZoneOffset)
|
||||
activityYearDay := activityTime.YearDay()
|
||||
days := currentYearDay - activityYearDay
|
||||
dayToActivityCount[days+dayOffset]++
|
||||
}
|
||||
|
||||
// Characters
|
||||
characters := []*arn.Character{}
|
||||
|
||||
@ -93,5 +127,5 @@ func Profile(ctx *aero.Context, viewUser *arn.User) string {
|
||||
}
|
||||
|
||||
ctx.Data = openGraph
|
||||
return ctx.HTML(components.Profile(viewUser, user, animeList, characters, friends, topGenres, ctx.URI()))
|
||||
return ctx.HTML(components.Profile(viewUser, user, animeList, characters, friends, topGenres, dayToActivityCount, ctx.URI()))
|
||||
}
|
||||
|
@ -1,30 +1,32 @@
|
||||
component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, characters []*arn.Character, friends []*arn.User, topGenres []string, uri string)
|
||||
component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, characters []*arn.Character, friends []*arn.User, topGenres []string, dayToActivityCount map[int]int, uri string)
|
||||
.profile
|
||||
ProfileHeader(viewUser, user, uri)
|
||||
|
||||
.profile-columns
|
||||
//- Favorites
|
||||
.profile-column.profile-favorites.mountable(data-mountable-type="column")
|
||||
//- Anime
|
||||
.profile-section
|
||||
h3.profile-column-header.mountable(data-mountable-type="favorites") Anime
|
||||
|
||||
if len(animeList.Items) == 0
|
||||
p.no-data.mountable(data-mountable-type="favorites") Nothing here yet.
|
||||
else
|
||||
.profile-favorite-anime-container
|
||||
.profile-favorite-anime-container.mountable(data-mountable-type="favorites")
|
||||
each item in animeList.Top(6)
|
||||
a.profile-favorite-anime.tip.mountable(href=item.Anime().Link(), aria-label=item.Anime().Title.ByUser(user), data-mountable-type="favorites")
|
||||
a.profile-favorite-anime.tip.mountable(href=item.Anime().Link(), aria-label=item.Anime().Title.ByUser(user), data-mountable-type="anime")
|
||||
img.profile-favorite-anime-image.lazy(data-src=item.Anime().ImageLink("small"), data-webp=true, alt=item.Anime().Title.ByUser(user))
|
||||
|
||||
//- Characters
|
||||
.profile-section
|
||||
h3.profile-column-header.mountable(data-mountable-type="favorites") Characters
|
||||
|
||||
if len(characters) == 0
|
||||
p.no-data.mountable(data-mountable-type="favorites") Nothing here yet.
|
||||
else
|
||||
.profile-favorite-characters-container
|
||||
.profile-favorite-characters-container.mountable(data-mountable-type="favorites")
|
||||
each character in characters
|
||||
.mountable(data-mountable-type="favorites")
|
||||
.mountable(data-mountable-type="character")
|
||||
CharacterSmall(character, user)
|
||||
//- a.profile-favorite-character.tip.mountable(href=character.Link(), aria-label=character.Name.ByUser(user), data-mountable-type="favorite-anime")
|
||||
//- img.profile-favorite-character-image.lazy(data-src=character.ImageLink("small"), data-webp=true, alt=character.Name.ByUser(user))
|
||||
@ -37,27 +39,47 @@ component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList,
|
||||
|
||||
//- Extra
|
||||
.profile-column.profile-extra.mountable(data-mountable-type="column")
|
||||
//- Genres
|
||||
.profile-section
|
||||
h3.profile-column-header.mountable(data-mountable-type="extra") Genres
|
||||
|
||||
if len(topGenres) == 0
|
||||
p.no-data.mountable(data-mountable-type="extra") Nothing here yet.
|
||||
else
|
||||
.anime-genres
|
||||
.anime-genres.mountable(data-mountable-type="extra")
|
||||
each genre in topGenres
|
||||
a.anime-genre.mountable(href="/genre/" + strings.ToLower(genre), data-mountable-type="extra")= genre
|
||||
a.anime-genre.mountable(href="/genre/" + strings.ToLower(genre), data-mountable-type="genre")= genre
|
||||
|
||||
//- Friends
|
||||
.profile-section
|
||||
h3.profile-column-header.mountable(data-mountable-type="extra") Friends
|
||||
|
||||
if len(friends) == 0
|
||||
p.no-data.mountable(data-mountable-type="extra") Nothing here yet.
|
||||
else
|
||||
.profile-friends
|
||||
.profile-friends.mountable(data-mountable-type="extra")
|
||||
each friend in friends
|
||||
.profile-friend.mountable(data-mountable-type="extra")
|
||||
.profile-friend.mountable(data-mountable-type="friend")
|
||||
Avatar(friend)
|
||||
|
||||
//- Activity
|
||||
.profile-section
|
||||
h3.profile-column-header.mountable(data-mountable-type="extra") Activity
|
||||
|
||||
.profile-activities.mountable(data-mountable-type="extra")
|
||||
for month := 5; month >= 0; month--
|
||||
.activities-month
|
||||
for week := 3; week >= 0; week--
|
||||
.activities-week
|
||||
for day := 6; day >= 0; day--
|
||||
if dayToActivityCount[month * 28 + week * 7 + day] == 0
|
||||
.box.mountable(data-count="0", data-mountable-type=fmt.Sprintf("month-%d", month))
|
||||
else
|
||||
.box.tip.mountable(aria-label=fmt.Sprintf("%s: %s", time.Weekday((6 - day + 1) % 7).String(), stringutils.Plural(dayToActivityCount[month * 28 + week * 7 + day], "activity")), data-count=dayToActivityCount[month * 28 + week * 7 + day], data-mountable-type=fmt.Sprintf("month-%d", month))
|
||||
|
||||
if day == 2
|
||||
.spacer-box
|
||||
|
||||
component ProfileHeader(viewUser *arn.User, user *arn.User, uri string)
|
||||
ProfileHead(viewUser, user, uri)
|
||||
|
||||
|
@ -159,6 +159,39 @@ const profile-image-size = 280px
|
||||
// 100%
|
||||
// filter brightness(35%) blur(0)
|
||||
|
||||
.profile-activities
|
||||
horizontal
|
||||
|
||||
const month-margin = 0.4rem
|
||||
|
||||
.activities-month
|
||||
horizontal
|
||||
margin 0 calc(month-margin / 2)
|
||||
|
||||
.activities-week
|
||||
vertical
|
||||
|
||||
.box
|
||||
width 0.75rem
|
||||
height 0.75rem
|
||||
border-radius 1px
|
||||
margin 1px
|
||||
background hsla(link-color-h, link-color-s, link-color-l, 0.75)
|
||||
|
||||
:hover
|
||||
cursor pointer
|
||||
background link-hover-color
|
||||
|
||||
[data-count="0"]
|
||||
background reverse-light-color
|
||||
|
||||
:hover
|
||||
cursor default
|
||||
background reverse-light-color
|
||||
|
||||
.spacer-box
|
||||
height month-margin
|
||||
|
||||
.profile-image
|
||||
object-fit cover
|
||||
width 100%
|
||||
|
Loading…
Reference in New Issue
Block a user