New user profile

This commit is contained in:
Eduard Urbach 2018-11-15 20:19:40 +09:00
parent a1c11a2eae
commit d5dff615c1
29 changed files with 271 additions and 141 deletions

View File

@ -1,19 +1,15 @@
component Comments(parent arn.PostParent, user *arn.User)
.thread
.posts
if user == nil && parent.CountPosts() == 0
p.no-data.mountable No comments have been written yet.
else
each post in parent.Posts()
Postable(post, user, true, "", "")
if user != nil
if arn.IsLocked(parent)
footer.footer.mountable
p.text-center= "This " + strings.ToLower(reflect.TypeOf(parent).Elem().Name()) + " is locked."
else
NewPostArea(user, "Comment")
.buttons
if !arn.IsLocked(parent)
NewPostActions(reflect.TypeOf(parent).Elem().Name(), parent.GetID(), false)
NewPostArea(parent, user, "Comment")
if user == nil && parent.CountPosts() == 0
p.no-data.mountable No comments have been written yet.
else
each post in parent.PostsRelevantFirst(5)
Postable(post, user, true, "", "")

View File

@ -1,4 +1,4 @@
component NewPostArea(user *arn.User, placeholder string)
component NewPostArea(parent arn.PostParent, user *arn.User, placeholder string)
#new-post.post.mountable
.post-parent
.post-author
@ -6,11 +6,18 @@ component NewPostArea(user *arn.User, placeholder string)
textarea#new-post-text.post-content(placeholder=placeholder + "...", aria-label=placeholder)
component NewPostActions(parentType string, parentID string, cancelButton bool)
#new-post-actions.buttons
button#reply-button.mountable.action(data-action="createPost", data-trigger="click", data-parent-type=parentType, data-parent-id=parentID)
if !arn.IsLocked(parent)
NewPostActions(parent, false)
component NewPostActions(parent arn.PostParent, cancelButton bool)
.buttons.new-post-actions
button#reply-button.mountable.action(data-action="createPost", data-trigger="click", data-parent-type=parent.TypeName(), data-parent-id=parent.GetID())
Icon("mail-reply")
span Reply
if parent.TypeName() == "Post" || parent.TypeName() == "Thread"
span= "Reply to " + parent.Creator().Nick
else
span Submit
if cancelButton
button#reply-cancel-button.mountable.action(data-action="cancelReply", data-trigger="click")

View File

