diff --git a/components/SettingsSelect.tsx b/components/SettingsSelect.tsx new file mode 100644 index 0000000..ba67368 --- /dev/null +++ b/components/SettingsSelect.tsx @@ -0,0 +1,119 @@ +import { Component, ContextType } from "preact"; +import { SettingsCtx } from "./SettingsContext.tsx"; +import { ConfigType } from "../config.ts"; +import Select from "preact-material-components/Select"; +import { Ref, StateUpdater, useRef } from "preact/hooks"; + +interface obj { + toString(): string; +} + +type Props = { + name: keyof ConfigType; + list: { value: T; text?: string; disabled?: boolean }[]; + description: string; + /**@default {0}*/ + selectedIndex?: number; + /**@default {false}*/ + disabled?: boolean; + /**@default {false}*/ + box?: boolean; + /**@default {false}*/ + outlined?: boolean; + hintText?: string; + set_value?: StateUpdater; +}; + +type State = { + selectedIndex: number; +}; + +export default class SettingsSelect + extends Component, State> { + static contextType = SettingsCtx; + declare context: ContextType; + ref: Ref(); + const id = `s-${this.props.name}`; + return ( +
+ + +
+ ); + } + set_changed() { + if (this.context) { + this.context.set_changed((v) => { + v.add(this.props.name); + return v; + }); + } + } + set_value(index: number) { + const value = this.props.list[index].value; + if (this.props.set_value) { + this.props.set_value(value); + this.set_changed(); + } else if (this.context) { + this.context.set_settings((v) => { + if (v) { + const t: Record = v; + t[this.props.name] = value; + this.set_changed(); + return t as ConfigType; + } + }); + } + } + update(index: number) { + const e = this.ref?.current; + if (e) { + const b = e.base; + if (b) { + const t = b as HTMLElement; + const s = t.querySelector("select"); + if (s) { + s.selectedIndex = index; + } + } + } + } +} diff --git a/components/SettingsText.tsx b/components/SettingsText.tsx index 362ed99..b63c086 100644 --- a/components/SettingsText.tsx +++ b/components/SettingsText.tsx @@ -30,6 +30,7 @@ export type SettingsTextProps = { set_value?: StateUpdater; min?: DataType[T]; max?: DataType[T]; + outlined?: boolean; }; export default class SettingsText @@ -99,6 +100,7 @@ export default class SettingsText const id = `s-${this.props.name}`; let cn = "text"; if (this.props.helpertext) cn += " helper"; + if (this.props.outlined) cn += " outlined"; return (
@@ -118,6 +120,7 @@ export default class SettingsText }} min={this.props.min} max={this.props.max} + outlined={this.props.outlined} /> {this.props.children}
diff --git a/config.ts b/config.ts index 1b16ec3..67cff92 100644 --- a/config.ts +++ b/config.ts @@ -18,8 +18,15 @@ export type ConfigType = { meili_host?: string; meili_search_api_key?: string; meili_update_api_key?: string; + ffmpeg_path: string; + thumbnail_method: ThumbnailMethod; }; +export enum ThumbnailMethod { + FFMPEG_BINARY, + FFMPEG_API, +} + export class Config { _data; constructor(data: JsonValue) { @@ -109,6 +116,14 @@ export class Config { get meili_update_api_key() { return this._return_string("meili_update_api_key"); } + get ffmpeg_path() { + return this._return_string("ffmpeg_path") || "ffmpeg"; + } + get thumbnail_method() { + const n = this._return_number("thumbnail") || 0; + if (n < 0 || n > 1) return ThumbnailMethod.FFMPEG_BINARY; + return n as ThumbnailMethod; + } to_json(): ConfigType { return { cookies: typeof this.cookies === "string", @@ -127,6 +142,8 @@ export class Config { meili_host: this.meili_host, meili_search_api_key: this.meili_search_api_key, meili_update_api_key: this.meili_update_api_key, + ffmpeg_path: this.ffmpeg_path, + thumbnail_method: this.thumbnail_method, }; } } diff --git a/islands/Settings.tsx b/islands/Settings.tsx index 5ce847d..d2cb49f 100644 --- a/islands/Settings.tsx +++ b/islands/Settings.tsx @@ -5,11 +5,12 @@ import Dialog from "preact-material-components/Dialog"; import Snackbar from "preact-material-components/Snackbar"; import { tw } from "twind"; import { GlobalCtx } from "../components/GlobalContext.tsx"; -import { ConfigType } from "../config.ts"; +import { ConfigType, ThumbnailMethod } from "../config.ts"; import SettingsCheckbox from "../components/SettingsCheckbox.tsx"; import SettingsContext from "../components/SettingsContext.tsx"; import SettingsText from "../components/SettingsText.tsx"; import t from "../server/i18n.ts"; +import SettingsSelect from "../components/SettingsSelect.tsx"; export type SettingsProps = { show: boolean; @@ -122,12 +123,14 @@ export default class Settings extends Component { value={settings.base} description={t("settings.base")} type="text" + outlined={true} /> diff --git a/routes/_middleware.ts b/routes/_middleware.ts index 5276b0d..ee8ae67 100644 --- a/routes/_middleware.ts +++ b/routes/_middleware.ts @@ -7,7 +7,7 @@ import { GetFileResponseOptions, } from "../server/get_file_response.ts"; -const STATIC_FILES = ["/sw.js", "/sw.js.map"]; +const STATIC_FILES = ["/common.css", "/sw.js", "/sw.js.map"]; export async function handler(req: Request, ctx: MiddlewareHandlerContext) { const url = new URL(req.url); diff --git a/static/common.css b/static/common.css index d646a31..e9ce4ea 100644 --- a/static/common.css +++ b/static/common.css @@ -44,3 +44,15 @@ .settings div.text.helper label { margin-top: 14px; } + +.settings div.text.outlined .mdc-text-field label { + top: 14px; +} + +.settings div.text.outlined .mdc-text-field.mdc-text-field--focused label { + top: 22px; +} + +.settings div.text.outlined { + margin-top: 5px; +} diff --git a/translation/en/settings.jsonc b/translation/en/settings.jsonc index 7b17eb4..6d4165d 100644 --- a/translation/en/settings.jsonc +++ b/translation/en/settings.jsonc @@ -23,5 +23,9 @@ "hostname": "Listening host: ", "meili_host": "Meilisearch server host: ", "meili_update_api_key": "Meilisearch API key for updating gallery metadata: ", - "meili_search_api_key": "Meilisearch API key for searching: " + "meili_search_api_key": "Meilisearch API key for searching: ", + "ffmpeg_path": "The path to the ffmpeg binary: ", + "thumbnail_method": "The method used to generate thumbnail: ", + "thumbnail_method0": "ffmpeg binary", + "thumbnail_method1": "ffmpeg API" } diff --git a/translation/zh-cn/settings.jsonc b/translation/zh-cn/settings.jsonc index 6a8c518..f3e5943 100644 --- a/translation/zh-cn/settings.jsonc +++ b/translation/zh-cn/settings.jsonc @@ -23,5 +23,9 @@ "hostname": "监听主机:", "meili_host": "Meilisearch服务器主机:", "meili_update_api_key": "用于更新画廊元数据的Meilisearch API密钥:", - "meili_search_api_key": "用于搜索的Meilisearch API密钥:" + "meili_search_api_key": "用于搜索的Meilisearch API密钥:", + "ffmpeg_path": "FFMPEG二进制的位置:", + "thumbnail_method": "生成缩略图的方式:", + "thumbnail_method0": "FFMPEG二进制", + "thumbnail_method1": "FFMPEG API" }