Cleanup and analytics

This commit is contained in:
Eduard Urbach 2017-06-30 17:51:17 +02:00
parent fde816b897
commit 7d189b3914
6 changed files with 122 additions and 83 deletions

View File

@ -13,6 +13,8 @@ component Layout(app *aero.Application, ctx *aero.Context, user *arn.User, conte
#content-container #content-container
main#content.fade!= content main#content.fade!= content
LoadingAnimation LoadingAnimation
if user != nil
#user(data-id=user.ID)
script(src="/scripts") script(src="/scripts")
component LoadingAnimation component LoadingAnimation

View File

@ -1,31 +1,17 @@
import { Application } from "./Application" import { Application } from "./Application"
import { Diff } from "./Diff" import { Diff } from "./Diff"
import { findAll, delay } from "./utils" import { displayLocalDate } from "./DateView"
import * as actions from "./actions" import { findAll, delay } from "./Utils"
import * as actions from "./Actions"
var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
]
var dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]
export class AnimeNotifier { export class AnimeNotifier {
app: Application app: Application
visibilityObserver: IntersectionObserver visibilityObserver: IntersectionObserver
user: HTMLElement
constructor(app: Application) { constructor(app: Application) {
this.app = app this.app = app
this.user = null
if("IntersectionObserver" in window) { if("IntersectionObserver" in window) {
// Enable lazy load // Enable lazy load
@ -52,6 +38,19 @@ export class AnimeNotifier {
} }
} }
init() {
document.addEventListener("readystatechange", this.onReadyStateChange.bind(this))
document.addEventListener("DOMContentLoaded", this.onContentLoaded.bind(this))
document.addEventListener("keydown", this.onKeyDown.bind(this), false)
window.addEventListener("popstate", this.onPopState.bind(this))
if("requestIdleCallback" in window) {
window["requestIdleCallback"](this.onIdle.bind(this))
} else {
this.onIdle()
}
}
onReadyStateChange() { onReadyStateChange() {
if(document.readyState !== "interactive") { if(document.readyState !== "interactive") {
return return
@ -61,22 +60,52 @@ export class AnimeNotifier {
} }
run() { run() {
this.user = this.app.find("user")
this.app.content = this.app.find("content") this.app.content = this.app.find("content")
this.app.loading = this.app.find("loading") this.app.loading = this.app.find("loading")
this.app.run() this.app.run()
} }
onContentLoaded() { onContentLoaded() {
// Stop watching all the objects from the previous page.
this.visibilityObserver.disconnect() this.visibilityObserver.disconnect()
// Update each of these asynchronously Promise.resolve().then(() => this.mountMountables()),
Promise.resolve().then(() => this.mountMountables()) Promise.resolve().then(() => this.lazyLoadImages()),
Promise.resolve().then(() => this.lazyLoadImages()) Promise.resolve().then(() => this.displayLocalDates()),
Promise.resolve().then(() => this.displayLocalDates()) Promise.resolve().then(() => this.setSelectBoxValue()),
Promise.resolve().then(() => this.setSelectBoxValue())
Promise.resolve().then(() => this.assignActions()) Promise.resolve().then(() => this.assignActions())
} }
onIdle() {
if(!this.user) {
return
}
let analytics = {
general: {
timezoneOffset: new Date().getTimezoneOffset()
},
screen: {
width: screen.width,
height: screen.height,
availableWidth: screen.availWidth,
availableHeight: screen.availHeight,
pixelRatio: window.devicePixelRatio
},
system: {
cpuCount: navigator.hardwareConcurrency,
platform: navigator.platform
}
}
fetch("/api/analytics/new", {
method: "POST",
credentials: "same-origin",
body: JSON.stringify(analytics)
})
}
setSelectBoxValue() { setSelectBoxValue() {
for(let element of document.getElementsByTagName("select")) { for(let element of document.getElementsByTagName("select")) {
element.value = element.getAttribute("value") element.value = element.getAttribute("value")
@ -84,54 +113,10 @@ export class AnimeNotifier {
} }
displayLocalDates() { displayLocalDates() {
const oneDay = 24 * 60 * 60 * 1000
const now = new Date() const now = new Date()
for(let element of findAll("utc-date")) { for(let element of findAll("utc-date")) {
let startDate = new Date(element.dataset.startDate) displayLocalDate(element, now)
let endDate = new Date(element.dataset.endDate)
let h = startDate.getHours()
let m = startDate.getMinutes()
let startTime = (h <= 9 ? "0" + h : h) + ":" + (m <= 9 ? "0" + m : m)
h = endDate.getHours()
m = endDate.getMinutes()
let endTime = (h <= 9 ? "0" + h : h) + ":" + (m <= 9 ? "0" + m : m)
let dayDifference = Math.round((startDate.getTime() - now.getTime()) / oneDay)
if(isNaN(dayDifference)) {
element.style.opacity = "0"
continue
}
let dayInfo = dayNames[startDate.getDay()] + ", " + monthNames[startDate.getMonth()] + " " + startDate.getDate()
let airingVerb = "will be airing"
switch(dayDifference) {
case 0:
element.innerText = "Today"
break
case 1:
element.innerText = "Tomorrow"
break
case -1:
element.innerText = "Yesterday"
break
default:
let text = Math.abs(dayDifference) + " days"
if(dayDifference < 0) {
text += " ago"
airingVerb = "aired"
} else {
element.innerText = text
}
}
element.title = "Episode " + element.dataset.episodeNumber + " " + airingVerb + " " + startTime + " - " + endTime + " your time"
} }
} }
@ -298,14 +283,4 @@ export class AnimeNotifier {
e.stopPropagation() e.stopPropagation()
} }
} }
// onResize(e: UIEvent) {
// let hasScrollbar = this.app.content.clientHeight === this.app.content.scrollHeight
// if(hasScrollbar) {
// this.app.content.classList.add("has-scrollbar")
// } else {
// this.app.content.classList.remove("has-scrollbar")
// }
// }
} }

65
scripts/DateView.ts Normal file
View File

@ -0,0 +1,65 @@
const oneDay = 24 * 60 * 60 * 1000
export var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
]
export var dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]
export function displayLocalDate(element: HTMLElement, now: Date) {
let startDate = new Date(element.dataset.startDate)
let endDate = new Date(element.dataset.endDate)
let h = startDate.getHours()
let m = startDate.getMinutes()
let startTime = (h <= 9 ? "0" + h : h) + ":" + (m <= 9 ? "0" + m : m)
h = endDate.getHours()
m = endDate.getMinutes()
let endTime = (h <= 9 ? "0" + h : h) + ":" + (m <= 9 ? "0" + m : m)
let dayDifference = Math.round((startDate.getTime() - now.getTime()) / oneDay)
if(isNaN(dayDifference)) {
element.style.opacity = "0"
return
}
let dayInfo = dayNames[startDate.getDay()] + ", " + monthNames[startDate.getMonth()] + " " + startDate.getDate()
let airingVerb = "will be airing"
switch(dayDifference) {
case 0:
element.innerText = "Today"
break
case 1:
element.innerText = "Tomorrow"
break
case -1:
element.innerText = "Yesterday"
break
default:
let text = Math.abs(dayDifference) + " days"
if(dayDifference < 0) {
text += " ago"
airingVerb = "aired"
} else {
element.innerText = text
}
}
element.title = "Episode " + element.dataset.episodeNumber + " " + airingVerb + " " + startTime + " - " + endTime + " your time"
}

View File

@ -4,7 +4,4 @@ import { AnimeNotifier } from "./AnimeNotifier"
let app = new Application() let app = new Application()
let arn = new AnimeNotifier(app) let arn = new AnimeNotifier(app)
document.addEventListener("readystatechange", arn.onReadyStateChange.bind(arn)) arn.init()
document.addEventListener("DOMContentLoaded", arn.onContentLoaded.bind(arn))
document.addEventListener("keydown", arn.onKeyDown.bind(arn), false)
window.addEventListener("popstate", arn.onPopState.bind(arn))