web: make everything ssr-compatible

This commit is contained in:
dumbmoron 2024-08-31 17:46:10 +00:00
parent 4b4fce326f
commit 51c140fbfa
No known key found for this signature in database
9 changed files with 91 additions and 53 deletions

View file

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from "$app/stores"; import { page } from "$app/stores";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { browser } from "$app/environment";
import { SvelteComponent, tick } from "svelte"; import { SvelteComponent, tick } from "svelte";
import env from "$lib/env"; import env from "$lib/env";
@ -43,7 +44,7 @@
}; };
$: linkFromHash = $page.url.hash.replace("#", "") || ""; $: linkFromHash = $page.url.hash.replace("#", "") || "";
$: linkFromQuery = $page.url.searchParams.get("u") || ""; $: linkFromQuery = (browser ? $page.url.searchParams.get("u") : 0) || "";
$: if (linkFromHash || linkFromQuery) { $: if (linkFromHash || linkFromQuery) {
if (validLink(linkFromHash)) { if (validLink(linkFromHash)) {

View file

@ -1,3 +1,17 @@
import { browser } from '$app/environment'
const device = {
is: {},
prefers: {},
supports: {},
userAgent: 'sveltekit server'
};
const app = {
is: {}
}
if (browser) {
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
const iPhone = ua.includes("iphone os"); const iPhone = ua.includes("iphone os");
@ -15,31 +29,27 @@ const installed = window.matchMedia('(display-mode: standalone)').matches;
const reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches; const reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches;
const reducedTransparency = window.matchMedia(`(prefers-reduced-transparency: reduce)`).matches; const reducedTransparency = window.matchMedia(`(prefers-reduced-transparency: reduce)`).matches;
const app = { app.is = { installed };
is: { device.is = {
installed
}
}
const device = {
is: {
iPhone, iPhone,
iPad, iPad,
iOS, iOS,
android, android,
mobile, mobile,
}, };
prefers: {
device.prefers = {
language, language,
reducedMotion, reducedMotion,
reducedTransparency, reducedTransparency,
}, };
supports: {
device.supports = {
share: navigator.share !== undefined, share: navigator.share !== undefined,
directDownload: !(installed && iOS), directDownload: !(installed && iOS),
}, };
userAgent: navigator.userAgent,
device.userAgent = navigator.userAgent;
} }
export { device, app }; export { device, app };

View file

@ -1,11 +1,20 @@
import { env } from "$env/dynamic/public"; import * as _env from "$env/static/public";
const getEnv = (_key: string) => {
const env = _env as Record<string, string | undefined>;
const key = `PUBLIC_${_key}`;
if (key in env) {
return env[key];
}
}
const variables = { const variables = {
HOST: env.PUBLIC_HOST, HOST: getEnv('HOST'),
PLAUSIBLE_HOST: env.PUBLIC_PLAUSIBLE_HOST, PLAUSIBLE_HOST: getEnv('PLAUSIBLE_HOST'),
PLAUSIBLE_ENABLED: env.PUBLIC_HOST && env.PUBLIC_PLAUSIBLE_HOST, PLAUSIBLE_ENABLED: getEnv('HOST') && getEnv('PLAUSIBLE_HOST'),
DEFAULT_API: env.PUBLIC_DEFAULT_API, DEFAULT_API: getEnv('DEFAULT_API'),
TURNSTILE_KEY: env.PUBLIC_TURNSTILE_KEY, TURNSTILE_KEY: getEnv('TURNSTILE_KEY'),
} }
const contacts = { const contacts = {

View file

@ -2,6 +2,7 @@ import mime from "mime";
import LibAV, { type LibAV as LibAVInstance } from "@imput/libav.js-remux-cli"; import LibAV, { type LibAV as LibAVInstance } from "@imput/libav.js-remux-cli";
import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, FileInfo, RenderParams } from "./types/libav"; import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, FileInfo, RenderParams } from "./types/libav";
import type { FfprobeData } from "fluent-ffmpeg"; import type { FfprobeData } from "fluent-ffmpeg";
import { browser } from "$app/environment";
export default class LibAVWrapper { export default class LibAVWrapper {
libav: Promise<LibAVInstance> | null; libav: Promise<LibAVInstance> | null;
@ -10,12 +11,12 @@ export default class LibAVWrapper {
constructor(onProgress?: FFmpegProgressCallback) { constructor(onProgress?: FFmpegProgressCallback) {
this.libav = null; this.libav = null;
this.concurrency = Math.min(4, navigator.hardwareConcurrency); this.concurrency = Math.min(4, browser ? navigator.hardwareConcurrency : 0);
this.onProgress = onProgress; this.onProgress = onProgress;
} }
async init() { async init() {
if (!this.libav) { if (this.concurrency && !this.libav) {
this.libav = LibAV.LibAV({ this.libav = LibAV.LibAV({
yesthreads: true, yesthreads: true,
base: '/_libav' base: '/_libav'

View file

@ -1,4 +1,5 @@
import { derived, readable, type Updater } from 'svelte/store'; import { derived, readable, type Updater } from 'svelte/store';
import { browser } from '$app/environment';
import { merge } from 'ts-deepmerge'; import { merge } from 'ts-deepmerge';
import type { import type {
@ -43,6 +44,9 @@ const migrate = (settings: AllPartialSettingsWithSchema): PartialSettings => {
const loadFromStorage = () => { const loadFromStorage = () => {
if (!browser)
return {};
const settings = localStorage.getItem('settings'); const settings = localStorage.getItem('settings');
if (!settings) { if (!settings) {
const migrated = migrateOldSettings(); const migrated = migrateOldSettings();

View file

@ -1,4 +1,5 @@
import { readable, derived, type Readable } from 'svelte/store'; import { readable, derived, type Readable } from 'svelte/store';
import { browser } from '$app/environment';
import settings from '$lib/state/settings'; import settings from '$lib/state/settings';
import { themeOptions } from '$lib/types/settings'; import { themeOptions } from '$lib/types/settings';
@ -7,20 +8,26 @@ type Theme = typeof themeOptions[number];
let set: (_: Theme) => void; let set: (_: Theme) => void;
const browserPreference = () => const browserPreference = () => {
window.matchMedia('(prefers-color-scheme: light)') if (!browser || window.matchMedia('(prefers-color-scheme: light)').matches) {
.matches ? 'light' : 'dark'; return 'light';
}
return 'dark'
}
const browserPreferenceReadable = readable( const browserPreferenceReadable = readable(
browserPreference(), browserPreference(),
_set => { set = _set } _set => { set = _set }
) )
if (browser) {
const matchMedia = window.matchMedia('(prefers-color-scheme: dark)'); const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
if (matchMedia.addEventListener) { if (matchMedia.addEventListener) {
matchMedia.addEventListener('change', () => set(browserPreference())); matchMedia.addEventListener('change', () => set(browserPreference()));
} }
}
export default derived( export default derived(
[settings, browserPreferenceReadable], [settings, browserPreferenceReadable],

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { page } from "$app/stores"; import { page } from "$app/stores";
import { browser } from "$app/environment";
import settings from "$lib/state/settings"; import settings from "$lib/state/settings";
import { version } from "$lib/version"; import { version } from "$lib/version";
@ -38,7 +39,7 @@
$: isMobile = screenWidth <= 750; $: isMobile = screenWidth <= 750;
$: isHome = $page.url.pathname === "/settings"; $: isHome = $page.url.pathname === "/settings";
$: { $: {
if (!isMobile && isHome) { if (browser && !isMobile && isHome) {
goto(defaultSettingsPage(), { replaceState: true }); goto(defaultSettingsPage(), { replaceState: true });
} }
} }

View file

@ -1,16 +1,17 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { device, app } from "$lib/device"; import { device, app } from "$lib/device";
import { version } from "$lib/version"; import { version } from "$lib/version";
import settings, { storedSettings } from "$lib/state/settings"; import settings, { storedSettings } from "$lib/state/settings";
import { goto } from "$app/navigation";
import { defaultSettingsPage } from "$lib/settings/defaults"; import { defaultSettingsPage } from "$lib/settings/defaults";
$: { onMount(() => {
if (!$settings.advanced.debug) { if (!$settings.advanced.debug) {
goto(defaultSettingsPage(), { replaceState: true }); goto(defaultSettingsPage(), { replaceState: true });
} }
} });
</script> </script>
{#if $settings.advanced.debug} {#if $settings.advanced.debug}

View file

@ -1,10 +1,11 @@
<script lang="ts"> <script lang="ts">
import { t } from "$lib/i18n/translations";
import { page } from "$app/stores"; import { page } from "$app/stores";
import { browser } from "$app/environment";
import { t } from "$lib/i18n/translations";
import { getAllChangelogs } from "$lib/changelogs"; import { getAllChangelogs } from "$lib/changelogs";
import type { ChangelogImport } from "$lib/types/changelogs";
import type { Optional } from "$lib/types/generic"; import type { Optional } from "$lib/types/generic";
import type { ChangelogImport } from "$lib/types/changelogs";
import ChangelogEntry from "$components/changelog/ChangelogEntry.svelte"; import ChangelogEntry from "$components/changelog/ChangelogEntry.svelte";
@ -36,7 +37,10 @@
page: changelogs[version]() as Promise<ChangelogImport>, page: changelogs[version]() as Promise<ChangelogImport>,
}; };
if (browser) {
window.location.hash = version; window.location.hash = version;
}
await changelog.page; await changelog.page;
}; };