chore(client/ts): port options/other

This commit is contained in:
Elian Doran 2025-01-11 11:18:50 +02:00
parent 03241a8967
commit 677760282c
No known key found for this signature in database
8 changed files with 65 additions and 26 deletions

View File

@ -2,6 +2,7 @@ import OptionsWidget from "../options_widget.js";
import server from "../../../../services/server.js"; import server from "../../../../services/server.js";
import toastService from "../../../../services/toast.js"; import toastService from "../../../../services/toast.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -13,13 +14,17 @@ const TPL = `
<label>${t("attachment_erasure_timeout.erase_attachments_after_x_seconds")}</label> <label>${t("attachment_erasure_timeout.erase_attachments_after_x_seconds")}</label>
<input class="erase-unused-attachments-after-time-in-seconds form-control options-number-input" type="number" min="0"> <input class="erase-unused-attachments-after-time-in-seconds form-control options-number-input" type="number" min="0">
</div> </div>
<p>${t("attachment_erasure_timeout.manual_erasing_description")}</p> <p>${t("attachment_erasure_timeout.manual_erasing_description")}</p>
<button class="erase-unused-attachments-now-button btn">${t("attachment_erasure_timeout.erase_unused_attachments_now")}</button> <button class="erase-unused-attachments-now-button btn">${t("attachment_erasure_timeout.erase_unused_attachments_now")}</button>
</div>`; </div>`;
export default class AttachmentErasureTimeoutOptions extends OptionsWidget { export default class AttachmentErasureTimeoutOptions extends OptionsWidget {
private $eraseUnusedAttachmentsAfterTimeInSeconds!: JQuery<HTMLElement>;
private $eraseUnusedAttachmentsNowButton!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$eraseUnusedAttachmentsAfterTimeInSeconds = this.$widget.find(".erase-unused-attachments-after-time-in-seconds"); this.$eraseUnusedAttachmentsAfterTimeInSeconds = this.$widget.find(".erase-unused-attachments-after-time-in-seconds");
@ -33,7 +38,7 @@ export default class AttachmentErasureTimeoutOptions extends OptionsWidget {
}); });
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$eraseUnusedAttachmentsAfterTimeInSeconds.val(options.eraseUnusedAttachmentsAfterSeconds); this.$eraseUnusedAttachmentsAfterTimeInSeconds.val(options.eraseUnusedAttachmentsAfterSeconds);
} }
} }

View File

