Added final null checks
This commit is contained in:
parent
70a62f06e5
commit
480ba3a370
@ -17,18 +17,14 @@ var correctResponseRendered = {
|
||||
"company": false
|
||||
}
|
||||
|
||||
// Search types
|
||||
var searchTypes = Object.keys(correctResponseRendered)
|
||||
|
||||
// Save old term to compare
|
||||
var oldTerm = ""
|
||||
|
||||
// Containers for all the search results
|
||||
var animeSearchResults: HTMLElement
|
||||
var characterSearchResults: HTMLElement
|
||||
var postsSearchResults: HTMLElement
|
||||
var threadsSearchResults: HTMLElement
|
||||
var soundtrackSearchResults: HTMLElement
|
||||
var userSearchResults: HTMLElement
|
||||
var amvSearchResults: HTMLElement
|
||||
var companySearchResults: HTMLElement
|
||||
var results = new Map<string, HTMLElement>()
|
||||
|
||||
// Delay before a request is sent
|
||||
const searchDelay = 140
|
||||
@ -60,14 +56,9 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
|
||||
oldTerm = term
|
||||
|
||||
// Reset
|
||||
correctResponseRendered.anime = false
|
||||
correctResponseRendered.character = false
|
||||
correctResponseRendered.posts = false
|
||||
correctResponseRendered.threads = false
|
||||
correctResponseRendered.soundtrack = false
|
||||
correctResponseRendered.user = false
|
||||
correctResponseRendered.amv = false
|
||||
correctResponseRendered.company = false
|
||||
for(let key of searchTypes) {
|
||||
correctResponseRendered[key] = false
|
||||
}
|
||||
|
||||
// Set browser URL
|
||||
let url = "/search/" + term
|
||||
@ -109,15 +100,11 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
|
||||
return
|
||||
}
|
||||
|
||||
if(!animeSearchResults) {
|
||||
animeSearchResults = document.getElementById("anime-search-results")
|
||||
characterSearchResults = document.getElementById("character-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")
|
||||
if(!results["anime"]) {
|
||||
for(let key of searchTypes) {
|
||||
results[key] = document.getElementById(`${key}-search-results`)
|
||||
}
|
||||
|
||||
searchPageTitle = document.getElementsByTagName("h1")[0]
|
||||
}
|
||||
|
||||
@ -129,9 +116,9 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
|
||||
return
|
||||
}
|
||||
|
||||
// Start searching
|
||||
// Start searching anime
|
||||
fetch("/_/anime-search/" + term, fetchOptions)
|
||||
.then(showResponseInElement(arn, url, "anime", animeSearchResults))
|
||||
.then(showResponseInElement(arn, url, "anime", results["anime"]))
|
||||
.catch(console.error)
|
||||
|
||||
requestIdleCallback(() => {
|
||||
@ -140,33 +127,16 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
|
||||
return
|
||||
}
|
||||
|
||||
fetch("/_/character-search/" + term, fetchOptions)
|
||||
.then(showResponseInElement(arn, url, "character", characterSearchResults))
|
||||
.catch(console.error)
|
||||
// Search the other types (everything except anime)
|
||||
for(let key of searchTypes) {
|
||||
if(key === "anime") {
|
||||
continue
|
||||
}
|
||||
|
||||
fetch("/_/posts-search/" + term, fetchOptions)
|
||||
.then(showResponseInElement(arn, url, "posts", postsSearchResults))
|
||||
.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))
|
||||
fetch(`/_/${key}-search/` + term, fetchOptions)
|
||||
.then(showResponseInElement(arn, url, key, results[key]))
|
||||
.catch(console.error)
|
||||
}
|
||||
})
|
||||
} catch(err) {
|
||||
console.error(err)
|
||||
@ -180,9 +150,9 @@ function showResponseInElement(arn: AnimeNotifier, url: string, typeName: string
|
||||
let html = await response.text()
|
||||
|
||||
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 {
|
||||
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) {
|
||||
@ -236,7 +206,6 @@ export function searchBySpeech(arn: AnimeNotifier, element: HTMLElement) {
|
||||
recognition.onend = e => {
|
||||
searchInput.placeholder = oldPlaceholder
|
||||
element.classList.remove("speech-listening")
|
||||
recognition = null
|
||||
}
|
||||
|
||||
// Focus search field
|
||||
|
@ -3,11 +3,16 @@ import { applyTheme } from "./Theme"
|
||||
|
||||
// Save new data from an input field
|
||||
export async function save(arn: AnimeNotifier, input: HTMLElement) {
|
||||
if(!input.dataset.field) {
|
||||
console.error("Input element missing data-field:", input)
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {}
|
||||
let isContentEditable = input.isContentEditable
|
||||
let value = isContentEditable ? input.textContent : (input as HTMLInputElement).value
|
||||
|
||||
if(value === undefined) {
|
||||
if(value === undefined || value === null) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -61,6 +66,11 @@ export async function save(arn: AnimeNotifier, input: HTMLElement) {
|
||||
|
||||
// Enable (bool field)
|
||||
export async function enable(arn: AnimeNotifier, button: HTMLButtonElement) {
|
||||
if(!button.dataset.field) {
|
||||
console.error("Button missing data-field:", button)
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {}
|
||||
let apiEndpoint = arn.findAPIEndpoint(button)
|
||||
|
||||
@ -84,6 +94,11 @@ export async function enable(arn: AnimeNotifier, button: HTMLButtonElement) {
|
||||
|
||||
// Disable (bool field)
|
||||
export async function disable(arn: AnimeNotifier, button: HTMLButtonElement) {
|
||||
if(!button.dataset.field) {
|
||||
console.error("Button missing data-field:", button)
|
||||
return
|
||||
}
|
||||
|
||||
let obj = {}
|
||||
let apiEndpoint = arn.findAPIEndpoint(button)
|
||||
|
||||
@ -106,18 +121,21 @@ export async function disable(arn: AnimeNotifier, button: HTMLButtonElement) {
|
||||
}
|
||||
|
||||
// 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 object = element.dataset.object || ""
|
||||
let apiEndpoint = arn.findAPIEndpoint(element)
|
||||
|
||||
arn.post(apiEndpoint + "/field/" + field + "/append", object)
|
||||
.then(() => arn.reloadContent())
|
||||
.catch(err => arn.statusMessage.showError(err))
|
||||
try {
|
||||
await arn.post(apiEndpoint + "/field/" + field + "/append", object)
|
||||
await arn.reloadContent()
|
||||
} catch(err) {
|
||||
arn.statusMessage.showError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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?")) {
|
||||
return
|
||||
}
|
||||
@ -126,9 +144,12 @@ export function arrayRemove(arn: AnimeNotifier, element: HTMLElement) {
|
||||
let index = element.dataset.index
|
||||
let apiEndpoint = arn.findAPIEndpoint(element)
|
||||
|
||||
arn.post(apiEndpoint + "/field/" + field + "/remove/" + index)
|
||||
.then(() => arn.reloadContent())
|
||||
.catch(err => arn.statusMessage.showError(err))
|
||||
try {
|
||||
await arn.post(apiEndpoint + "/field/" + field + "/remove/" + index)
|
||||
await arn.reloadContent()
|
||||
} catch(err) {
|
||||
arn.statusMessage.showError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Increase episode
|
||||
@ -137,10 +158,16 @@ export function increaseEpisode(arn: AnimeNotifier, element: HTMLElement) {
|
||||
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)
|
||||
prev.textContent = String(episodes + 1)
|
||||
save(arn, prev)
|
||||
return save(arn, prev)
|
||||
}
|
||||
|
||||
// Add number
|
||||
@ -149,6 +176,11 @@ export function addNumber(arn: AnimeNotifier, element: HTMLElement) {
|
||||
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 add = parseInt(element.dataset.add)
|
||||
let num = parseInt(input.value)
|
||||
@ -167,5 +199,5 @@ export function addNumber(arn: AnimeNotifier, element: HTMLElement) {
|
||||
}
|
||||
|
||||
input.value = newValue.toString()
|
||||
save(arn, input)
|
||||
return save(arn, input)
|
||||
}
|
@ -36,8 +36,19 @@ export function chargeUp(arn: AnimeNotifier, button: HTMLElement) {
|
||||
// Toggle fade
|
||||
export function toggleFade(arn: AnimeNotifier, button: HTMLElement) {
|
||||
let elementId = button.dataset.elementId
|
||||
|
||||
if(!elementId) {
|
||||
console.error("Missing element ID:", elementId)
|
||||
return
|
||||
}
|
||||
|
||||
let element = document.getElementById(elementId)
|
||||
|
||||
if(!element) {
|
||||
console.error("Invalid element ID:", elementId)
|
||||
return
|
||||
}
|
||||
|
||||
if(element.classList.contains("fade-out")) {
|
||||
element.classList.remove("fade-out")
|
||||
} else {
|
||||
|
@ -2,5 +2,6 @@ import AnimeNotifier from "../AnimeNotifier"
|
||||
|
||||
// Toggle sidebar
|
||||
export function toggleSidebar(arn: AnimeNotifier) {
|
||||
document.getElementById("sidebar").classList.toggle("sidebar-visible")
|
||||
let sidebar = document.getElementById("sidebar") as HTMLElement
|
||||
sidebar.classList.toggle("sidebar-visible")
|
||||
}
|
@ -3,26 +3,31 @@ import { bytesHumanReadable, uploadWithProgress } from "../Utils"
|
||||
|
||||
// Select file
|
||||
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.")
|
||||
return
|
||||
}
|
||||
|
||||
let fileType = button.dataset.type
|
||||
let endpoint = button.dataset.endpoint
|
||||
|
||||
// Click on virtual file input element
|
||||
let input = document.createElement("input")
|
||||
input.setAttribute("type", "file")
|
||||
input.value = null
|
||||
input.value = ""
|
||||
|
||||
input.onchange = async () => {
|
||||
let file = input.files[0]
|
||||
|
||||
if(!file) {
|
||||
if(!fileType || !endpoint) {
|
||||
console.error("Missing data-type or data-endpoint:", button)
|
||||
return
|
||||
}
|
||||
|
||||
if(!input.files || input.files.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let file = input.files[0]
|
||||
|
||||
// Check mime type for images
|
||||
if(fileType === "image" && !file.type.startsWith("image/")) {
|
||||
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
|
||||
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 lazyLoad = userImage["became visible"]
|
||||
|
||||
|
@ -3,21 +3,28 @@ import Diff from "scripts/Diff"
|
||||
|
||||
// Follow user
|
||||
export async function followUser(arn: AnimeNotifier, element: HTMLElement) {
|
||||
try {
|
||||
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)
|
||||
}
|
||||
return updateFollow(arn, element, "You are now following")
|
||||
}
|
||||
|
||||
// Unfollow user
|
||||
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 {
|
||||
await arn.post(element.dataset.api)
|
||||
await arn.post(api)
|
||||
await arn.reloadContent()
|
||||
arn.statusMessage.showInfo("You stopped following " + document.getElementById("nick").textContent + ".")
|
||||
arn.statusMessage.showInfo(`${message} ${nick.textContent}.`)
|
||||
} catch(err) {
|
||||
arn.statusMessage.showError(err)
|
||||
}
|
||||
|
@ -2,9 +2,21 @@ import AnimeNotifier from "../AnimeNotifier"
|
||||
|
||||
// Toggle play video
|
||||
export function togglePlayVideo(arn: AnimeNotifier, element: HTMLElement) {
|
||||
let container = document.getElementById(element.dataset.mediaId)
|
||||
let video = container.getElementsByTagName("video")[0]
|
||||
let mediaId = element.dataset.mediaId
|
||||
|
||||
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
|
||||
|
||||
if(video.readyState >= 2) {
|
||||
@ -30,7 +42,19 @@ function togglePlayVideoElement(video: HTMLVideoElement) {
|
||||
// Toggle fullscreen
|
||||
export function toggleFullscreen(arn: AnimeNotifier, button: HTMLElement) {
|
||||
let elementId = button.dataset.id
|
||||
|
||||
if(!elementId) {
|
||||
console.error("Missing data-id:", button)
|
||||
return
|
||||
}
|
||||
|
||||
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 exitFullscreen = document.exitFullscreen || document["mozCancelFullScreen"] || document["webkitExitFullscreen"] || document["msExitFullscreen"]
|
||||
let fullscreen = document.fullscreen || document["webkitIsFullScreen"] || document["mozFullScreen"]
|
||||
|
@ -1474,7 +1474,7 @@ export default class AnimeNotifier {
|
||||
}
|
||||
|
||||
// This is called every time an uncaught JavaScript error is thrown
|
||||
onError(evt: ErrorEvent) {
|
||||
async onError(evt: ErrorEvent) {
|
||||
let report = {
|
||||
message: evt.message,
|
||||
stack: evt.error.stack,
|
||||
@ -1483,8 +1483,11 @@ export default class AnimeNotifier {
|
||||
columnNumber: evt.colno,
|
||||
}
|
||||
|
||||
this.post("/api/new/clienterrorreport", report)
|
||||
.then(() => console.log("Successfully reported the error to the website staff."))
|
||||
.catch(() => console.warn("Failed reporting the error to the website staff."))
|
||||
try {
|
||||
await this.post("/api/new/clienterrorreport", report)
|
||||
console.log("Successfully reported the error to the website staff.")
|
||||
} catch(err) {
|
||||
console.warn("Failed reporting the error to the website staff:", err)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user