Added final null checks

This commit is contained in:
Eduard Urbach 2019-04-22 15:59:08 +09:00
parent 70a62f06e5
commit 480ba3a370
8 changed files with 145 additions and 93 deletions

View File

@ -17,18 +17,14 @@ var correctResponseRendered = {
"company": false "company": false
} }
// Search types
var searchTypes = Object.keys(correctResponseRendered)
// Save old term to compare // Save old term to compare
var oldTerm = "" var oldTerm = ""
// Containers for all the search results // Containers for all the search results
var animeSearchResults: HTMLElement var results = new Map<string, HTMLElement>()
var characterSearchResults: HTMLElement
var postsSearchResults: HTMLElement
var threadsSearchResults: HTMLElement
var soundtrackSearchResults: HTMLElement
var userSearchResults: HTMLElement
var amvSearchResults: HTMLElement
var companySearchResults: HTMLElement
// Delay before a request is sent // Delay before a request is sent
const searchDelay = 140 const searchDelay = 140
@ -60,14 +56,9 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
oldTerm = term oldTerm = term
// Reset // Reset
correctResponseRendered.anime = false for(let key of searchTypes) {
correctResponseRendered.character = false correctResponseRendered[key] = false
correctResponseRendered.posts = false }
correctResponseRendered.threads = false
correctResponseRendered.soundtrack = false
correctResponseRendered.user = false
correctResponseRendered.amv = false
correctResponseRendered.company = false
// Set browser URL // Set browser URL
let url = "/search/" + term let url = "/search/" + term
@ -109,15 +100,11 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
return return
} }
if(!animeSearchResults) { if(!results["anime"]) {
animeSearchResults = document.getElementById("anime-search-results") for(let key of searchTypes) {
characterSearchResults = document.getElementById("character-search-results") results[key] = document.getElementById(`${key}-search-results`)
postsSearchResults = document.getElementById("posts-search-results") }
threadsSearchResults = document.getElementById("threads-search-results")
soundtrackSearchResults = document.getElementById("soundtrack-search-results")
userSearchResults = document.getElementById("user-search-results")
amvSearchResults = document.getElementById("amv-search-results")
companySearchResults = document.getElementById("company-search-results")
searchPageTitle = document.getElementsByTagName("h1")[0] searchPageTitle = document.getElementsByTagName("h1")[0]
} }
@ -129,9 +116,9 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
return return
} }
// Start searching // Start searching anime
fetch("/_/anime-search/" + term, fetchOptions) fetch("/_/anime-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "anime", animeSearchResults)) .then(showResponseInElement(arn, url, "anime", results["anime"]))
.catch(console.error) .catch(console.error)
requestIdleCallback(() => { requestIdleCallback(() => {
@ -140,33 +127,16 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
return return
} }
fetch("/_/character-search/" + term, fetchOptions) // Search the other types (everything except anime)
.then(showResponseInElement(arn, url, "character", characterSearchResults)) for(let key of searchTypes) {
.catch(console.error) if(key === "anime") {
continue
}
fetch("/_/posts-search/" + term, fetchOptions) fetch(`/_/${key}-search/` + term, fetchOptions)
.then(showResponseInElement(arn, url, "posts", postsSearchResults)) .then(showResponseInElement(arn, url, key, results[key]))
.catch(console.error) .catch(console.error)
}
fetch("/_/threads-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "threads", threadsSearchResults))
.catch(console.error)
fetch("/_/soundtrack-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "soundtrack", soundtrackSearchResults))
.catch(console.error)
fetch("/_/user-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "user", userSearchResults))
.catch(console.error)
fetch("/_/amv-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "amv", amvSearchResults))
.catch(console.error)
fetch("/_/company-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "company", companySearchResults))
.catch(console.error)
}) })
} catch(err) { } catch(err) {
console.error(err) console.error(err)
@ -180,9 +150,9 @@ function showResponseInElement(arn: AnimeNotifier, url: string, typeName: string
let html = await response.text() let html = await response.text()
if(html.includes("no-search-results")) { if(html.includes("no-search-results")) {
Diff.mutations.queue(() => element.parentElement.classList.add("search-section-disabled")) Diff.mutations.queue(() => (element.parentElement as HTMLElement).classList.add("search-section-disabled"))
} else { } else {
Diff.mutations.queue(() => element.parentElement.classList.remove("search-section-disabled")) Diff.mutations.queue(() => (element.parentElement as HTMLElement).classList.remove("search-section-disabled"))
} }
if(arn.app.currentPath !== url) { if(arn.app.currentPath !== url) {
@ -236,7 +206,6 @@ export function searchBySpeech(arn: AnimeNotifier, element: HTMLElement) {
recognition.onend = e => { recognition.onend = e => {
searchInput.placeholder = oldPlaceholder searchInput.placeholder = oldPlaceholder
element.classList.remove("speech-listening") element.classList.remove("speech-listening")
recognition = null
} }
// Focus search field // Focus search field

View File

@ -3,11 +3,16 @@ import { applyTheme } from "./Theme"
// Save new data from an input field // Save new data from an input field
export async function save(arn: AnimeNotifier, input: HTMLElement) { export async function save(arn: AnimeNotifier, input: HTMLElement) {
if(!input.dataset.field) {
console.error("Input element missing data-field:", input)
return
}
let obj = {} let obj = {}
let isContentEditable = input.isContentEditable let isContentEditable = input.isContentEditable
let value = isContentEditable ? input.textContent : (input as HTMLInputElement).value let value = isContentEditable ? input.textContent : (input as HTMLInputElement).value
if(value === undefined) { if(value === undefined || value === null) {
return return
} }
@ -61,6 +66,11 @@ export async function save(arn: AnimeNotifier, input: HTMLElement) {
// Enable (bool field) // Enable (bool field)
export async function enable(arn: AnimeNotifier, button: HTMLButtonElement) { export async function enable(arn: AnimeNotifier, button: HTMLButtonElement) {
if(!button.dataset.field) {
console.error("Button missing data-field:", button)
return
}
let obj = {} let obj = {}
let apiEndpoint = arn.findAPIEndpoint(button) let apiEndpoint = arn.findAPIEndpoint(button)
@ -84,6 +94,11 @@ export async function enable(arn: AnimeNotifier, button: HTMLButtonElement) {
// Disable (bool field) // Disable (bool field)
export async function disable(arn: AnimeNotifier, button: HTMLButtonElement) { export async function disable(arn: AnimeNotifier, button: HTMLButtonElement) {
if(!button.dataset.field) {
console.error("Button missing data-field:", button)
return
}
let obj = {} let obj = {}
let apiEndpoint = arn.findAPIEndpoint(button) let apiEndpoint = arn.findAPIEndpoint(button)
@ -106,18 +121,21 @@ export async function disable(arn: AnimeNotifier, button: HTMLButtonElement) {
} }
// Append new element to array // Append new element to array
export function arrayAppend(arn: AnimeNotifier, element: HTMLElement) { export async function arrayAppend(arn: AnimeNotifier, element: HTMLElement) {
let field = element.dataset.field let field = element.dataset.field
let object = element.dataset.object || "" let object = element.dataset.object || ""
let apiEndpoint = arn.findAPIEndpoint(element) let apiEndpoint = arn.findAPIEndpoint(element)
arn.post(apiEndpoint + "/field/" + field + "/append", object) try {
.then(() => arn.reloadContent()) await arn.post(apiEndpoint + "/field/" + field + "/append", object)
.catch(err => arn.statusMessage.showError(err)) await arn.reloadContent()
} catch(err) {
arn.statusMessage.showError(err)
}
} }
// Remove element from array // Remove element from array
export function arrayRemove(arn: AnimeNotifier, element: HTMLElement) { export async function arrayRemove(arn: AnimeNotifier, element: HTMLElement) {
if(!confirm("Are you sure you want to remove this element?")) { if(!confirm("Are you sure you want to remove this element?")) {
return return
} }
@ -126,9 +144,12 @@ export function arrayRemove(arn: AnimeNotifier, element: HTMLElement) {
let index = element.dataset.index let index = element.dataset.index
let apiEndpoint = arn.findAPIEndpoint(element) let apiEndpoint = arn.findAPIEndpoint(element)
arn.post(apiEndpoint + "/field/" + field + "/remove/" + index) try {
.then(() => arn.reloadContent()) await arn.post(apiEndpoint + "/field/" + field + "/remove/" + index)
.catch(err => arn.statusMessage.showError(err)) await arn.reloadContent()
} catch(err) {
arn.statusMessage.showError(err)
}
} }
// Increase episode // Increase episode
@ -137,10 +158,16 @@ export function increaseEpisode(arn: AnimeNotifier, element: HTMLElement) {
return return
} }
let prev = element.previousSibling as HTMLElement let prev = element.previousSibling
if(prev === null || !(prev instanceof HTMLElement) || prev.textContent === null) {
console.error("Previous sibling is invalid:", element)
return
}
let episodes = parseInt(prev.textContent) let episodes = parseInt(prev.textContent)
prev.textContent = String(episodes + 1) prev.textContent = String(episodes + 1)
save(arn, prev) return save(arn, prev)
} }
// Add number // Add number
@ -149,6 +176,11 @@ export function addNumber(arn: AnimeNotifier, element: HTMLElement) {
return return
} }
if(!element.dataset.id || !element.dataset.add) {
console.error("Element is missing the data-id or data-add attribute:", element)
return
}
let input = document.getElementById(element.dataset.id) as HTMLInputElement let input = document.getElementById(element.dataset.id) as HTMLInputElement
let add = parseInt(element.dataset.add) let add = parseInt(element.dataset.add)
let num = parseInt(input.value) let num = parseInt(input.value)
@ -167,5 +199,5 @@ export function addNumber(arn: AnimeNotifier, element: HTMLElement) {
} }
input.value = newValue.toString() input.value = newValue.toString()
save(arn, input) return save(arn, input)
} }

View File

@ -36,8 +36,19 @@ export function chargeUp(arn: AnimeNotifier, button: HTMLElement) {
// Toggle fade // Toggle fade
export function toggleFade(arn: AnimeNotifier, button: HTMLElement) { export function toggleFade(arn: AnimeNotifier, button: HTMLElement) {
let elementId = button.dataset.elementId let elementId = button.dataset.elementId
if(!elementId) {
console.error("Missing element ID:", elementId)
return
}
let element = document.getElementById(elementId) let element = document.getElementById(elementId)
if(!element) {
console.error("Invalid element ID:", elementId)
return
}
if(element.classList.contains("fade-out")) { if(element.classList.contains("fade-out")) {
element.classList.remove("fade-out") element.classList.remove("fade-out")
} else { } else {

View File

@ -2,5 +2,6 @@ import AnimeNotifier from "../AnimeNotifier"
// Toggle sidebar // Toggle sidebar
export function toggleSidebar(arn: AnimeNotifier) { export function toggleSidebar(arn: AnimeNotifier) {
document.getElementById("sidebar").classList.toggle("sidebar-visible") let sidebar = document.getElementById("sidebar") as HTMLElement
sidebar.classList.toggle("sidebar-visible")
} }

View File

@ -3,26 +3,31 @@ import { bytesHumanReadable, uploadWithProgress } from "../Utils"
// Select file // Select file
export function selectFile(arn: AnimeNotifier, button: HTMLButtonElement) { export function selectFile(arn: AnimeNotifier, button: HTMLButtonElement) {
if(button.dataset.endpoint === "/api/upload/cover" && arn.user.dataset.pro !== "true") { let fileType = button.dataset.type
let endpoint = button.dataset.endpoint
if(endpoint === "/api/upload/cover" && arn.user && arn.user.dataset.pro !== "true") {
alert("Please buy a PRO account to use this feature.") alert("Please buy a PRO account to use this feature.")
return return
} }
let fileType = button.dataset.type
let endpoint = button.dataset.endpoint
// Click on virtual file input element // Click on virtual file input element
let input = document.createElement("input") let input = document.createElement("input")
input.setAttribute("type", "file") input.setAttribute("type", "file")
input.value = null input.value = ""
input.onchange = async () => { input.onchange = async () => {
let file = input.files[0] if(!fileType || !endpoint) {
console.error("Missing data-type or data-endpoint:", button)
if(!file) {
return return
} }
if(!input.files || input.files.length === 0) {
return
}
let file = input.files[0]
// Check mime type for images // Check mime type for images
if(fileType === "image" && !file.type.startsWith("image/")) { if(fileType === "image" && !file.type.startsWith("image/")) {
arn.statusMessage.showError(file.name + " is not an image file!") arn.statusMessage.showError(file.name + " is not an image file!")
@ -171,7 +176,7 @@ function previewImage(dataURL: string, endpoint: string, previews: HTMLCollectio
// Update sidebar avatar // Update sidebar avatar
function updateSideBarAvatar(url: string) { function updateSideBarAvatar(url: string) {
let sidebar = document.getElementById("sidebar") let sidebar = document.getElementById("sidebar") as HTMLElement
let userImage = sidebar.getElementsByClassName("user-image")[0] as HTMLImageElement let userImage = sidebar.getElementsByClassName("user-image")[0] as HTMLImageElement
let lazyLoad = userImage["became visible"] let lazyLoad = userImage["became visible"]

View File

@ -3,21 +3,28 @@ import Diff from "scripts/Diff"
// Follow user // Follow user
export async function followUser(arn: AnimeNotifier, element: HTMLElement) { export async function followUser(arn: AnimeNotifier, element: HTMLElement) {
try { return updateFollow(arn, element, "You are now following")
await arn.post(element.dataset.api)
await arn.reloadContent()
arn.statusMessage.showInfo("You are now following " + document.getElementById("nick").textContent + ".")
} catch(err) {
arn.statusMessage.showError(err)
}
} }
// Unfollow user // Unfollow user
export async function unfollowUser(arn: AnimeNotifier, element: HTMLElement) { export async function unfollowUser(arn: AnimeNotifier, element: HTMLElement) {
return updateFollow(arn, element, "You stopped following")
}
// Update follow
async function updateFollow(arn: AnimeNotifier, element: HTMLElement, message: string) {
let api = element.dataset.api
let nick = document.getElementById("nick")
if(!api || !nick || !nick.textContent) {
console.error("Missing data-api or invalid nick:", element)
return
}
try { try {
await arn.post(element.dataset.api) await arn.post(api)
await arn.reloadContent() await arn.reloadContent()
arn.statusMessage.showInfo("You stopped following " + document.getElementById("nick").textContent + ".") arn.statusMessage.showInfo(`${message} ${nick.textContent}.`)
} catch(err) { } catch(err) {
arn.statusMessage.showError(err) arn.statusMessage.showError(err)
} }

View File

@ -2,9 +2,21 @@ import AnimeNotifier from "../AnimeNotifier"
// Toggle play video // Toggle play video
export function togglePlayVideo(arn: AnimeNotifier, element: HTMLElement) { export function togglePlayVideo(arn: AnimeNotifier, element: HTMLElement) {
let container = document.getElementById(element.dataset.mediaId) let mediaId = element.dataset.mediaId
let video = container.getElementsByTagName("video")[0]
if(!mediaId) {
console.error("Missing data-media-id:", element)
return
}
let container = document.getElementById(mediaId)
if(!container) {
console.error("Invalid data-media-id:", element)
return
}
let video = container.getElementsByTagName("video")[0]
video.volume = arn.audioPlayer.volume video.volume = arn.audioPlayer.volume
if(video.readyState >= 2) { if(video.readyState >= 2) {
@ -30,7 +42,19 @@ function togglePlayVideoElement(video: HTMLVideoElement) {
// Toggle fullscreen // Toggle fullscreen
export function toggleFullscreen(arn: AnimeNotifier, button: HTMLElement) { export function toggleFullscreen(arn: AnimeNotifier, button: HTMLElement) {
let elementId = button.dataset.id let elementId = button.dataset.id
if(!elementId) {
console.error("Missing data-id:", button)
return
}
let element = document.getElementById(elementId) let element = document.getElementById(elementId)
if(!element) {
console.error("Invalid data-id:", button)
return
}
let requestFullscreen = element.requestFullscreen || element["mozRequestFullScreen"] || element["webkitRequestFullScreen"] || element["msRequestFullscreen"] let requestFullscreen = element.requestFullscreen || element["mozRequestFullScreen"] || element["webkitRequestFullScreen"] || element["msRequestFullscreen"]
let exitFullscreen = document.exitFullscreen || document["mozCancelFullScreen"] || document["webkitExitFullscreen"] || document["msExitFullscreen"] let exitFullscreen = document.exitFullscreen || document["mozCancelFullScreen"] || document["webkitExitFullscreen"] || document["msExitFullscreen"]
let fullscreen = document.fullscreen || document["webkitIsFullScreen"] || document["mozFullScreen"] let fullscreen = document.fullscreen || document["webkitIsFullScreen"] || document["mozFullScreen"]

View File

@ -1474,7 +1474,7 @@ export default class AnimeNotifier {
} }
// This is called every time an uncaught JavaScript error is thrown // This is called every time an uncaught JavaScript error is thrown
onError(evt: ErrorEvent) { async onError(evt: ErrorEvent) {
let report = { let report = {
message: evt.message, message: evt.message,
stack: evt.error.stack, stack: evt.error.stack,
@ -1483,8 +1483,11 @@ export default class AnimeNotifier {
columnNumber: evt.colno, columnNumber: evt.colno,
} }
this.post("/api/new/clienterrorreport", report) try {
.then(() => console.log("Successfully reported the error to the website staff.")) await this.post("/api/new/clienterrorreport", report)
.catch(() => console.warn("Failed reporting the error to the website staff.")) console.log("Successfully reported the error to the website staff.")
} catch(err) {
console.warn("Failed reporting the error to the website staff:", err)
}
} }
} }