@ -1,5 +1,6 @@
import OptionsWidget from "../options_widget.js"; import OptionsWidget from "../options_widget.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
// TODO: Deduplicate with src/services/html_sanitizer once there is a commons project between client and server. // TODO: Deduplicate with src/services/html_sanitizer once there is a commons project between client and server.
export const DEFAULT_ALLOWED_TAGS = [ export const DEFAULT_ALLOWED_TAGS = [
@ -103,12 +104,12 @@ export const DEFAULT_ALLOWED_TAGS = [
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t("import.html_import_tags.title")}</h4> <h4>${t("import.html_import_tags.title")}</h4>
<p>${t("import.html_import_tags.description")}</p> <p>${t("import.html_import_tags.description")}</p>
<textarea class="allowed-html-tags form-control" style="height: 150px; font-family: monospace;" <textarea class="allowed-html-tags form-control" style="height: 150px; font-family: monospace;"
placeholder="${t("import.html_import_tags.placeholder")}"></textarea> placeholder="${t("import.html_import_tags.placeholder")}"></textarea>
<div> <div>
<button class="btn btn-sm btn-secondary reset-to-default"> <button class="btn btn-sm btn-secondary reset-to-default">
${t("import.html_import_tags.reset_button")} ${t("import.html_import_tags.reset_button")}
@ -117,6 +118,10 @@ const TPL = `
</div>`; </div>`;
export default class HtmlImportTagsOptions extends OptionsWidget { export default class HtmlImportTagsOptions extends OptionsWidget {
private $allowedTags!: JQuery<HTMLElement>;
private $resetButton!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.contentSized(); this.contentSized();
@ -131,7 +136,7 @@ export default class HtmlImportTagsOptions extends OptionsWidget {
this.refresh(); this.refresh();
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
try { try {
if (options.allowedHtmlTags) { if (options.allowedHtmlTags) {
const tags = JSON.parse(options.allowedHtmlTags); const tags = JSON.parse(options.allowedHtmlTags);
@ -148,7 +153,7 @@ export default class HtmlImportTagsOptions extends OptionsWidget {
} }
async saveTags() { async saveTags() {
const tagsText = this.$allowedTags.val(); const tagsText = String(this.$allowedTags.val()) || "";
const tags = tagsText const tags = tagsText
.split(/[\n,\s]+/) // Split on newlines, commas, or spaces .split(/[\n,\s]+/) // Split on newlines, commas, or spaces
.map((tag) => tag.trim()) .map((tag) => tag.trim())

View File

@ -1,10 +1,11 @@
import OptionsWidget from "../options_widget.js"; import OptionsWidget from "../options_widget.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t("network_connections.network_connections_title")}</h4> <h4>${t("network_connections.network_connections_title")}</h4>
<label> <label>
<input class="check-for-updates form-check-input" type="checkbox" name="check-for-updates"> <input class="check-for-updates form-check-input" type="checkbox" name="check-for-updates">
${t("network_connections.check_for_updates")} ${t("network_connections.check_for_updates")}
@ -12,13 +13,16 @@ const TPL = `
</div>`; </div>`;
export default class NetworkConnectionsOptions extends OptionsWidget { export default class NetworkConnectionsOptions extends OptionsWidget {
private $checkForUpdates!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$checkForUpdates = this.$widget.find(".check-for-updates"); this.$checkForUpdates = this.$widget.find(".check-for-updates");
this.$checkForUpdates.on("change", () => this.updateCheckboxOption("checkForUpdates", this.$checkForUpdates)); this.$checkForUpdates.on("change", () => this.updateCheckboxOption("checkForUpdates", this.$checkForUpdates));
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.setCheckboxState(this.$checkForUpdates, options.checkForUpdates); this.setCheckboxState(this.$checkForUpdates, options.checkForUpdates);
} }
} }

View File

@ -2,6 +2,7 @@ import OptionsWidget from "../options_widget.js";
import server from "../../../../services/server.js"; import server from "../../../../services/server.js";
import toastService from "../../../../services/toast.js"; import toastService from "../../../../services/toast.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -13,13 +14,17 @@ const TPL = `
<label>${t("note_erasure_timeout.erase_notes_after_x_seconds")}</label> <label>${t("note_erasure_timeout.erase_notes_after_x_seconds")}</label>
<input class="erase-entities-after-time-in-seconds form-control options-number-input" type="number" min="0"> <input class="erase-entities-after-time-in-seconds form-control options-number-input" type="number" min="0">
</div> </div>
<p>${t("note_erasure_timeout.manual_erasing_description")}</p> <p>${t("note_erasure_timeout.manual_erasing_description")}</p>
<button class="erase-deleted-notes-now-button btn">${t("note_erasure_timeout.erase_deleted_notes_now")}</button> <button class="erase-deleted-notes-now-button btn">${t("note_erasure_timeout.erase_deleted_notes_now")}</button>
</div>`; </div>`;
export default class NoteErasureTimeoutOptions extends OptionsWidget { export default class NoteErasureTimeoutOptions extends OptionsWidget {
private $eraseEntitiesAfterTimeInSeconds!: JQuery<HTMLElement>;
private $eraseDeletedNotesButton!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$eraseEntitiesAfterTimeInSeconds = this.$widget.find(".erase-entities-after-time-in-seconds"); this.$eraseEntitiesAfterTimeInSeconds = this.$widget.find(".erase-entities-after-time-in-seconds");
@ -33,7 +38,7 @@ export default class NoteErasureTimeoutOptions extends OptionsWidget {
}); });
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$eraseEntitiesAfterTimeInSeconds.val(options.eraseEntitiesAfterTimeInSeconds); this.$eraseEntitiesAfterTimeInSeconds.val(options.eraseEntitiesAfterTimeInSeconds);
} }
} }

View File

