From a2e85380220be39c09cbcfc502d5f12d552f73ef Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:20:37 +0800 Subject: [PATCH] [F] Fix settings stroage --- src/routes/song/[slug]/+page.svelte | 10 +- src/shared/ext.ts | 275 ++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 src/shared/ext.ts diff --git a/src/routes/song/[slug]/+page.svelte b/src/routes/song/[slug]/+page.svelte index 702cbc1..24b9d91 100644 --- a/src/routes/song/[slug]/+page.svelte +++ b/src/routes/song/[slug]/+page.svelte @@ -7,7 +7,8 @@ import { isKana, isKanji, toHiragana, toKatakana } from "wanakana"; import { composeList, fuzzyEquals } from "./IMEHelper.ts"; import MenuItem from "../../../components/material3/MenuItem.svelte"; - import "scope-extensions-js"; + import "../../../shared/ext.ts" + import { browser } from "$app/environment"; let { data }: PageProps = $props() @@ -19,11 +20,12 @@ let inp = $state("") // Settings stored in localStorage - let settings = $state(localStorage.getItem('kashi-dash-settings')?.let(it => JSON.parse(it)) ?? { + let settingDefaults = { isFuri: true, allKata: false - }) - $effect(() => localStorage.setItem('kashi-dash-settings', JSON.stringify(settings))) + } + let settings = $state(browser ? (localStorage.getItem('kashi-dash-settings')?.let((it) => JSON.parse(it)) ?? settingDefaults) : settingDefaults) + $effect(() => { if (browser) localStorage.setItem('kashi-dash-settings', JSON.stringify(settings)) }) const preprocessKana = (kana: string) => settings.allKata ? toKatakana(kana) : kana // Process each line into segments with swi (start word index) and kanji/kana diff --git a/src/shared/ext.ts b/src/shared/ext.ts new file mode 100644 index 0000000..4d351c7 --- /dev/null +++ b/src/shared/ext.ts @@ -0,0 +1,275 @@ +export {}; + +declare global { + interface Object { + /** + * Calls the specified function block with `this` value as its argument and returns its result + * @param block - The function to be executed with `this` as argument + * @returns `block`'s result + */ + let(this: T | null | undefined, block: (it: T) => R): R; + /** + * Calls the specified function block with `this` value as its argument and returns `this` value + * @param block - The function to be executed with `this` as argument + * @returns `this` + */ + also(this: T | null | undefined, block: (it: T) => void): T; + /** + * Calls the specified function block with `this` value as its receiver and returns its value + * @param block - The function to be executed with `this` as context + * @returns `block`'s result + */ + run(this: T | null | undefined, block: (this: T) => R): R; + /** + * Calls the specified function block with `this` value as its receiver and returns `this` value + * @param block - The function to be executed with `this` as context + * @returns `this` + */ + apply(this: T | null | undefined, block: (this: T) => void): T; + /** + * Returns `this` value if it satisfies the given predicate or `undefined` if it doesn't + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeIf(this: T | null | undefined, predicate: (it: T) => boolean): T | undefined; + /** + * Returns `this` value if it does not satisfy the given predicate or `undefined` if it does + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeUnless(this: T | null | undefined, predicate: (it: T) => boolean): T | undefined; + } + interface Number { + /** + * Calls the specified function block with `this` value as its argument and returns its result + * @param block - The function to be executed with `this` as argument + * @returns `block`'s result + */ + let(this: Number | null | undefined, block: (it: number) => R): R; + /** + * Calls the specified function block with `this` value as its argument and returns `this` value + * @param block - The function to be executed with `this` as argument + * @returns `this` + */ + also(this: Number | null | undefined, block: (it: number) => void): number; + /** + * Calls the specified function block with `this` value as its receiver and returns its value + * @param block - The function to be executed with `this` as context + * @returns `block`'s result + */ + run(this: Number | null | undefined, block: (this: number) => R): R; + /** + * Calls the specified function block with `this` value as its receiver and returns `this` value + * @param block - The function to be executed with `this` as context + * @returns `this` + */ + apply(this: Number | null | undefined, block: (this: number) => void): number; + /** + * Returns `this` value if it satisfies the given predicate or `undefined` if it doesn't + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeIf(this: Number | null | undefined, predicate: (it: number) => boolean): number | undefined; + /** + * Returns `this` value if it does not satisfy the given predicate or `undefined` if it does + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeUnless(this: Number | null | undefined, predicate: (it: number) => boolean): number | undefined; + } + interface String { + /** + * Calls the specified function block with `this` value as its argument and returns its result + * @param block - The function to be executed with `this` as argument + * @returns `block`'s result + */ + let(this: String | null | undefined, block: (it: string) => R): R; + /** + * Calls the specified function block with `this` value as its argument and returns `this` value + * @param block - The function to be executed with `this` as argument + * @returns `this` + */ + also(this: String | null | undefined, block: (it: string) => void): string; + /** + * Calls the specified function block with `this` value as its receiver and returns its value + * @param block - The function to be executed with `this` as context + * @returns `block`'s result + */ + run(this: String | null | undefined, block: (this: string) => R): R; + /** + * Calls the specified function block with `this` value as its receiver and returns `this` value + * @param block - The function to be executed with `this` as context + * @returns `this` + */ + apply(this: String | null | undefined, block: (this: string) => void): string; + /** + * Returns `this` value if it satisfies the given predicate or `undefined` if it doesn't + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeIf(this: String | null | undefined, predicate: (it: string) => boolean): string | undefined; + /** + * Returns `this` value if it does not satisfy the given predicate or `undefined` if it does + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeUnless(this: String | null | undefined, predicate: (it: string) => boolean): string | undefined; + } + interface Boolean { + /** + * Calls the specified function block with `this` value as its argument and returns its result + * @param block - The function to be executed with `this` as argument + * @returns `block`'s result + */ + let(this: Boolean | null | undefined, block: (it: boolean) => R): R; + /** + * Calls the specified function block with `this` value as its argument and returns `this` value + * @param block - The function to be executed with `this` as argument + * @returns `this` + */ + also(this: Boolean | null | undefined, block: (it: boolean) => void): boolean; + /** + * Calls the specified function block with `this` value as its receiver and returns its value + * @param block - The function to be executed with `this` as context + * @returns `block`'s result + */ + run(this: Boolean | null | undefined, block: (this: boolean) => R): R; + /** + * Calls the specified function block with `this` value as its receiver and returns `this` value + * @param block - The function to be executed with `this` as context + * @returns `this` + */ + apply(this: Boolean | null | undefined, block: (this: boolean) => void): boolean; + /** + * Returns `this` value if it satisfies the given predicate or `undefined` if it doesn't + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeIf(this: Boolean | null | undefined, predicate?: (it: boolean) => boolean): boolean | undefined; + /** + * Returns `this` value if it does not satisfy the given predicate or `undefined` if it does + * @param predicate - The function to be executed with `this` as argument and returns a truthy or falsy value + * @returns `this` or `undefined` + */ + takeUnless(this: Boolean | null | undefined, predicate?: (it: boolean) => boolean): boolean | undefined; + } +} + +Object.prototype.let = function(this, block) { + return block(this!); +} + +Object.prototype.also = function(this, block) { + block(this!); + return this!; +} + +Object.prototype.run = function(this, block) { + return block.call(this!); +} + +Object.prototype.apply = function(this, block) { + block.call(this!); + return this!; +} + +Object.prototype.takeIf = function(this, predicate) { + return predicate(this!) ? this! : undefined; +} + +Object.prototype.takeUnless = function(this, predicate) { + return predicate(this!) ? undefined : this!; +} + +Number.prototype.let = function(this, block) { + return block(this!.valueOf()); +} + +Number.prototype.also = function(this, block) { + block(this!.valueOf()); + return this!.valueOf(); +} + +Number.prototype.run = function(this, block) { + return block.call(this!.valueOf()); +} + +Number.prototype.apply = function(this, block) { + block.call(this!.valueOf()); + return this!.valueOf(); +} + +Number.prototype.takeIf = function(this, predicate) { + return predicate(this!.valueOf()) ? this!.valueOf() : undefined; +} + +Number.prototype.takeUnless = function(this, predicate) { + return predicate(this!.valueOf()) ? undefined : this!.valueOf(); +} + +String.prototype.let = function(this, block) { + return block(this!.valueOf()); +} + +String.prototype.also = function(this, block) { + block(this!.valueOf()); + return this!.valueOf(); +} + +String.prototype.run = function(this, block) { + return block.call(this!.valueOf()); +} + +String.prototype.apply = function(this, block) { + block.call(this!.valueOf()); + return this!.valueOf(); +} + +String.prototype.takeIf = function(this, predicate) { + return predicate(this!.valueOf()) ? this!.valueOf() : undefined; +} + +String.prototype.takeUnless = function(this, predicate) { + return predicate(this!.valueOf()) ? undefined : this!.valueOf(); +} + +Boolean.prototype.let = function(this, block) { + return block(this!.valueOf()); +} + +Boolean.prototype.also = function(this, block) { + block(this!.valueOf()); + return this!.valueOf(); +} + +Boolean.prototype.run = function(this, block) { + return block.call(this!.valueOf()); +} + +Boolean.prototype.apply = function(this, block) { + block.call(this!.valueOf()); + return this!.valueOf(); +} + +Boolean.prototype.takeIf = function(this, predicate) { + return predicate && predicate(this!.valueOf()) || this!.valueOf() ? this!.valueOf() : undefined; +} + +Boolean.prototype.takeUnless = function(this, predicate) { + return predicate && predicate(this!.valueOf()) || this!.valueOf() ? undefined : this!.valueOf(); +} + +// Make enumerable false to avoid for..in loops from iterating over these methods +for (const key of [ + "let", + "also", + "run", + "apply", + "takeIf", + "takeUnless" +]) { + Object.defineProperty(Object.prototype, key, { enumerable: false }); + Object.defineProperty(Number.prototype, key, { enumerable: false }); + Object.defineProperty(String.prototype, key, { enumerable: false }); + Object.defineProperty(Boolean.prototype, key, { enumerable: false }); +} \ No newline at end of file