feat(react/settings): port spellcheck

This commit is contained in:
Elian Doran
2025-08-15 13:52:52 +03:00
parent 25dce64c3b
commit fb559d66fe
4 changed files with 67 additions and 74 deletions

View File

@@ -306,7 +306,7 @@ function copySelectionToClipboard() {
}
}
function dynamicRequire(moduleName: string) {
export function dynamicRequire(moduleName: string) {
if (typeof __non_webpack_require__ !== "undefined") {
return __non_webpack_require__(moduleName);
} else {

View File

@@ -8,11 +8,8 @@ import DateTimeFormatOptions from "./options/text_notes/date_time_format.js";
import CodeEditorOptions from "./options/code_notes/code_editor.js";
import CodeAutoReadOnlySizeOptions from "./options/code_notes/code_auto_read_only_size.js";
import CodeMimeTypesOptions from "./options/code_notes/code_mime_types.js";
import SpellcheckOptions from "./options/spellcheck.js";
import PasswordOptions from "./options/password/password.js";
import ProtectedSessionTimeoutOptions from "./options/password/protected_session_timeout.js";
import EtapiOptions from "./options/etapi.js";
import BackupOptions from "./options/backup.js";
import SearchEngineOptions from "./options/other/search_engine.js";
import TrayOptions from "./options/other/tray.js";
import NoteErasureTimeoutOptions from "./options/other/note_erasure_timeout.js";
@@ -42,6 +39,7 @@ import InternationalizationOptions from "./options/i18n.jsx";
import SyncOptions from "./options/sync.jsx";
import EtapiSettings from "./options/etapi.js";
import BackupSettings from "./options/backup.js";
import SpellcheckSettings from "./options/spellcheck.js";
const TPL = /*html*/`<div class="note-detail-content-widget note-detail-printable">
<style>
@@ -90,9 +88,7 @@ const CONTENT_WIDGETS: Record<OptionPages | "_backendLog", ((typeof NoteContextA
CodeAutoReadOnlySizeOptions
],
_optionsImages: <ImageSettings />,
_optionsSpellcheck: [
SpellcheckOptions
],
_optionsSpellcheck: <SpellcheckSettings />,
_optionsPassword: [
PasswordOptions,
ProtectedSessionTimeoutOptions

View File

@@ -1,67 +0,0 @@
import utils from "../../../services/utils.js";
import OptionsWidget from "./options_widget.js";
import { t } from "../../../services/i18n.js";
import type { OptionMap } from "@triliumnext/commons";
const TPL_WEB = `
<div class="options-section">
<h4>${t("spellcheck.title")}</h4>
<p>${t("spellcheck.description")}</p>
</div>
`;
const TPL_ELECTRON = `
<div class="options-section">
<h4>${t("spellcheck.title")}</h4>
<p class="form-text">${t("spellcheck.restart-required")}</p>
<label class="tn-checkbox">
<input type="checkbox" class="spell-check-enabled">
${t("spellcheck.enable")}
</label>
<br/>
<div class="form-group">
<label for="spell-check-language-code">${t("spellcheck.language_code_label")}</label>
<input id="spell-check-language-code" type="text" class="spell-check-language-code form-control" placeholder="${t("spellcheck.language_code_placeholder")}">
</div>
<p class="form-text">${t("spellcheck.multiple_languages_info")}</p>
<p class="form-text"><strong>${t("spellcheck.available_language_codes_label")} </strong> <span class="available-language-codes"></span></p>
</div>`;
export default class SpellcheckOptions extends OptionsWidget {
private $spellCheckEnabled!: JQuery<HTMLElement>;
private $spellCheckLanguageCode!: JQuery<HTMLElement>;
private $availableLanguageCodes!: JQuery<HTMLElement>;
doRender() {
const template = utils.isElectron() ? TPL_ELECTRON : TPL_WEB;
this.$widget = $(template);
this.$spellCheckEnabled = this.$widget.find(".spell-check-enabled");
this.$spellCheckLanguageCode = this.$widget.find(".spell-check-language-code");
this.$spellCheckEnabled.on("change", () => this.updateCheckboxOption("spellCheckEnabled", this.$spellCheckEnabled));
this.$spellCheckLanguageCode.on("change", () => this.updateOption("spellCheckLanguageCode", this.$spellCheckLanguageCode.val()));
this.$availableLanguageCodes = this.$widget.find(".available-language-codes");
if (utils.isElectron()) {
const { webContents } = utils.dynamicRequire("@electron/remote").getCurrentWindow();
this.$availableLanguageCodes.text(webContents.session.availableSpellCheckerLanguages.join(", "));
}
}
optionsLoaded(options: OptionMap) {
this.setCheckboxState(this.$spellCheckEnabled, options.spellCheckEnabled);
this.$spellCheckLanguageCode.val(options.spellCheckLanguageCode);
}
}

View File

@@ -0,0 +1,64 @@
import { useMemo } from "preact/hooks";
import { t } from "../../../services/i18n";
import FormCheckbox from "../../react/FormCheckbox";
import FormGroup from "../../react/FormGroup";
import FormText from "../../react/FormText";
import FormTextBox from "../../react/FormTextBox";
import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
import OptionsSection from "./components/OptionsSection";
import { dynamicRequire, isElectron } from "../../../services/utils";
export default function SpellcheckSettings() {
if (isElectron()) {
return <ElectronSpellcheckSettings />
} else {
return <WebSpellcheckSettings />
}
}
function ElectronSpellcheckSettings() {
const [ spellCheckEnabled, setSpellCheckEnabled ] = useTriliumOptionBool("spellCheckEnabled");
const [ spellCheckLanguageCode, setSpellCheckLanguageCode ] = useTriliumOption("spellCheckLanguageCode");
const availableLanguageCodes = useMemo(() => {
if (!isElectron()) {
return [];
}
const { webContents } = dynamicRequire("@electron/remote").getCurrentWindow();
return webContents.session.availableSpellCheckerLanguages as string[];
}, [])
return (
<OptionsSection title={t("spellcheck.title")}>
<FormText>{t("spellcheck.restart-required")}</FormText>
<FormCheckbox
name="spell-check-enabled"
label={t("spellcheck.enable")}
currentValue={spellCheckEnabled} onChange={setSpellCheckEnabled}
/>
<FormGroup label={t("spellcheck.language_code_label")} description={t("spellcheck.multiple_languages_info")}>
<FormTextBox
name="spell-check-languages"
placeholder={t("spellcheck.language_code_placeholder")}
currentValue={spellCheckLanguageCode} onChange={setSpellCheckLanguageCode}
/>
</FormGroup>
<FormText>
<strong>{t("spellcheck.available_language_codes_label")} </strong>
{availableLanguageCodes.join(", ")}
</FormText>
</OptionsSection>
)
}
function WebSpellcheckSettings() {
return (
<OptionsSection title={t("spellcheck.title")}>
<p>{t("spellcheck.description")}</p>
</OptionsSection>
)
}