@ -2,6 +2,7 @@ import OptionsWidget from "../options_widget.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import server from "../../../../services/server.js"; import server from "../../../../services/server.js";
import toastService from "../../../../services/toast.js"; import toastService from "../../../../services/toast.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -19,11 +20,15 @@ const TPL = `
</div>`; </div>`;
export default class RevisionSnapshotsLimitOptions extends OptionsWidget { export default class RevisionSnapshotsLimitOptions extends OptionsWidget {
private $revisionSnapshotsNumberLimit!: JQuery<HTMLElement>;
private $eraseExcessRevisionSnapshotsButton!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$revisionSnapshotsNumberLimit = this.$widget.find(".revision-snapshot-number-limit"); this.$revisionSnapshotsNumberLimit = this.$widget.find(".revision-snapshot-number-limit");
this.$revisionSnapshotsNumberLimit.on("change", () => { this.$revisionSnapshotsNumberLimit.on("change", () => {
let revisionSnapshotNumberLimit = this.$revisionSnapshotsNumberLimit.val(); let revisionSnapshotNumberLimit = parseInt(String(this.$revisionSnapshotsNumberLimit.val()), 10);
if (!isNaN(revisionSnapshotNumberLimit) && revisionSnapshotNumberLimit >= -1) { if (!isNaN(revisionSnapshotNumberLimit) && revisionSnapshotNumberLimit >= -1) {
this.updateOption("revisionSnapshotNumberLimit", revisionSnapshotNumberLimit); this.updateOption("revisionSnapshotNumberLimit", revisionSnapshotNumberLimit);
} }
@ -36,7 +41,7 @@ export default class RevisionSnapshotsLimitOptions extends OptionsWidget {
}); });
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$revisionSnapshotsNumberLimit.val(options.revisionSnapshotNumberLimit); this.$revisionSnapshotsNumberLimit.val(options.revisionSnapshotNumberLimit);
} }
} }

View File

@ -1,5 +1,6 @@
import OptionsWidget from "../options_widget.js"; import OptionsWidget from "../options_widget.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -14,13 +15,16 @@ const TPL = `
</div>`; </div>`;
export default class RevisionsSnapshotIntervalOptions extends OptionsWidget { export default class RevisionsSnapshotIntervalOptions extends OptionsWidget {
private $revisionsTimeInterval!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$revisionsTimeInterval = this.$widget.find(".revision-snapshot-time-interval-in-seconds"); this.$revisionsTimeInterval = this.$widget.find(".revision-snapshot-time-interval-in-seconds");
this.$revisionsTimeInterval.on("change", () => this.updateOption("revisionSnapshotTimeInterval", this.$revisionsTimeInterval.val())); this.$revisionsTimeInterval.on("change", () => this.updateOption("revisionSnapshotTimeInterval", this.$revisionsTimeInterval.val()));
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$revisionsTimeInterval.val(options.revisionSnapshotTimeInterval); this.$revisionsTimeInterval.val(options.revisionSnapshotTimeInterval);
} }
} }

View File

