chore(client/ts): port options_widget

This commit is contained in:
Elian Doran 2025-01-03 18:40:52 +02:00
parent b6e97c1ae9
commit 428ffa7826
No known key found for this signature in database
3 changed files with 114 additions and 108 deletions

View File

@ -1,22 +1,27 @@
import { FilterOptionsByType, OptionDefinitions, OptionMap, OptionNames } from "../../../../../services/options_interface.js";
import { EventData, EventListener } from "../../../components/app_context.js";
import FNote from "../../../entities/fnote.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 NoteContextAwareWidget from "../../note_context_aware_widget.js"; import NoteContextAwareWidget from "../../note_context_aware_widget.js";
export default class OptionsWidget extends NoteContextAwareWidget { export default class OptionsWidget extends NoteContextAwareWidget
implements EventListener<"entitiesReloaded">
{
constructor() { constructor() {
super(); super();
this.contentSized(); this.contentSized();
} }
async updateOption(name, value) { async updateOption<T extends OptionNames>(name: T, value: string) {
const opts = { [name]: value }; const opts = { [name]: value };
await this.updateMultipleOptions(opts); await this.updateMultipleOptions(opts);
} }
async updateMultipleOptions(opts) { async updateMultipleOptions(opts: Partial<OptionMap>) {
await server.put('options', opts); await server.put('options', opts);
this.showUpdateNotification(); this.showUpdateNotification();
@ -32,17 +37,17 @@ export default class OptionsWidget extends NoteContextAwareWidget {
}); });
} }
async updateCheckboxOption(name, $checkbox) { async updateCheckboxOption<T extends FilterOptionsByType<boolean>>(name: T, $checkbox: JQuery<HTMLElement>) {
const isChecked = $checkbox.prop("checked"); const isChecked = $checkbox.prop("checked");
return await this.updateOption(name, isChecked ? 'true' : 'false'); return await this.updateOption(name, isChecked ? 'true' : 'false');
} }
setCheckboxState($checkbox, optionValue) { setCheckboxState($checkbox: JQuery<HTMLElement>, optionValue: string) {
$checkbox.prop('checked', optionValue === 'true'); $checkbox.prop('checked', optionValue === 'true');
} }
optionsLoaded(options) {} optionsLoaded(options: OptionMap) {}
async refresh() { async refresh() {
this.toggleInt(this.isEnabled()); this.toggleInt(this.isEnabled());
@ -58,15 +63,15 @@ export default class OptionsWidget extends NoteContextAwareWidget {
} }
} }
async refreshWithNote(note) { async refreshWithNote(note: FNote) {
const options = await server.get('options'); const options = await server.get<OptionMap>('options');
if (options) { if (options) {
this.optionsLoaded(options); this.optionsLoaded(options);
} }
} }
async entitiesReloadedEvent({loadResults}) { async entitiesReloadedEvent({loadResults}: EventData<"entitiesReloaded">) {
if (loadResults.getOptionNames().length > 0) { if (loadResults.getOptionNames().length > 0) {
this.refresh(); this.refresh();
} }

View File

@ -15,107 +15,9 @@
import becca from "../becca/becca.js"; import becca from "../becca/becca.js";
import BOption from "../becca/entities/boption.js"; import BOption from "../becca/entities/boption.js";
import { OptionRow } from '../becca/entities/rows.js'; import { OptionRow } from '../becca/entities/rows.js';
import { KeyboardActionNames } from "./keyboard_actions_interface.js"; import { FilterOptionsByType, OptionDefinitions, OptionMap, OptionNames } from "./options_interface.js";
import sql from "./sql.js"; import sql from "./sql.js";
/**
* For each keyboard action, there is a corresponding option which identifies the key combination defined by the user.
*/
type KeyboardShortcutsOptions<T extends KeyboardActionNames> = {
[key in T as `keyboardShortcuts${Capitalize<key>}`]: string
};
interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActionNames> {
"openNoteContexts": string;
"lastDailyBackupDate": string;
"lastWeeklyBackupDate": string;
"lastMonthlyBackupDate": string;
"dbVersion": string;
"theme": string;
"syncServerHost": string;
"syncServerTimeout": string;
"syncProxy": string;
"mainFontFamily": string;
"treeFontFamily": string;
"detailFontFamily": string;
"monospaceFontFamily": string;
"spellCheckLanguageCode": string;
"codeNotesMimeTypes": string;
"headingStyle": string;
"highlightsList": string;
"customSearchEngineName": string;
"customSearchEngineUrl": string;
"locale": string;
"codeBlockTheme": string;
"textNoteEditorType": string;
"layoutOrientation": string;
"allowedHtmlTags": string;
"documentId": string;
"documentSecret": string;
"passwordVerificationHash": string;
"passwordVerificationSalt": string;
"passwordDerivedKeySalt": string;
"encryptedDataKey": string;
"lastSyncedPull": number;
"lastSyncedPush": number;
"revisionSnapshotTimeInterval": number;
"revisionSnapshotNumberLimit": number;
"protectedSessionTimeout": number;
"zoomFactor": number;
"mainFontSize": number;
"treeFontSize": number;
"detailFontSize": number;
"monospaceFontSize": number;
"imageMaxWidthHeight": number;
"imageJpegQuality": number;
"leftPaneWidth": number;
"rightPaneWidth": number;
"eraseEntitiesAfterTimeInSeconds": number;
"autoReadonlySizeText": number;
"autoReadonlySizeCode": number;
"maxContentWidth": number;
"minTocHeadings": number;
"eraseUnusedAttachmentsAfterSeconds": number;
"firstDayOfWeek": number;
"initialized": boolean;
"overrideThemeFonts": boolean;
"spellCheckEnabled": boolean;
"autoFixConsistencyIssues": boolean;
"vimKeymapEnabled": boolean;
"codeLineWrapEnabled": boolean;
"leftPaneVisible": boolean;
"rightPaneVisible": boolean;
"nativeTitleBarVisible": boolean;
"hideArchivedNotes_main": boolean;
"debugModeEnabled": boolean;
"autoCollapseNoteTree": boolean;
"dailyBackupEnabled": boolean;
"weeklyBackupEnabled": boolean;
"monthlyBackupEnabled": boolean;
"compressImages": boolean;
"downloadImagesAutomatically": boolean;
"checkForUpdates": boolean;
"disableTray": boolean;
"promotedAttributesOpenInRibbon": boolean;
"editedNotesOpenInRibbon": boolean;
"codeBlockWordWrap": boolean;
"textNoteEditorMultilineToolbar": boolean;
"backgroundEffects": boolean;
};
export type OptionNames = keyof OptionDefinitions;
type FilterOptionsByType<U> = {
[K in keyof OptionDefinitions]: OptionDefinitions[K] extends U ? K : never;
}[keyof OptionDefinitions];
/**
* A dictionary where the keys are the option keys (e.g. `theme`) and their corresponding values.
*/
export type OptionMap = Record<OptionNames, string>;
function getOptionOrNull(name: OptionNames): string | null { function getOptionOrNull(name: OptionNames): string | null {
let option; let option;

View File

@ -0,0 +1,99 @@
import { KeyboardActionNames } from "./keyboard_actions_interface.js";
/**
* A dictionary where the keys are the option keys (e.g. `theme`) and their corresponding values.
*/
export type OptionMap = Record<OptionNames, string>;
/**
* For each keyboard action, there is a corresponding option which identifies the key combination defined by the user.
*/
type KeyboardShortcutsOptions<T extends KeyboardActionNames> = {
[key in T as `keyboardShortcuts${Capitalize<key>}`]: string
};
export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActionNames> {
"openNoteContexts": string;
"lastDailyBackupDate": string;
"lastWeeklyBackupDate": string;
"lastMonthlyBackupDate": string;
"dbVersion": string;
"theme": string;
"syncServerHost": string;
"syncServerTimeout": string;
"syncProxy": string;
"mainFontFamily": string;
"treeFontFamily": string;
"detailFontFamily": string;
"monospaceFontFamily": string;
"spellCheckLanguageCode": string;
"codeNotesMimeTypes": string;
"headingStyle": string;
"highlightsList": string;
"customSearchEngineName": string;
"customSearchEngineUrl": string;
"locale": string;
"codeBlockTheme": string;
"textNoteEditorType": string;
"layoutOrientation": string;
"allowedHtmlTags": string;
"documentId": string;
"documentSecret": string;
"passwordVerificationHash": string;
"passwordVerificationSalt": string;
"passwordDerivedKeySalt": string;
"encryptedDataKey": string;
"lastSyncedPull": number;
"lastSyncedPush": number;
"revisionSnapshotTimeInterval": number;
"revisionSnapshotNumberLimit": number;
"protectedSessionTimeout": number;
"zoomFactor": number;
"mainFontSize": number;
"treeFontSize": number;
"detailFontSize": number;
"monospaceFontSize": number;
"imageMaxWidthHeight": number;
"imageJpegQuality": number;
"leftPaneWidth": number;
"rightPaneWidth": number;
"eraseEntitiesAfterTimeInSeconds": number;
"autoReadonlySizeText": number;
"autoReadonlySizeCode": number;
"maxContentWidth": number;
"minTocHeadings": number;
"eraseUnusedAttachmentsAfterSeconds": number;
"firstDayOfWeek": number;
"initialized": boolean;
"overrideThemeFonts": boolean;
"spellCheckEnabled": boolean;
"autoFixConsistencyIssues": boolean;
"vimKeymapEnabled": boolean;
"codeLineWrapEnabled": boolean;
"leftPaneVisible": boolean;
"rightPaneVisible": boolean;
"nativeTitleBarVisible": boolean;
"hideArchivedNotes_main": boolean;
"debugModeEnabled": boolean;
"autoCollapseNoteTree": boolean;
"dailyBackupEnabled": boolean;
"weeklyBackupEnabled": boolean;
"monthlyBackupEnabled": boolean;
"compressImages": boolean;
"downloadImagesAutomatically": boolean;
"checkForUpdates": boolean;
"disableTray": boolean;
"promotedAttributesOpenInRibbon": boolean;
"editedNotesOpenInRibbon": boolean;
"codeBlockWordWrap": boolean;
"textNoteEditorMultilineToolbar": boolean;
"backgroundEffects": boolean;
};
export type OptionNames = keyof OptionDefinitions;
export type FilterOptionsByType<U> = {
[K in keyof OptionDefinitions]: OptionDefinitions[K] extends U ? K : never;
}[keyof OptionDefinitions];