Added sorting options for anime lists

This commit is contained in:
Eduard Urbach 2019-08-29 12:23:58 +09:00
parent cdfb66657a
commit e28618029a
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
14 changed files with 153 additions and 134 deletions

View File

@ -156,63 +156,6 @@ func (list *AnimeList) User() *User {
return user
}
// Sort ...
func (list *AnimeList) Sort() {
list.Lock()
defer list.Unlock()
sort.Slice(list.Items, func(i, j int) bool {
a := list.Items[i]
b := list.Items[j]
if (a.Status != AnimeListStatusWatching && a.Status != AnimeListStatusPlanned) && (b.Status != AnimeListStatusWatching && b.Status != AnimeListStatusPlanned) {
if a.Rating.Overall == b.Rating.Overall {
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
}
return a.Rating.Overall > b.Rating.Overall
}
epsA := a.Anime().UpcomingEpisode()
epsB := b.Anime().UpcomingEpisode()
if epsA == nil && epsB == nil {
if a.Rating.Overall == b.Rating.Overall {
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
}
return a.Rating.Overall > b.Rating.Overall
}
if epsA == nil {
return false
}
if epsB == nil {
return true
}
return epsA.Episode.AiringDate.Start < epsB.Episode.AiringDate.Start
})
}
// SortByRating sorts the anime list by overall rating.
func (list *AnimeList) SortByRating() {
list.Lock()
defer list.Unlock()
sort.Slice(list.Items, func(i, j int) bool {
a := list.Items[i]
b := list.Items[j]
if a.Rating.Overall == b.Rating.Overall {
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
}
return a.Rating.Overall > b.Rating.Overall
})
}
// Top returns the top entries.
func (list *AnimeList) Top(count int) []*AnimeListItem {
list.Lock()

58
arn/AnimeListSort.go Normal file
View File

@ -0,0 +1,58 @@
package arn
import "sort"
// Sort sorts the anime list by the given algorithm.
func (list *AnimeList) Sort(algorithm string) {
list.Lock()
defer list.Unlock()
switch algorithm {
case SortByTitle:
sort.Slice(list.Items, func(i, j int) bool {
a := list.Items[i]
b := list.Items[j]
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
})
case SortByRating:
sort.Slice(list.Items, func(i, j int) bool {
a := list.Items[i]
b := list.Items[j]
if a.Rating.Overall == b.Rating.Overall {
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
}
return a.Rating.Overall > b.Rating.Overall
})
case SortByAiringDate:
sort.Slice(list.Items, func(i, j int) bool {
a := list.Items[i]
b := list.Items[j]
epsA := a.Anime().UpcomingEpisode()
epsB := b.Anime().UpcomingEpisode()
if epsA == nil && epsB == nil {
if a.Rating.Overall == b.Rating.Overall {
return a.Anime().Title.Canonical < b.Anime().Title.Canonical
}
return a.Rating.Overall > b.Rating.Overall
}
if epsA == nil {
return false
}
if epsB == nil {
return true
}
return epsA.Episode.AiringDate.Start < epsB.Episode.AiringDate.Start
})
}
}

View File

@ -30,10 +30,9 @@ const (
// Settings represents user settings.
type Settings struct {
UserID string `json:"userId"`
SortBy string `json:"sortBy"`
SortBy string `json:"sortBy" editable:"true"`
TitleLanguage string `json:"titleLanguage" editable:"true"`
Providers ServiceProviders `json:"providers"`
Avatar AvatarSettings `json:"avatar"`
Format FormatSettings `json:"format"`
Notification NotificationSettings `json:"notification"`
Editor EditorSettings `json:"editor"`
@ -110,30 +109,20 @@ type ServiceProviders struct {
Anime string `json:"anime"`
}
// AvatarSettings ...
type AvatarSettings struct {
Source string `json:"source" editable:"true"`
SourceURL string `json:"sourceUrl" editable:"true"`
}
// CalendarSettings ...
type CalendarSettings struct {
ShowAddedAnimeOnly bool `json:"showAddedAnimeOnly" editable:"true"`
}
// NewSettings ...
// NewSettings creates the default settings for a new user.
func NewSettings(user *User) *Settings {
return &Settings{
UserID: user.ID,
SortBy: SortByAiringDate,
SortBy: SortByRating,
TitleLanguage: TitleLanguageCanonical,
Providers: ServiceProviders{
Anime: "",
},
Avatar: AvatarSettings{
Source: "",
SourceURL: "",
},
Format: FormatSettings{
RatingsPrecision: 1,
},

View File

@ -0,0 +1,38 @@
.badge
horizontal
justify-content center
align-items center
background reverse-light-color
border-radius 50%
padding 0.5rem
color text-color
width 30px
height 30px
:hover
color text-color
background reverse-light-hover-color
.sidebar-badge
position absolute
top 50%
transform translateY(-50%)
:active
transform translateY(-50%) translateY(3px)
.left-badge
left 12%
.right-badge
right 12%
.badge-important
background badge-important-bg-color
color badge-important-text-color
font-weight bold
:hover
background badge-important-hover-bg-color
color badge-important-text-color
text-shadow none

View File

@ -65,42 +65,3 @@ const sidebar-spacing-y = 0.7rem
.icon
font-size 1rem
margin-right 0.75rem
.badge
horizontal
justify-content center
align-items center
background reverse-light-color
border-radius 50%
padding 0.5rem
color text-color
width 30px
height 30px
:hover
color text-color
background reverse-light-hover-color
.sidebar-badge
position absolute
top 50%
transform translateY(-50%)
:active
transform translateY(-50%) translateY(3px)
.left-badge
left 12%
.right-badge
right 12%
.badge-important
background badge-important-bg-color
color badge-important-text-color
font-weight bold
:hover
background badge-important-hover-bg-color
color badge-important-text-color
text-shadow none

View File

@ -17,18 +17,14 @@ component AnimeListScrollable(animeListItems []*arn.AnimeListItem, viewUser *arn
a(href=item.Link(viewUser.Nick))= item.Anime().Title.ByUser(user)
.anime-list-item-actions
if user != nil && item.Status != arn.AnimeListStatusCompleted && user.Location.CountryName != "Japan"
//- if user.ID == "KpdWUlPzR"
//- a(href=arn.Nyaa.GetLink(item.Anime()), title="Search on Nyaa", target="_blank", rel="noopener")
//- RawIcon("download")
//- else
if user != nil && item.Status != arn.AnimeListStatusCompleted
if item.Anime().EpisodeByNumber(item.Episodes + 1) != nil
for _, link := range item.Anime().EpisodeByNumber(item.Episodes + 1).Links
a.tip(href=link, aria-label="Watch episode " + fmt.Sprint(item.Episodes + 1), target="_blank", rel="noopener")
RawIcon("eye")
.anime-list-item-airing-date
if (item.Status == arn.AnimeListStatusWatching || item.Status == arn.AnimeListStatusPlanned) && item.Anime().UpcomingEpisode() != nil
if item.Status != arn.AnimeListStatusCompleted && item.Anime().UpcomingEpisode() != nil
span.utc-airing-date(data-start-date=item.Anime().UpcomingEpisode().Episode.AiringDate.Start, data-end-date=item.Anime().UpcomingEpisode().Episode.AiringDate.End, data-episode-number=item.Anime().UpcomingEpisode().Episode.Number)
if item.Status != arn.AnimeListStatusCompleted

View File

@ -22,11 +22,17 @@ const (
func Filter(ctx aero.Context) error {
user := utils.GetUser(ctx)
status := ctx.Get("status")
return AnimeList(ctx, user, status)
sortBy := arn.SortByRating
if user != nil {
sortBy = user.Settings().SortBy
}
return AnimeList(ctx, user, status, sortBy)
}
// AnimeList renders the anime list items.
func AnimeList(ctx aero.Context, user *arn.User, status string) error {
func AnimeList(ctx aero.Context, user *arn.User, status string, sortBy string) error {
nick := ctx.Get("nick")
index, _ := ctx.GetInt("index")
viewUser, err := arn.GetUserByNick(nick)
@ -50,9 +56,9 @@ func AnimeList(ctx aero.Context, user *arn.User, status string) error {
}
// Sort the items
statusList.Sort()
statusList.Sort(sortBy)
// These are all animer list items for the given status
// These are all anime list items for the given status
allItems := statusList.Items
// Slice the part that we need

View File

@ -33,7 +33,7 @@ func Get(ctx aero.Context) error {
}
watchingList := animeList.Watching()
watchingList.Sort()
watchingList.Sort(user.Settings().SortBy)
return ctx.HTML(components.BrowserExtension(watchingList, animeList.User(), user))
}

View File

@ -34,6 +34,11 @@ func Get(ctx aero.Context) error {
// Profile renders the user profile page of the given viewUser.
func Profile(ctx aero.Context, viewUser *arn.User) error {
user := utils.GetUser(ctx)
sortBy := arn.SortByRating
if user != nil {
sortBy = user.Settings().SortBy
}
// Anime list
animeList := viewUser.AnimeList()
@ -43,7 +48,7 @@ func Profile(ctx aero.Context, viewUser *arn.User) error {
}
completedList := animeList.FilterStatus(arn.AnimeListStatusCompleted)
completedList.SortByRating()
completedList.Sort(sortBy)
// Genres
topGenres := animeList.TopGenres(5)

View File

@ -7,7 +7,7 @@ component SettingsStyle(user *arn.User)
.widget.mountable(data-api="/api/settings/" + user.ID)
h3.widget-title
Icon("font")
span Style
span General
.widget-section
label(for="Theme")= "Theme:"
@ -24,7 +24,19 @@ component SettingsStyle(user *arn.User)
option(value="japanese") 日本語
InputNumber("Format.RatingsPrecision", float64(user.Settings().Format.RatingsPrecision), "Ratings precision", "How many decimals after the comma would you like to display in ratings on anime pages?", "0", "2", "1")
.widget.mountable(data-api="/api/settings/" + user.ID)
h3.widget-title
Icon("list")
span List
.widget-section
label(for="SortBy")= "Sort by:"
select.widget-ui-element.action(id="SortBy", data-field="SortBy", value=user.Settings().SortBy, title="Sorting algorithm for anime lists", data-action="save", data-trigger="change")
option(value="airing date") Airing date ⮞ Rating ⮞ Title
option(value="rating") Rating ⮞ Title
option(value="title") Title
if arn.IsDevelopment()
.widget.mountable(data-api="/api/settings/" + user.ID)
h3.widget-title

View File

@ -0,0 +1,15 @@
package main
import (
"github.com/animenotifier/notify.moe/arn"
)
func main() {
defer arn.Node.Close()
for user := range arn.StreamUsers() {
settings := user.Settings()
settings.SortBy = arn.SortByAiringDate
settings.Save()
}
}

View File

@ -3,14 +3,6 @@ html
font-family "Ubuntu", "Trebuchet MS", sans-serif
font-size 90%
// > 900px
// html
// font-size 90%
// > 1400px
// html
// font-size 95%
body
tab-size 4
overflow hidden

View File

@ -3,10 +3,9 @@ mixin ui-element
background ui-background
border-radius ui-element-border-radius
default-transition
:hover
border-color ui-hover-border-color
// background ui-hover-background
// box-shadow outline-shadow-medium
mixin ui-disabled
color button-color !important

View File

@ -7,6 +7,11 @@
box-sizing inherit
font inherit
// This breaks accessibility, but is needed to ensure a consistent style.
// Make sure you add your own focus styles.
::-moz-focus-inner
border 0
// Set root element to use border-box sizing,
// all sub-elements will inherit this property.
html