@ -1,5 +1,5 @@
component Postable(post arn.Postable, user *arn.User, includeReplies bool, headerContent string, highlightAuthorID string)
.post.mountable(id=strings.ToLower(post.Type()) + "-" + fmt.Sprint(post.GetID()), data-pro=post.Creator().IsPro(), data-api="/api/" + strings.ToLower(post.Type()) + "/" + post.GetID())
.post.mountable(id=strings.ToLower(post.TypeName()) + "-" + fmt.Sprint(post.GetID()), data-pro=post.Creator().IsPro(), data-api="/api/" + strings.ToLower(post.TypeName()) + "/" + post.GetID())
.post-parent
.post-author
Avatar(post.Creator())
@ -12,7 +12,7 @@ component Postable(post arn.Postable, user *arn.User, includeReplies bool, heade
if user != nil && user.ID == post.Creator().ID
.post-edit-interface
if post.Type() == "Thread"
if post.TypeName() == "Thread"
input.post-title-input.hidden(id="title-" + post.GetID(), value=post.TitleByUser(user), type="text", placeholder="Thread title")
textarea.post-text-input.hidden(id="source-" + post.GetID())= post.GetText()
@ -48,7 +48,7 @@ component Postable(post arn.Postable, user *arn.User, includeReplies bool, heade
a.post-tool.post-edit.tip.action(data-action="editPost", data-trigger="click", data-id=post.GetID(), aria-label="Edit")
Icon("pencil")
if post.Type() != "Thread"
if post.TypeName() != "Thread"
if user != nil && (user.Role == "admin" || user.Role == "editor")
a.post-tool.post-delete.tip.action(data-action="deletePost", data-trigger="click", data-id=post.GetID(), aria-label="Delete")
Icon("trash")

View File

@ -37,7 +37,7 @@ func fetchActivities(user *arn.User, followedOnly bool) []arn.Activity {
return false
}
if activity.Type() == "ActivityCreate" {
if activity.TypeName() == "ActivityCreate" {
obj := activity.(*arn.ActivityCreate).Object()
if obj == nil {
@ -48,7 +48,7 @@ func fetchActivities(user *arn.User, followedOnly bool) []arn.Activity {
return !isDraftable || !draft.GetIsDraft()
}
if activity.Type() == "ActivityConsumeAnime" {
if activity.TypeName() == "ActivityConsumeAnime" {
return activity.(*arn.ActivityConsumeAnime).Anime() != nil
}

View File

@ -32,20 +32,20 @@ component Activity(activity arn.Activity, user *arn.User)
.post-content
.activity-header
.activity-parent
if activity.Type() == "ActivityCreate"
if activity.TypeName() == "ActivityCreate"
ActivityCreateTitle(activity.(*arn.ActivityCreate), user)
else if activity.Type() == "ActivityConsumeAnime"
else if activity.TypeName() == "ActivityConsumeAnime"
ActivityConsumeAnimeTitle(activity.(*arn.ActivityConsumeAnime), user)
if user != nil && user.ID == activity.GetCreatedBy() && activity.Type() == "ActivityConsumeAnime"
button.activity-action.tip.action(data-action="deleteObject", data-trigger="click", aria-label="Delete", data-return-path="/activity", data-confirm-type="activity", data-api=fmt.Sprintf("/api/%s/%s", strings.ToLower(activity.Type()), activity.GetID()))
if user != nil && user.ID == activity.GetCreatedBy() && activity.TypeName() == "ActivityConsumeAnime"
button.activity-action.tip.action(data-action="deleteObject", data-trigger="click", aria-label="Delete", data-return-path="/activity", data-confirm-type="activity", data-api=fmt.Sprintf("/api/%s/%s", strings.ToLower(activity.TypeName()), activity.GetID()))
RawIcon("trash")
.activity-date.utc-date(data-date=activity.GetCreated())
if activity.Type() == "ActivityCreate"
if activity.TypeName() == "ActivityCreate"
ActivityCreateText(activity.(*arn.ActivityCreate), user)
else if activity.Type() == "ActivityConsumeAnime"
else if activity.TypeName() == "ActivityConsumeAnime"
ActivityConsumeAnimeText(activity.(*arn.ActivityConsumeAnime), user)
component ActivityConsumeAnimeTitle(activity *arn.ActivityConsumeAnime, user *arn.User)

View File

@ -6,7 +6,6 @@
align-items center
margin 0.5rem
default-transition
transform scale(1)
:hover
.image-title

View File

@ -33,5 +33,5 @@ component CompareMAL(comparisons []*utils.MALComparison, year string, status str
.data-comparison-difference-detail= difference.DetailsA()
.data-comparison-difference-detail= difference.DetailsB()
button.data-comparison-difference-ignore.action(data-action="newAnimeDiffIgnore", data-trigger="click", data-id=arn.CreateDifferenceID(comparison.Anime.ID, "mal", comparison.MALAnime.ID, difference.Type()), data-hash=difference.Hash())
button.data-comparison-difference-ignore.action(data-action="newAnimeDiffIgnore", data-trigger="click", data-id=arn.CreateDifferenceID(comparison.Anime.ID, "mal", comparison.MALAnime.ID, difference.TypeName()), data-hash=difference.Hash())
RawIcon("trash")

View File

@ -19,5 +19,5 @@ func ReplyUI(ctx *aero.Context) string {
return ctx.Error(http.StatusNotFound, "Post not found", err)
}
return ctx.HTML(components.NewPostArea(user, "Reply") + components.NewPostActions(post.Type(), post.ID, true))
return ctx.HTML(components.NewPostArea(post, user, "Reply") + components.NewPostActions(post, true))
}

37
pages/profile/old.pixy Normal file
View File

@ -0,0 +1,37 @@
//- component ProfileTabs(viewUser *arn.User, uri string)
//- .tabs.mountable.never-unmount
//- Tab("Anime", "th", "/+" + viewUser.Nick)
//- Tab("Characters", "child", "/+" + viewUser.Nick + "/characters/liked")
//- Tab("Forum", "comment", "/+" + viewUser.Nick + "/forum/threads")
//- Tab("Tracks", "music", "/+" + viewUser.Nick + "/soundtracks/liked")
//- Tab("Quotes", "quote-left", "/+" + viewUser.Nick + "/quotes/liked")
//- Tab("Stats", "area-chart", "/+" + viewUser.Nick + "/stats")
//- Tab("Followers", "users", "/+" + viewUser.Nick + "/followers")
//- if strings.Contains(uri, "/soundtracks")
//- .tabs
//- Tab("Liked", "heart", "/+" + viewUser.Nick + "/soundtracks/liked")
//- Tab("Added", "plus", "/+" + viewUser.Nick + "/soundtracks/added")
//- if strings.Contains(uri, "/quotes")
//- .tabs
//- Tab("Liked", "heart", "/+" + viewUser.Nick + "/quotes/liked")
//- Tab("Added", "plus", "/+" + viewUser.Nick + "/quotes/added")
//- Anime shelf
//- if len(animeList.Items) == 0
//- p.no-data.mountable= viewUser.Nick + " hasn't added any anime yet."
//- else
//- .profile-watching-list.mountable
//- each item in animeList.Items
//- if item.Status == arn.AnimeListStatusWatching || item.Status == arn.AnimeListStatusCompleted
//- a.profile-watching-list-item.tip(href=item.Anime().Link(), aria-label=item.Anime().Title.ByUser(user) + " (" + fmt.Sprint(item.Episodes) + " / " + arn.EpisodesToString(item.Anime().EpisodeCount) + ")")
//- img.profile-watching-list-item-image.lazy(data-src=item.Anime().ImageLink("small"), data-webp="true", data-color=item.Anime().AverageColor(), alt=item.Anime().Title.ByUser(user), importance="high")
//- Footer
//- .footer
//- .buttons
//- if user != nil && (user.Role == "admin" || user.Role == "editor")
//- a.button.profile-action(href="/api/user/" + viewUser.ID, target="_blank", rel="noopener")
//- Icon("search-plus")
//- span JSON

View File

@ -1,12 +1,19 @@
package profile
import (
"sort"
"github.com/aerogo/aero"
"github.com/animenotifier/arn"
"github.com/animenotifier/notify.moe/components"
"github.com/animenotifier/notify.moe/utils"
)
const (
maxCharacters = 6
maxFriends = 7
)
// Get user profile page.
func Get(ctx *aero.Context) string {
nick := ctx.Get("nick")
@ -22,6 +29,8 @@ func Get(ctx *aero.Context) string {
// Profile renders the user profile page of the given viewUser.
func Profile(ctx *aero.Context, viewUser *arn.User) string {
user := utils.GetUser(ctx)
// Anime list
animeList := viewUser.AnimeList()
if user == nil || user.ID != viewUser.ID {
@ -30,6 +39,10 @@ func Profile(ctx *aero.Context, viewUser *arn.User) string {
animeList.SortByRating()
// Genres
topGenres := animeList.TopGenres(5)
// Open graph
openGraph := &arn.OpenGraph{
Tags: map[string]string{
"og:title": viewUser.Nick,
@ -46,7 +59,39 @@ func Profile(ctx *aero.Context, viewUser *arn.User) string {
},
}
ctx.Data = openGraph
// Friends
friends := viewUser.Follows().UsersWhoFollowBack()
return ctx.HTML(components.Profile(viewUser, user, animeList, ctx.URI()))
arn.SortUsersFollowers(friends)
if len(friends) > maxFriends {
friends = friends[:maxFriends]
}
// Characters
characters := []*arn.Character{}
for character := range arn.StreamCharacters() {
if arn.Contains(character.Likes, viewUser.ID) {
characters = append(characters, character)
}
}
sort.Slice(characters, func(i, j int) bool {
aLikes := len(characters[i].Likes)
bLikes := len(characters[j].Likes)
if aLikes == bLikes {
return characters[i].Name.Canonical < characters[j].Name.Canonical
}
return aLikes > bLikes
})
if len(characters) > maxCharacters {
characters = characters[:maxCharacters]
}
ctx.Data = openGraph
return ctx.HTML(components.Profile(viewUser, user, animeList, characters, friends, topGenres, ctx.URI()))
}

View File

@ -1,48 +1,53 @@
component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, uri string)
ProfileHeader(viewUser, user, uri)
component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, characters []*arn.Character, friends []*arn.User, topGenres []string, uri string)
.profile
ProfileHeader(viewUser, user, uri)
//- if len(animeList.Items) == 0
//- p.no-data.mountable= viewUser.Nick + " hasn't added any anime yet."
//- else
//- .profile-watching-list.mountable
//- each item in animeList.Items
//- if item.Status == arn.AnimeListStatusWatching || item.Status == arn.AnimeListStatusCompleted
//- a.profile-watching-list-item.tip(href=item.Anime().Link(), aria-label=item.Anime().Title.ByUser(user) + " (" + fmt.Sprint(item.Episodes) + " / " + arn.EpisodesToString(item.Anime().EpisodeCount) + ")")
//- img.profile-watching-list-item-image.lazy(data-src=item.Anime().ImageLink("small"), data-webp="true", data-color=item.Anime().AverageColor(), alt=item.Anime().Title.ByUser(user), importance="high")
.profile-columns
.profile-column.profile-favorites
.profile-section
h3.profile-column-header.mountable Anime
.profile-favorite-anime-container
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")
img.profile-favorite-anime-image.lazy(data-src=item.Anime().ImageLink("small"), data-webp=true, alt=item.Anime().Title.ByUser(user))
//- .footer
//- .buttons
//- if user != nil && (user.Role == "admin" || user.Role == "editor")
//- a.button.profile-action(href="/api/user/" + viewUser.ID, target="_blank", rel="noopener")
//- Icon("search-plus")
//- span JSON
.profile-section
h3.profile-column-header.mountable(data-mountable-type="favorites") Characters
.profile-favorite-characters-container
each character in characters
.mountable(data-mountable-type="favorites")
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))
component ProfileTabs(viewUser *arn.User, uri string)
.tabs.mountable.never-unmount
Tab("Anime", "th", "/+" + viewUser.Nick)
Tab("Characters", "child", "/+" + viewUser.Nick + "/characters/liked")
Tab("Forum", "comment", "/+" + viewUser.Nick + "/forum/threads")
Tab("Tracks", "music", "/+" + viewUser.Nick + "/soundtracks/liked")
Tab("Quotes", "quote-left", "/+" + viewUser.Nick + "/quotes/liked")
Tab("Stats", "area-chart", "/+" + viewUser.Nick + "/stats")
Tab("Followers", "users", "/+" + viewUser.Nick + "/followers")
if strings.Contains(uri, "/soundtracks")
.tabs
Tab("Liked", "heart", "/+" + viewUser.Nick + "/soundtracks/liked")
Tab("Added", "plus", "/+" + viewUser.Nick + "/soundtracks/added")
.profile-column.profile-activity
.profile-section
h3.profile-column-header.mountable(data-mountable-type="activity") Activity
Comments(viewUser, user)
.profile-column.profile-extra
.profile-section
h3.profile-column-header.mountable(data-mountable-type="extra") Genres
if strings.Contains(uri, "/quotes")
.tabs
Tab("Liked", "heart", "/+" + viewUser.Nick + "/quotes/liked")
Tab("Added", "plus", "/+" + viewUser.Nick + "/quotes/added")
.anime-genres
each genre in topGenres
a.anime-genre.mountable(href="/genre/" + strings.ToLower(genre), data-mountable-type="extra")= genre
.profile-section
h3.profile-column-header.mountable(data-mountable-type="extra") Friends
.profile-friends
each friend in friends
.profile-friend.mountable(data-mountable-type="extra")
Avatar(friend)
component ProfileHeader(viewUser *arn.User, user *arn.User, uri string)
ProfileHead(viewUser, user, uri)
//- ProfileTabs(viewUser, uri)
component ProfileHead(viewUser *arn.User, user *arn.User, uri string)
.profile
.profile-head
img.profile-cover.lazy(data-src=viewUser.CoverLink("large"), data-webp="true", alt="Cover image")
.profile-image-container.mountable.never-unmount
@ -137,5 +142,4 @@ component ProfileHead(viewUser *arn.User, user *arn.User, uri string)
else
button.profile-action.action.mountable.never-unmount(data-action="unfollowUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/remove/" + viewUser.ID)
Icon("user-times")
span Unfollow
span Unfollow

View File

@ -1,6 +1,6 @@
const profile-image-size = 280px
.profile
.profile-head
vertical
align-items center
@ -40,8 +40,59 @@ const profile-image-size = 280px
color pro-color
animation sk-pulse 1.5s infinite linear
.profile-columns
vertical
.profile-column
// border 1px solid red
// height 100px
padding calc(content-padding / 2)
.profile-column-header
font-style bold
margin-bottom 1rem
.profile-section
margin-bottom 1rem
.profile-favorite-anime-container
display grid
grid-template-columns repeat(auto-fill, anime-image-small-width)
grid-template-rows repeat(auto-fill, anime-image-small-height)
grid-gap 0.5rem
justify-content space-evenly
.profile-friends
display grid
grid-template-columns repeat(auto-fill, avatar-size)
grid-template-rows repeat(auto-fill, avatar-size)
grid-gap 0.5rem
margin 0 0.5rem
justify-content space-evenly
.profile-favorite-anime
// anime-mini-item
.profile-favorite-anime-image
// anime-mini-item-image
border-radius ui-element-border-radius
.profile-favorite-characters-container
display grid
grid-template-columns repeat(auto-fill, character-image-small-width)
grid-template-rows repeat(auto-fill, character-image-small-height)
grid-gap 0.5rem
justify-content space-evenly
// .profile-favorite-character
// margin 0.25rem
// .profile-favorite-character-image
// border-radius ui-element-border-radius
> 740px
.profile
.profile-head
horizontal
align-items stretch
@ -61,6 +112,10 @@ const profile-image-size = 280px
padding content-padding
margin-top 0
.profile-columns
display grid
grid-template-columns 27% 46% 27%
.profile-pro-status
position absolute
right 0

View File

@ -30,7 +30,7 @@ func Anime(ctx *aero.Context) string {
completed := animeList.FilterStatus(arn.AnimeListStatusCompleted)
// Genre affinity
bestGenres := getBestGenres(animeList)
bestGenres := animeList.TopGenres(bestGenreCount)
// Get all anime
var tv []*arn.Anime

View File

@ -1,43 +0,0 @@
package recommended
import (
"sort"
"github.com/animenotifier/arn"
)
// getBestGenres returns the most liked genres for the user's anime list.
func getBestGenres(animeList *arn.AnimeList) []string {
genreItems := animeList.Genres()
genreAffinity := map[string]float64{}
bestGenres := []string{}
for genre, animeListItems := range genreItems {
affinity := 0.0
for _, item := range animeListItems {
if item.Status != arn.AnimeListStatusCompleted {
continue
}
if item.Rating.Overall != 0 {
affinity += item.Rating.Overall
} else {
affinity += 5.0
}
}
genreAffinity[genre] = affinity
bestGenres = append(bestGenres, genre)
}
sort.Slice(bestGenres, func(i, j int) bool {
return genreAffinity[bestGenres[i]] > genreAffinity[bestGenres[j]]
})
if len(bestGenres) > bestGenreCount {
bestGenres = bestGenres[:bestGenreCount]
}
return bestGenres
}

View File

@ -19,5 +19,5 @@ func ReplyUI(ctx *aero.Context) string {
return ctx.Error(http.StatusNotFound, "Thread not found", err)
}
return ctx.HTML(components.NewPostArea(user, "Reply") + components.NewPostActions(thread.Type(), thread.ID, true))
return ctx.HTML(components.NewPostArea(thread, user, "Reply") + components.NewPostActions(thread, true))
}

View File

@ -11,11 +11,11 @@ component Thread(thread *arn.Thread, user *arn.User)
footer.footer.mountable
p.text-center This topic is locked.
else
NewPostArea(user, "Reply")
NewPostArea(thread, user, "Reply")
.buttons
if !thread.Locked
NewPostActions("Thread", thread.ID, false)
NewPostActions(thread, false)
if user.Role == "admin" || user.Role == "editor"
if thread.Locked

View File

@ -105,7 +105,7 @@ export async function reply(arn: AnimeNotifier, element: HTMLElement) {
}
// Delete old reply button
let oldPostActions = document.getElementById("new-post-actions")
let oldPostActions = document.getElementsByClassName("new-post-actions")[0]
if(oldPostActions) {
oldPostActions.remove()

View File

@ -159,6 +159,7 @@ export default class AnimeNotifier {
Promise.resolve().then(() => this.lazyLoad()),
Promise.resolve().then(() => this.displayLocalDates()),
Promise.resolve().then(() => this.setSelectBoxValue()),
Promise.resolve().then(() => this.textAreaFocus()),
Promise.resolve().then(() => this.markPlayingSoundTrack()),
Promise.resolve().then(() => this.assignActions()),
Promise.resolve().then(() => this.updatePushUI()),
@ -194,6 +195,26 @@ export default class AnimeNotifier {
}
}
textAreaFocus() {
const newPostText = document.getElementById("new-post-text") as HTMLTextAreaElement
if(!newPostText || newPostText["has-input-listener"]) {
return
}
newPostText.addEventListener("input", () => {
if(newPostText.value.length > 0) {
const newPostActions = document.getElementsByClassName("new-post-actions")[0]
newPostActions.classList.add("new-post-actions-enabled")
} else {
const newPostActions = document.getElementsByClassName("new-post-actions")[0]
newPostActions.classList.remove("new-post-actions-enabled")
}
})
newPostText["has-input-listener"] = true
}
async onIdle() {
// Register event listeners
document.addEventListener("keydown", this.onKeyDown.bind(this), false)
@ -1071,6 +1092,7 @@ export default class AnimeNotifier {
this.lazyLoad(findAllInside("lazy", element))
this.mountMountables(findAllInside("mountable", element))
this.assignTooltipOffsets(findAllInside("tip", element))
this.textAreaFocus()
}
scrollTo(target: HTMLElement) {

View File

@ -80,10 +80,18 @@ post-content-padding-y = 0.75rem
align-items flex-start
margin-right 0.5rem
#new-post-actions
horizontal
.new-post-actions
justify-content flex-end
opacity 0
height 0
transform translateY(-50%)
transition all transition-speed ease
.new-post-actions-enabled
opacity 1
height auto
margin-bottom 0.75rem
transform translateY(0)
// Toolbar

View File

@ -7,8 +7,8 @@ type CanonicalTitle struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *CanonicalTitle) Type() string {
// TypeName returns the diff type.
func (diff *CanonicalTitle) TypeName() string {
return "CanonicalTitle"
}

View File

@ -7,8 +7,8 @@ type EndDate struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *EndDate) Type() string {
// TypeName returns the diff type.
func (diff *EndDate) TypeName() string {
return "EndDate"
}

View File

@ -9,8 +9,8 @@ type EpisodeCount struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *EpisodeCount) Type() string {
// TypeName returns the diff type.
func (diff *EpisodeCount) TypeName() string {
return "EpisodeCount"
}

View File

@ -9,8 +9,8 @@ type Genres struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *Genres) Type() string {
// TypeName returns the diff type.
func (diff *Genres) TypeName() string {
return "Genres"
}

View File

@ -2,7 +2,7 @@ package animediff
// Difference describes a difference between two anime.
type Difference interface {
Type() string
TypeName() string
Explanation() string
DetailsA() string
DetailsB() string

View File

@ -7,8 +7,8 @@ type JapaneseTitle struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *JapaneseTitle) Type() string {
// TypeName returns the diff type.
func (diff *JapaneseTitle) TypeName() string {
return "JapaneseTitle"
}

View File

@ -7,8 +7,8 @@ type RomajiTitle struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *RomajiTitle) Type() string {
// TypeName returns the diff type.
func (diff *RomajiTitle) TypeName() string {
return "RomajiTitle"
}

View File

@ -7,8 +7,8 @@ type StartDate struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *StartDate) Type() string {
// TypeName returns the diff type.
func (diff *StartDate) TypeName() string {
return "StartDate"
}

View File

@ -7,8 +7,8 @@ type Status struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *Status) Type() string {
// TypeName returns the diff type.
func (diff *Status) TypeName() string {
return "Status"
}

View File

@ -7,8 +7,8 @@ type Synopsis struct {
NumericHash uint64
}
// Type returns the diff type.
func (diff *Synopsis) Type() string {
// TypeName returns the diff type.
func (diff *Synopsis) TypeName() string {
return "Synopsis"
}