Files
decePubClient/wwwroot/main.js
T

158 lines
5.0 KiB
JavaScript
Raw Normal View History

2022-02-14 01:51:52 +01:00
window.cascadingStateInstanceReference = (dotNetReference) => {
try {
window.cascadingStateInstance = dotNetReference
} catch (e) {
console.error(e)
}
}
window.logFromJs = (message, where) => {
try {
if (!window.cascadingStateInstance ||
typeof window.cascadingStateInstance.invokeMethodAsync != "function")
return
window.cascadingStateInstance.invokeMethodAsync('LogFromJs', message, where)
} catch (e) {
console.error(e)
}
}
// The client once kept its error log in IndexedDB (DnetIndexedDb's database "data"). Nothing uses IndexedDB now, so a
// browser that still holds that database drops it.
try {
window.indexedDB?.deleteDatabase("data")
} catch (e) {
console.error(e)
2022-02-14 01:51:52 +01:00
}
window.getLanguage = () => {
try {
return navigator.language.substr(0, 2)
} catch (e) {
console.error(e)
window.logFromJs(e.message, "getLanguage")
}
}
window.isOnline = async () => {
try {
const isOnline = navigator.onLine
if (navigator.connection !== undefined &&
navigator.connection.effectiveType !== undefined &&
navigator.connection.type !== undefined) {
if (!isOnline)
return isOnline
return navigator.connection.type === "cellular" ?
navigator.connection.effectiveType.indexOf("2g") === -1 :
2022-02-14 01:51:52 +01:00
true
} else
return isOnline
2022-02-14 01:51:52 +01:00
} catch (e) {
console.error(e)
window.logFromJs(e.message, "isOnline")
}
}
window.setAppBadge = (counter) => {
try {
navigator.setAppBadge(counter)
} catch (e) {
console.error(e)
window.logFromJs(e.message, "setAppBadge")
}
}
window.clearAppBadge = () => {
try {
navigator.clearAppBadge()
} catch (e) {
console.error(e)
window.logFromJs(e.message, "clearAppBadge")
}
}
2026-10-06 23:39:10 +02:00
// On a touch screen a tap on a post (not on its links, controls or menus, and not ending a text selection) opens its
// thread, through the card's own thread link (Content.razor, data-thread-link), which Blazor's router takes.
document.addEventListener("click", event => {
try {
if (window.matchMedia("(hover: hover)").matches || !(event.target instanceof Element))
return
const card = event.target.closest("[data-thread]")
if (!card || event.target.closest("a, button, input, textarea, select, label, summary, video, audio, [role=button], .dropdown, .modal, [data-sheet]"))
return
if (!window.getSelection()?.isCollapsed)
return
card.querySelector("a[data-thread-link]")?.click()
} catch (e) {
console.error(e)
window.logFromJs(e.message, "openThread")
}
})
2026-10-06 23:49:49 +02:00
// The Back button (a popstate) as opposed to the app's own navigation: Blazor's location-changing handlers can't tell
// them apart, and MainLayout lets Back close an open overlay but lets the app's navigation through. Registered for the
// capture phase, so it runs before Blazor's own listener.
let backAt = 0
window.addEventListener("popstate", () => backAt = Date.now(), { capture: true })
window.tookBack = () => {
const back = Date.now() - backAt < 1000
backAt = 0
return back
}
2026-10-06 23:36:03 +02:00
window.canHover = () => {
try {
return window.matchMedia("(hover: hover)").matches
} catch (e) {
console.error(e)
window.logFromJs(e.message, "canHover")
return true
}
}
2026-10-06 23:31:07 +02:00
// the selected tab of a sideways-scrolling strip, brought into its middle
window.revealActive = strip => {
try {
strip?.querySelector("[aria-selected=true]")?.scrollIntoView({ inline: "center", block: "nearest" })
} catch (e) {
console.error(e)
window.logFromJs(e.message, "revealActive")
}
}
// the reader asked for less motion: what would move by itself (a gifv) waits for a tap
window.prefersReducedMotion = () => {
try {
return window.matchMedia("(prefers-reduced-motion: reduce)").matches
} catch (e) {
console.error(e)
window.logFromJs(e.message, "prefersReducedMotion")
return false
}
}
// text put on the clipboard (the recovery codes of two-factor sign-in); false when the browser refused it
window.copyText = async text => {
try {
await navigator.clipboard.writeText(text)
return true
} catch (e) {
console.error(e)
window.logFromJs(e.message, "copyText")
return false
}
}
// a phone: narrower than Tailwind's md, or held sideways (as short as the short: variant)
2022-02-14 01:51:52 +01:00
window.isMobileMedia = () => {
try {
return window.matchMedia("(max-width: 767.98px), (max-height: 30rem)").matches
2022-02-14 01:51:52 +01:00
} catch (e) {
console.error(e)
window.logFromJs(e.message, "isMobileMedia")
}
}
// This device's position for located posts and the Nearby feed, asked only when the reader chooses one of them. It
// goes to PrivaPub only, which keeps located posts on the server and rounds what it stores.
window.feedPosition = () => new Promise(resolve => {
try {
if (!navigator.geolocation)
return resolve({ error: "unsupported" })
navigator.geolocation.getCurrentPosition(
position => resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude, accuracy: position.coords.accuracy }),
error => resolve({ error: error.message || String(error.code) }),
{ enableHighAccuracy: false, timeout: 15000, maximumAge: 600000 })
} catch (e) {
console.error(e)
window.logFromJs(e.message, "feedPosition")
resolve({ error: e.message })
}
})