@ -1,13 +1,14 @@
import OptionsWidget from "../options_widget.js"; import OptionsWidget from "../options_widget.js";
import utils from "../../../../services/utils.js"; import utils from "../../../../services/utils.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t("search_engine.title")}</h4> <h4>${t("search_engine.title")}</h4>
<p>${t("search_engine.custom_search_engine_info")}</p> <p>${t("search_engine.custom_search_engine_info")}</p>
<form class="sync-setup-form"> <form class="sync-setup-form">
<div class="form-group"> <div class="form-group">
<label for="predefined-search-engine-select">${t("search_engine.predefined_templates_label")}</label> <label for="predefined-search-engine-select">${t("search_engine.predefined_templates_label")}</label>
@ -18,24 +19,24 @@ const TPL = `
<option value="Google">${t("search_engine.google")}</option> <option value="Google">${t("search_engine.google")}</option>
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>${t("search_engine.custom_name_label")}</label> <label>${t("search_engine.custom_name_label")}</label>
<input type="text" class="custom-search-engine-name form-control" placeholder="${t("search_engine.custom_name_placeholder")}"> <input type="text" class="custom-search-engine-name form-control" placeholder="${t("search_engine.custom_name_placeholder")}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>${t("search_engine.custom_url_label")}</label> <label>${t("search_engine.custom_url_label")}</label>
<input type="text" class="custom-search-engine-url form-control" placeholder="${t("search_engine.custom_url_placeholder")}"> <input type="text" class="custom-search-engine-url form-control" placeholder="${t("search_engine.custom_url_placeholder")}">
</div> </div>
<div style="display: flex; justify-content: space-between;"> <div style="display: flex; justify-content: space-between;">
<button class="btn btn-primary">${t("search_engine.save_button")}</button> <button class="btn btn-primary">${t("search_engine.save_button")}</button>
</div> </div>
</form> </form>
</div>`; </div>`;
const SEARCH_ENGINES = { const SEARCH_ENGINES: Record<string, string> = {
Bing: "https://www.bing.com/search?q={keyword}", Bing: "https://www.bing.com/search?q={keyword}",
Baidu: "https://www.baidu.com/s?wd={keyword}", Baidu: "https://www.baidu.com/s?wd={keyword}",
DuckDuckGo: "https://duckduckgo.com/?q={keyword}", DuckDuckGo: "https://duckduckgo.com/?q={keyword}",
@ -43,6 +44,12 @@ const SEARCH_ENGINES = {
}; };
export default class SearchEngineOptions extends OptionsWidget { export default class SearchEngineOptions extends OptionsWidget {
private $form!: JQuery<HTMLElement>;
private $predefinedSearchEngineSelect!: JQuery<HTMLElement>;
private $customSearchEngineName!: JQuery<HTMLInputElement>;
private $customSearchEngineUrl!: JQuery<HTMLInputElement>;
isEnabled() { isEnabled() {
return super.isEnabled() && utils.isElectron(); return super.isEnabled() && utils.isElectron();
} }
@ -56,7 +63,7 @@ export default class SearchEngineOptions extends OptionsWidget {
this.$customSearchEngineUrl = this.$widget.find(".custom-search-engine-url"); this.$customSearchEngineUrl = this.$widget.find(".custom-search-engine-url");
this.$predefinedSearchEngineSelect.on("change", () => { this.$predefinedSearchEngineSelect.on("change", () => {
const predefinedSearchEngine = this.$predefinedSearchEngineSelect.val(); const predefinedSearchEngine = String(this.$predefinedSearchEngineSelect.val());
this.$customSearchEngineName[0].value = predefinedSearchEngine; this.$customSearchEngineName[0].value = predefinedSearchEngine;
this.$customSearchEngineUrl[0].value = SEARCH_ENGINES[predefinedSearchEngine]; this.$customSearchEngineUrl[0].value = SEARCH_ENGINES[predefinedSearchEngine];
}); });
@ -69,7 +76,7 @@ export default class SearchEngineOptions extends OptionsWidget {
}); });
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$predefinedSearchEngineSelect.val(""); this.$predefinedSearchEngineSelect.val("");
this.$customSearchEngineName[0].value = options.customSearchEngineName; this.$customSearchEngineName[0].value = options.customSearchEngineName;
this.$customSearchEngineUrl[0].value = options.customSearchEngineUrl; this.$customSearchEngineUrl[0].value = options.customSearchEngineUrl;

View File

@ -1,6 +1,7 @@
import OptionsWidget from "../options_widget.js"; import OptionsWidget from "../options_widget.js";
import { t } from "../../../../services/i18n.js"; import { t } from "../../../../services/i18n.js";
import utils from "../../../../services/utils.js"; import utils from "../../../../services/utils.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -13,6 +14,9 @@ const TPL = `
</div>`; </div>`;
export default class TrayOptions extends OptionsWidget { export default class TrayOptions extends OptionsWidget {
private $trayEnabled!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$trayEnabled = this.$widget.find(".tray-enabled"); this.$trayEnabled = this.$widget.find(".tray-enabled");
@ -23,7 +27,7 @@ export default class TrayOptions extends OptionsWidget {
return utils.isElectron(); return utils.isElectron();
} }
async optionsLoaded(options) { async optionsLoaded(options: OptionMap) {
this.$trayEnabled.prop("checked", options.disableTray !== "true"); this.$trayEnabled.prop("checked", options.disableTray !== "true");
} }
} }