Lazy load images
This commit is contained in:
parent
79ba7ecf3b
commit
b6c4968c6c
@ -1,14 +1,14 @@
|
|||||||
component InputText(id string, value string, label string, placeholder string)
|
component InputText(id string, value string, label string, placeholder string)
|
||||||
.widget-input
|
.widget-input
|
||||||
label(for=id)= label + ":"
|
label(for=id)= label + ":"
|
||||||
input.widget-element.action(id=id, type="text", value=value, placeholder=placeholder, data-action="save", data-trigger="change")
|
input.widget-element.action(id=id, type="text", value=value, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
|
||||||
|
|
||||||
component InputTextArea(id string, value string, label string, placeholder string)
|
component InputTextArea(id string, value string, label string, placeholder string)
|
||||||
.widget-input
|
.widget-input
|
||||||
label(for=id)= label + ":"
|
label(for=id)= label + ":"
|
||||||
textarea.widget-element.action(id=id, placeholder=placeholder, data-action="save", data-trigger="change")= value
|
textarea.widget-element.action(id=id, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")= value
|
||||||
|
|
||||||
component InputNumber(id string, value int, label string, placeholder string, min string, max string)
|
component InputNumber(id string, value int, label string, placeholder string, min string, max string)
|
||||||
.widget-input
|
.widget-input
|
||||||
label(for=id)= label + ":"
|
label(for=id)= label + ":"
|
||||||
input.widget-element.action(id=id, type="number", value=value, min=min, max=max, placeholder=placeholder, data-action="save", data-trigger="change")
|
input.widget-element.action(id=id, type="number", value=value, min=min, max=max, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
|
@ -159,8 +159,10 @@ component Anime(anime *arn.Anime, user *arn.User)
|
|||||||
//- if providers.AnimePlanet
|
//- if providers.AnimePlanet
|
||||||
//- a.light-button(href="http://www.anime-planet.com/anime/" + providers.AnimePlanet.providerId, target="_blank") AnimePlanet
|
//- a.light-button(href="http://www.anime-planet.com/anime/" + providers.AnimePlanet.providerId, target="_blank") AnimePlanet
|
||||||
|
|
||||||
.sources
|
.footer
|
||||||
p Powered by Kitsu.
|
a(href="/api/anime/" + anime.ID) Anime API
|
||||||
|
span |
|
||||||
|
span Powered by Kitsu.
|
||||||
//- if descriptionSource
|
//- if descriptionSource
|
||||||
//- span= " Summary by " + summarySource + "."
|
//- span= " Summary by " + summarySource + "."
|
||||||
//- //-
|
//- //-
|
||||||
|
@ -87,10 +87,11 @@
|
|||||||
.anime-rating-categories
|
.anime-rating-categories
|
||||||
vertical
|
vertical
|
||||||
|
|
||||||
.sources
|
.footer
|
||||||
font-size 0.8rem
|
font-size 0.8rem
|
||||||
opacity 0.5
|
opacity 0.7
|
||||||
margin-top 0.5rem
|
margin-top 0.5rem
|
||||||
|
text-align center
|
||||||
|
|
||||||
.relations
|
.relations
|
||||||
horizontal-wrap
|
horizontal-wrap
|
||||||
|
@ -84,6 +84,6 @@ component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList,
|
|||||||
.spacer
|
.spacer
|
||||||
.post-likes= len(post.Likes)
|
.post-likes= len(post.Likes)
|
||||||
|
|
||||||
if user != nil && user.Role == "admin"
|
|
||||||
.side-note
|
.footer
|
||||||
a(href="/api/user/" + viewUser.ID)= "API: ", viewUser.Nick
|
a(href="/api/user/" + viewUser.ID) User API
|
@ -1,7 +1,7 @@
|
|||||||
component Settings(user *arn.User)
|
component Settings(user *arn.User)
|
||||||
h2.page-title Settings
|
h2.page-title Settings
|
||||||
.widgets(data-api="/api/user/" + user.ID)
|
.widgets
|
||||||
.widget.mountable
|
.widget.mountable(data-api="/api/user/" + user.ID)
|
||||||
h3.widget-title
|
h3.widget-title
|
||||||
Icon("user")
|
Icon("user")
|
||||||
span Personal
|
span Personal
|
||||||
@ -10,11 +10,19 @@ component Settings(user *arn.User)
|
|||||||
InputText("Tagline", user.Tagline, "Tagline", "Text that appears below your username")
|
InputText("Tagline", user.Tagline, "Tagline", "Text that appears below your username")
|
||||||
InputText("Website", user.Website, "Website", "Your homepage")
|
InputText("Website", user.Website, "Website", "Your homepage")
|
||||||
|
|
||||||
.widget.mountable
|
.widget.mountable(data-api="/api/user/" + user.ID)
|
||||||
h3.widget-title
|
h3.widget-title
|
||||||
Icon("cubes")
|
Icon("cubes")
|
||||||
span Accounts
|
span Accounts
|
||||||
|
|
||||||
InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co")
|
InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co")
|
||||||
InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net")
|
InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net")
|
||||||
InputText("Accounts.Kitsu.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io")
|
InputText("Accounts.AnimePlanet.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io")
|
||||||
|
InputText("Accounts.AnimePlanet.Nick", user.Accounts.AnimePlanet.Nick, "AnimePlanet", "Your username on anime-planet.com")
|
||||||
|
|
||||||
|
.widget.mountable(data-api="/api/settings/" + user.ID)
|
||||||
|
h3.widget-title
|
||||||
|
Icon("cogs")
|
||||||
|
span Settings
|
||||||
|
|
||||||
|
InputText("TitleLanguage", user.Settings().TitleLanguage, "Title language", "Language of anime titles")
|
@ -5,9 +5,21 @@ import * as actions from "./actions"
|
|||||||
|
|
||||||
export class AnimeNotifier {
|
export class AnimeNotifier {
|
||||||
app: Application
|
app: Application
|
||||||
|
visibilityObserver: IntersectionObserver
|
||||||
|
|
||||||
constructor(app: Application) {
|
constructor(app: Application) {
|
||||||
this.app = app
|
this.app = app
|
||||||
|
this.visibilityObserver = new IntersectionObserver(
|
||||||
|
entries => {
|
||||||
|
for(let entry of entries) {
|
||||||
|
if(entry.intersectionRatio > 0) {
|
||||||
|
entry.target["became visible"]()
|
||||||
|
this.visibilityObserver.unobserve(entry.target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
onReadyStateChange() {
|
onReadyStateChange() {
|
||||||
@ -24,6 +36,15 @@ export class AnimeNotifier {
|
|||||||
this.app.run()
|
this.app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onContentLoaded() {
|
||||||
|
this.visibilityObserver.disconnect()
|
||||||
|
|
||||||
|
// Update each of these asynchronously
|
||||||
|
Promise.resolve().then(() => this.updateMountables())
|
||||||
|
Promise.resolve().then(() => this.updateActions())
|
||||||
|
Promise.resolve().then(() => this.lazyLoadImages())
|
||||||
|
}
|
||||||
|
|
||||||
reloadContent() {
|
reloadContent() {
|
||||||
return fetch("/_" + this.app.currentPath, {
|
return fetch("/_" + this.app.currentPath, {
|
||||||
credentials: "same-origin"
|
credentials: "same-origin"
|
||||||
@ -57,9 +78,24 @@ export class AnimeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAvatars() {
|
lazyLoadImages() {
|
||||||
for(let element of findAll("user-image")) {
|
for(let element of findAll("user-image")) {
|
||||||
let img = element as HTMLImageElement
|
this.lazyLoadImage(element as HTMLImageElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let element of findAll("anime-cover-image")) {
|
||||||
|
this.lazyLoadImage(element as HTMLImageElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazyLoadImage(img: HTMLImageElement) {
|
||||||
|
// Prevent browser from loading it instantly
|
||||||
|
img["original source"] = img.src
|
||||||
|
img.src = ""
|
||||||
|
|
||||||
|
// Once the image becomes visible, load it
|
||||||
|
img["became visible"] = () => {
|
||||||
|
img.src = img["original source"]
|
||||||
|
|
||||||
if(img.naturalWidth === 0) {
|
if(img.naturalWidth === 0) {
|
||||||
img.onload = function() {
|
img.onload = function() {
|
||||||
@ -73,6 +109,8 @@ export class AnimeNotifier {
|
|||||||
img.classList.add("user-image-found")
|
img.classList.add("user-image-found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.visibilityObserver.observe(img)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMountables() {
|
updateMountables() {
|
||||||
@ -94,13 +132,6 @@ export class AnimeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onContentLoaded() {
|
|
||||||
// Update each of these asynchronously
|
|
||||||
Promise.resolve().then(() => this.updateMountables())
|
|
||||||
Promise.resolve().then(() => this.updateAvatars())
|
|
||||||
Promise.resolve().then(() => this.updateActions())
|
|
||||||
}
|
|
||||||
|
|
||||||
onPopState(e: PopStateEvent) {
|
onPopState(e: PopStateEvent) {
|
||||||
if(e.state) {
|
if(e.state) {
|
||||||
this.app.load(e.state, {
|
this.app.load(e.state, {
|
||||||
|
Loading…
Reference in New Issue
Block a user