mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-05 12:25:22 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 801bac9e09 |
@@ -1,360 +0,0 @@
|
|||||||
# Architectural Decision Record: Setting Definition Repository
|
|
||||||
|
|
||||||
## Status
|
|
||||||
|
|
||||||
Proposed
|
|
||||||
|
|
||||||
## Release
|
|
||||||
|
|
||||||
Not scheduled. Intended as a design direction before refactoring the settings dialogue.
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
The current settings dialogue is implemented around `ObsidianLiveSyncSettingTab`.
|
|
||||||
It is effective and feature rich, but several responsibilities are combined in the
|
|
||||||
same layer:
|
|
||||||
|
|
||||||
- editing-state buffering and dirty-state tracking,
|
|
||||||
- local-only dialogue state such as `configPassphrase`, `preset`, `syncMode`, and
|
|
||||||
`deviceAndVaultName`,
|
|
||||||
- persistence through `SettingService`,
|
|
||||||
- Obsidian `Setting` component rendering,
|
|
||||||
- pane layout and visibility rules,
|
|
||||||
- validation and value coercion,
|
|
||||||
- setup wizard transitions,
|
|
||||||
- rebuild/restart side effects,
|
|
||||||
- remote diagnostics and maintenance actions.
|
|
||||||
|
|
||||||
Some setting metadata already exists in `configurationNames` and related setting
|
|
||||||
constants. This is a useful seed, but it is not a complete source of truth. The
|
|
||||||
metadata does not currently describe storage domain, value kind, validation,
|
|
||||||
capability requirements, migration behaviour, cross-setting dependencies, or
|
|
||||||
whether a value should be rendered by a generic control or a custom pane.
|
|
||||||
|
|
||||||
The settings dialogue also contains a mix of simple controls and workflow panels.
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- Simple controls: `showStatusOnEditor`, `syncOnSave`, `customChunkSize`,
|
|
||||||
`readChunksOnline`, `useTimeouts`.
|
|
||||||
- Derived or dialogue-only values: `syncMode`, `preset`, `configPassphrase`,
|
|
||||||
`deviceAndVaultName`.
|
|
||||||
- Workflow panels: remote configuration management, E2EE setup, setup wizard,
|
|
||||||
local/remote rebuild, maintenance commands, Customisation Sync dialogue open.
|
|
||||||
|
|
||||||
This matters primarily for maintainability and platform independence. A setting
|
|
||||||
should have one shared definition of its domain meaning regardless of whether it
|
|
||||||
is displayed in Obsidian, surfaced in a CLI, used by a WebApp, or documented.
|
|
||||||
Tests benefit from this separation, but testability is a consequence rather than
|
|
||||||
the main design goal.
|
|
||||||
|
|
||||||
Real Obsidian E2E remains the right signal for Obsidian shell behaviour such as
|
|
||||||
opening the settings tab, rendering real Obsidian components, and verifying
|
|
||||||
user-visible workflows. Harness-based tests can then focus on deterministic
|
|
||||||
setting semantics that no longer depend on mounting the whole Obsidian setting
|
|
||||||
tab.
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
Introduce a platform-neutral Setting Definition Repository as the source of
|
|
||||||
truth for setting metadata and setting semantics.
|
|
||||||
|
|
||||||
The repository should live in the shared domain layer, not under the Obsidian
|
|
||||||
dialogue implementation and not under a generic model bucket. In the current
|
|
||||||
layout this means `src/lib/src/common/settings`.
|
|
||||||
|
|
||||||
The repository should not be an Obsidian UI abstraction. It should describe what
|
|
||||||
a setting is and how it behaves. Obsidian, CLI, WebApp, tests, and documentation
|
|
||||||
can then consume the same definitions through their own renderers or adapters.
|
|
||||||
The Obsidian settings tab should use an Obsidian renderer that maps repository
|
|
||||||
definitions to native Obsidian `Setting` components for simple controls, while
|
|
||||||
workflow panes remain custom.
|
|
||||||
|
|
||||||
The existing Obsidian setting dialogue should be migrated incrementally. Complex
|
|
||||||
workflow panes should remain custom-rendered at first. Simple controls should
|
|
||||||
move to repository-driven rendering first.
|
|
||||||
|
|
||||||
## Proposed Model
|
|
||||||
|
|
||||||
Each setting definition should describe a single setting key or a dialogue-only
|
|
||||||
virtual key.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
type SettingStorageDomain = "persisted" | "local" | "derived" | "ephemeral";
|
|
||||||
|
|
||||||
type SettingValueKind = "boolean" | "text" | "password" | "number" | "select" | "textarea" | "string-list" | "custom";
|
|
||||||
|
|
||||||
type SettingCapability = "database-user" | "server-admin" | "filesystem" | "obsidian-shell" | "obsidian-plugin-host";
|
|
||||||
|
|
||||||
type SettingDefinition<TSettings, TKey extends keyof TSettings | string> = {
|
|
||||||
key: TKey;
|
|
||||||
storage: SettingStorageDomain;
|
|
||||||
kind: SettingValueKind;
|
|
||||||
defaultValue?: unknown;
|
|
||||||
labelKey: string;
|
|
||||||
descriptionKey?: string;
|
|
||||||
label: string;
|
|
||||||
description?: string;
|
|
||||||
category: string;
|
|
||||||
pane?: string;
|
|
||||||
section?: string;
|
|
||||||
level?: "ADVANCED" | "POWER_USER" | "EDGE_CASE";
|
|
||||||
status?: "BETA" | "ALPHA" | "EXPERIMENTAL";
|
|
||||||
obsolete?: boolean;
|
|
||||||
internal?: boolean;
|
|
||||||
placeholder?: string;
|
|
||||||
options?: Record<string, string>;
|
|
||||||
secret?: boolean;
|
|
||||||
requiredCapabilities?: SettingCapability[];
|
|
||||||
visible?: (context: SettingEvaluationContext<TSettings>) => boolean;
|
|
||||||
enabled?: (context: SettingEvaluationContext<TSettings>) => boolean;
|
|
||||||
validate?: (value: unknown, context: SettingEvaluationContext<TSettings>) => SettingValidationResult;
|
|
||||||
coerce?: (value: unknown, context: SettingEvaluationContext<TSettings>) => unknown;
|
|
||||||
affects?: SettingEffect[];
|
|
||||||
commit?: SettingCommitPolicy<TKey>;
|
|
||||||
render?: "auto" | "custom";
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
`SettingEvaluationContext` should carry the current editing settings, persisted
|
|
||||||
settings, platform capabilities, and remote capability information if known. It
|
|
||||||
should not carry an Obsidian `App`.
|
|
||||||
|
|
||||||
`labelKey` and `descriptionKey` should be i18n keys. During migration, the key
|
|
||||||
may be the literal English text already used by `configurationNames` and
|
|
||||||
`SettingInformation`. This matches the current i18n behaviour where an unknown
|
|
||||||
key resolves to the key itself, avoids adding translation resources up front, and
|
|
||||||
lets us later replace literal keys with stable resource keys without changing
|
|
||||||
consumers. `label` and `description` remain compatibility aliases while existing
|
|
||||||
code still expects resolved strings.
|
|
||||||
|
|
||||||
`internal` should mark settings that are not currently editable from the UI.
|
|
||||||
Obsolete settings are internal by default. Missing UI metadata alone should not
|
|
||||||
make a setting internal; `kind`, `render`, and explicit `internal` metadata
|
|
||||||
should decide whether the automatic renderer can safely handle it.
|
|
||||||
|
|
||||||
`commit` should describe when a value is persisted, not how a button is rendered.
|
|
||||||
Immediate settings can save on change. Explicit settings are held in the editing
|
|
||||||
buffer until an apply action commits the configured group. This keeps apply
|
|
||||||
buttons out of the repository while still making grouped save behaviour
|
|
||||||
testable.
|
|
||||||
|
|
||||||
## Storage Domains
|
|
||||||
|
|
||||||
Settings should be classified by where they live:
|
|
||||||
|
|
||||||
- `persisted`: normal `ObsidianLiveSyncSettings` values saved through
|
|
||||||
`SettingService`.
|
|
||||||
- `local`: values stored outside the main settings document, for example local
|
|
||||||
storage or device/vault identity.
|
|
||||||
- `derived`: values computed from persisted settings, for example `syncMode`.
|
|
||||||
- `ephemeral`: dialogue-only inputs such as `preset`.
|
|
||||||
|
|
||||||
This makes current special cases explicit:
|
|
||||||
|
|
||||||
- `configPassphrase` is local-only.
|
|
||||||
- `deviceAndVaultName` is local/service managed.
|
|
||||||
- `syncMode` is derived from `liveSync` and `periodicReplication`.
|
|
||||||
- `preset` is ephemeral and expands to several persisted settings.
|
|
||||||
|
|
||||||
## Rendering Strategy
|
|
||||||
|
|
||||||
The repository should support generic rendering, but it should not force every
|
|
||||||
pane to become schema-driven immediately.
|
|
||||||
|
|
||||||
Use three levels:
|
|
||||||
|
|
||||||
1. **Auto-rendered controls**
|
|
||||||
Simple `boolean`, `number`, `text`, `password`, `select`, and `textarea`
|
|
||||||
settings. These can replace many `new Setting(...).autoWire...` calls.
|
|
||||||
|
|
||||||
2. **Repository-defined groups with custom sections**
|
|
||||||
A pane can declare layout, headings, and order through the repository but keep
|
|
||||||
a custom renderer for the section body.
|
|
||||||
|
|
||||||
3. **Fully custom workflow panes**
|
|
||||||
Remote configuration management, E2EE setup, setup wizard, maintenance, and
|
|
||||||
rebuild flows should remain custom until their side effects are separately
|
|
||||||
modelled.
|
|
||||||
|
|
||||||
The Obsidian setting dialogue becomes a renderer of repository definitions plus a
|
|
||||||
host for custom workflow panes.
|
|
||||||
|
|
||||||
## Side Effects
|
|
||||||
|
|
||||||
Setting changes should distinguish value persistence from effects.
|
|
||||||
|
|
||||||
Examples of effects:
|
|
||||||
|
|
||||||
- `requires-local-rebuild`
|
|
||||||
- `requires-remote-rebuild`
|
|
||||||
- `requires-restart`
|
|
||||||
- `requires-apply-settings`
|
|
||||||
- `suspends-sync`
|
|
||||||
- `updates-unresolved-error-ui`
|
|
||||||
- `changes-active-remote`
|
|
||||||
- `expands-preset`
|
|
||||||
|
|
||||||
The current `isNeedRebuildLocal()` and `isNeedRebuildRemote()` methods should
|
|
||||||
eventually be replaced by repository metadata. This would make rebuild prompts
|
|
||||||
testable without rendering the full settings tab.
|
|
||||||
|
|
||||||
## Capability Requirements
|
|
||||||
|
|
||||||
Some settings and actions require capabilities that not all users or platforms
|
|
||||||
have.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- CouchDB server diagnostics and automatic CouchDB repair require server-admin
|
|
||||||
capability.
|
|
||||||
- Normal CouchDB sync requires only database-user capability.
|
|
||||||
- Hidden File Sync and Customisation Sync require filesystem capability.
|
|
||||||
- Obsidian plug-in reload requires obsidian-plugin-host capability.
|
|
||||||
- Opening settings panes and workspace views requires obsidian-shell capability.
|
|
||||||
|
|
||||||
Capability metadata should be used for:
|
|
||||||
|
|
||||||
- warning text in Obsidian settings,
|
|
||||||
- disabling unsupported actions,
|
|
||||||
- CLI/WebApp help output,
|
|
||||||
- Harness tests for visibility and enabled-state rules.
|
|
||||||
|
|
||||||
The repository should not introduce a generic cross-platform `PluginManager`
|
|
||||||
concept. Obsidian plug-in host behaviour should remain an Obsidian-specific
|
|
||||||
adapter or custom workflow.
|
|
||||||
|
|
||||||
## Current Assumptions to Preserve
|
|
||||||
|
|
||||||
- Settings can be edited in a buffer before being saved.
|
|
||||||
- Some values save immediately unless `holdValue` is set.
|
|
||||||
- Some values require explicit Apply buttons.
|
|
||||||
- Visibility and enabled-state often depend on other editing values.
|
|
||||||
- Some settings are hidden in setup wizard mode.
|
|
||||||
- Advanced, power-user, and edge-case levels remain supported.
|
|
||||||
- The dialogue can be reloaded while preserving dirty local edits.
|
|
||||||
- Existing `SettingService` remains responsible for encryption, persistence,
|
|
||||||
migration, and applying settings.
|
|
||||||
- Existing complex setup and remote configuration workflows remain custom.
|
|
||||||
|
|
||||||
## Migration Plan
|
|
||||||
|
|
||||||
### Phase 1: Repository Skeleton
|
|
||||||
|
|
||||||
- Create a repository module in the shared setting domain
|
|
||||||
(`src/lib/src/common/settings`), not under the Obsidian dialogue folder.
|
|
||||||
- Move existing `configurationNames` metadata into repository definitions without
|
|
||||||
changing runtime behaviour.
|
|
||||||
- Add storage domain, kind, i18n keys, internal marker, pane, section, level, and
|
|
||||||
secret metadata for a small subset of settings.
|
|
||||||
- Keep `getConfig()`, `getConfName()`, and existing callers working through a
|
|
||||||
compatibility facade.
|
|
||||||
|
|
||||||
### Phase 2: Evaluation API
|
|
||||||
|
|
||||||
- Add pure functions:
|
|
||||||
- `getSettingDefinition(key)`
|
|
||||||
- `listSettingDefinitions(filter)`
|
|
||||||
- `evaluateSetting(definition, context)`
|
|
||||||
- `validateSettingValue(key, value, context)`
|
|
||||||
- `getSettingEffects(changedKeys, context)`
|
|
||||||
- Add unit tests for derived values, visibility, enabled-state, validation, and
|
|
||||||
rebuild/restart effects.
|
|
||||||
|
|
||||||
### Phase 3: Obsidian Renderer for Simple Controls
|
|
||||||
|
|
||||||
- Add a small renderer that maps repository definitions to Obsidian `Setting`
|
|
||||||
controls.
|
|
||||||
- Migrate one low-risk pane first, likely Appearance/Logging or Advanced memory
|
|
||||||
cache settings.
|
|
||||||
- Keep custom panes untouched.
|
|
||||||
- Keep `LiveSyncSetting` as a compatibility wrapper during migration.
|
|
||||||
|
|
||||||
### Phase 4: Derived and Local Values
|
|
||||||
|
|
||||||
- Model `syncMode`, `preset`, `configPassphrase`, and `deviceAndVaultName`
|
|
||||||
explicitly.
|
|
||||||
- Replace ad hoc save paths in `ObsidianLiveSyncSettingTab` with storage-domain
|
|
||||||
handlers.
|
|
||||||
- Keep user-visible behaviour unchanged.
|
|
||||||
|
|
||||||
### Phase 5: Effects and Capability Warnings
|
|
||||||
|
|
||||||
- Replace `isNeedRebuildLocal()` and `isNeedRebuildRemote()` with
|
|
||||||
repository-driven effect calculation.
|
|
||||||
- Model explicit commit groups for settings that must be applied together, for
|
|
||||||
example configuration encryption passphrase settings, setting sync file, and
|
|
||||||
database suffix changes.
|
|
||||||
- Add capability metadata for CouchDB diagnostics, repair, Hidden File Sync, and
|
|
||||||
Obsidian-only plug-in operations.
|
|
||||||
- Use this to improve warnings for database-scoped CouchDB users and
|
|
||||||
administrator-only actions.
|
|
||||||
|
|
||||||
### Phase 6: Documentation and Non-Obsidian Consumers
|
|
||||||
|
|
||||||
- Treat documentation as an authored source, not as an output that must be fully
|
|
||||||
generated from code.
|
|
||||||
- Optionally combine repository metadata with a documentation source such as YAML
|
|
||||||
to generate or lint `docs/settings.md`.
|
|
||||||
- Use the repository to verify that documented settings exist, that defaults and
|
|
||||||
storage domains are consistent, and that internal settings are intentionally
|
|
||||||
omitted or documented as internal.
|
|
||||||
- Expose repository metadata to CLI/WebApp where useful.
|
|
||||||
- Let Harness tests assert the same repository semantics used by Obsidian.
|
|
||||||
|
|
||||||
## Testing Strategy
|
|
||||||
|
|
||||||
Use Harness or unit tests for:
|
|
||||||
|
|
||||||
- default value coverage,
|
|
||||||
- type/kind consistency,
|
|
||||||
- every persisted setting has a definition or is explicitly internal,
|
|
||||||
- visibility and enabled-state predicates,
|
|
||||||
- derived values such as `syncMode`,
|
|
||||||
- preset expansion,
|
|
||||||
- rebuild/restart effect calculation,
|
|
||||||
- capability warnings.
|
|
||||||
|
|
||||||
Use real Obsidian E2E for:
|
|
||||||
|
|
||||||
- opening the actual setting tab,
|
|
||||||
- rendering Obsidian `Setting` components,
|
|
||||||
- setup wizard flow,
|
|
||||||
- remote configuration workflow,
|
|
||||||
- actual restart prompts,
|
|
||||||
- workflows that depend on Obsidian settings shell behaviour.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
Positive:
|
|
||||||
|
|
||||||
- Setting semantics are maintained in one platform-neutral place.
|
|
||||||
- Setting semantics become testable without mounting Obsidian UI.
|
|
||||||
- Documentation, CLI, WebApp, and Obsidian can share setting metadata where it is
|
|
||||||
useful.
|
|
||||||
- Capability-sensitive settings become explicit.
|
|
||||||
- Future settings are less likely to be implemented in only one surface.
|
|
||||||
- The Obsidian settings dialogue can be refactored incrementally.
|
|
||||||
|
|
||||||
Negative:
|
|
||||||
|
|
||||||
- There will be a temporary compatibility layer between old setting constants and
|
|
||||||
the repository.
|
|
||||||
- Some panes will remain custom, so the repository will not remove all UI code.
|
|
||||||
- Definition metadata can become stale if not enforced by tests.
|
|
||||||
- Over-generalising workflow panes would make the repository harder to maintain.
|
|
||||||
|
|
||||||
## Non-Goals
|
|
||||||
|
|
||||||
- Do not replace `SettingService` persistence in the first phase.
|
|
||||||
- Do not make Obsidian plug-in host operations cross-platform.
|
|
||||||
- Do not convert all setting panes to schema-driven UI at once.
|
|
||||||
- Do not require real Obsidian E2E for every setting definition.
|
|
||||||
- Do not remove custom renderers for remote setup, E2EE setup, or maintenance
|
|
||||||
workflows.
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
- What should the exact `CapabilityProvider` interface look like for static
|
|
||||||
platform capabilities and runtime-probed remote capabilities? This should be
|
|
||||||
decided while implementing the Obsidian renderer so the interface follows a
|
|
||||||
real consumer instead of an abstract capability model.
|
|
||||||
+1
-1
Submodule src/lib updated: c7c5fe21be...5c1033485e
@@ -8,13 +8,7 @@ import {
|
|||||||
type ValueComponent,
|
type ValueComponent,
|
||||||
} from "@/deps.ts";
|
} from "@/deps.ts";
|
||||||
import { unique } from "octagonal-wheels/collection";
|
import { unique } from "octagonal-wheels/collection";
|
||||||
import {
|
import { LEVEL_ADVANCED, LEVEL_POWER_USER, statusDisplay, type ConfigurationItem } from "@lib/common/types.ts";
|
||||||
LEVEL_ADVANCED,
|
|
||||||
LEVEL_POWER_USER,
|
|
||||||
statusDisplay,
|
|
||||||
type ConfigurationItem,
|
|
||||||
type SettingDefinition,
|
|
||||||
} from "@lib/common/types.ts";
|
|
||||||
import { type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import { type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import {
|
import {
|
||||||
type AllSettingItemKey,
|
type AllSettingItemKey,
|
||||||
@@ -24,21 +18,9 @@ import {
|
|||||||
type AllNumericItemKey,
|
type AllNumericItemKey,
|
||||||
type AllBooleanItemKey,
|
type AllBooleanItemKey,
|
||||||
} from "./settingConstants.ts";
|
} from "./settingConstants.ts";
|
||||||
import { $msg, $t } from "@lib/common/i18n.ts";
|
import { $msg } from "@lib/common/i18n.ts";
|
||||||
import { wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts";
|
import { wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts";
|
||||||
|
|
||||||
function configurationFromDefinition(definition: SettingDefinition<AllSettingItemKey>): ConfigurationItem {
|
|
||||||
return {
|
|
||||||
name: $t(definition.labelKey),
|
|
||||||
desc: definition.descriptionKey ? $t(definition.descriptionKey) : undefined,
|
|
||||||
placeHolder: definition.placeholder,
|
|
||||||
status: definition.status,
|
|
||||||
obsolete: definition.obsolete,
|
|
||||||
level: definition.level,
|
|
||||||
isHidden: definition.secret,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LiveSyncSetting extends Setting {
|
export class LiveSyncSetting extends Setting {
|
||||||
autoWiredComponent?: TextComponent | ToggleComponent | DropdownComponent | ButtonComponent | TextAreaComponent;
|
autoWiredComponent?: TextComponent | ToggleComponent | DropdownComponent | ButtonComponent | TextAreaComponent;
|
||||||
applyButtonComponent?: ButtonComponent;
|
applyButtonComponent?: ButtonComponent;
|
||||||
@@ -74,7 +56,7 @@ export class LiveSyncSetting extends Setting {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
autoWireSetting(key: AllSettingItemKey, opt?: AutoWireOption) {
|
autoWireSetting(key: AllSettingItemKey, opt?: AutoWireOption) {
|
||||||
const conf = opt?.settingDefinition ? configurationFromDefinition(opt.settingDefinition) : getConfig(key);
|
const conf = getConfig(key);
|
||||||
if (!conf) {
|
if (!conf) {
|
||||||
// throw new Error($msg("liveSyncSetting.errorNoSuchSettingItem", { key }));
|
// throw new Error($msg("liveSyncSetting.errorNoSuchSettingItem", { key }));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
import {
|
|
||||||
getExplicitSettingCommitGroup,
|
|
||||||
getSettingDefinition,
|
|
||||||
type AllBooleanItemKey,
|
|
||||||
type AllNumericItemKey,
|
|
||||||
type AllSettingItemKey,
|
|
||||||
type AllStringItemKey,
|
|
||||||
} from "./settingConstants.ts";
|
|
||||||
import type { LiveSyncSetting } from "./LiveSyncSetting.ts";
|
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
|
||||||
import type { AutoWireOption } from "./SettingPane.ts";
|
|
||||||
|
|
||||||
export type ObsidianSettingRenderOption<TOption extends string = string> = AutoWireOption & {
|
|
||||||
options?: Record<TOption, string>;
|
|
||||||
clampMin?: number;
|
|
||||||
clampMax?: number;
|
|
||||||
acceptZero?: boolean;
|
|
||||||
renderInternal?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function addObsidianApplyButton(setting: LiveSyncSetting, group: string, text?: string): LiveSyncSetting {
|
|
||||||
const commitGroup = getExplicitSettingCommitGroup(group);
|
|
||||||
if (!commitGroup) {
|
|
||||||
throw new Error(`No explicit setting commit group found for '${group}'`);
|
|
||||||
}
|
|
||||||
return setting.addApplyButton(commitGroup.applyKeys, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderObsidianApplyButton(containerEl: HTMLElement, group: string, text?: string): LiveSyncSetting {
|
|
||||||
return addObsidianApplyButton(new Setting(containerEl), group, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderObsidianSetting<TOption extends string = string>(
|
|
||||||
containerEl: HTMLElement,
|
|
||||||
key: AllSettingItemKey,
|
|
||||||
opt: ObsidianSettingRenderOption<TOption> = {}
|
|
||||||
): LiveSyncSetting {
|
|
||||||
const definition = getSettingDefinition(key);
|
|
||||||
if (!definition) {
|
|
||||||
throw new Error(`No setting definition found for '${key}'`);
|
|
||||||
}
|
|
||||||
if (definition.internal && !opt.renderInternal) {
|
|
||||||
throw new Error(`Setting '${key}' is internal and cannot be rendered automatically`);
|
|
||||||
}
|
|
||||||
if (definition.render === "custom" || definition.kind === "custom") {
|
|
||||||
throw new Error(`Setting '${key}' requires a custom renderer`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isExplicitCommit = definition.commit?.mode === "explicit";
|
|
||||||
const holdValue = opt.holdValue ?? isExplicitCommit;
|
|
||||||
const setting = new Setting(containerEl);
|
|
||||||
const wireOption = {
|
|
||||||
...opt,
|
|
||||||
holdValue,
|
|
||||||
settingDefinition: definition,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (opt.options) {
|
|
||||||
return setting.autoWireDropDown(key as AllStringItemKey, { ...wireOption, options: opt.options });
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (definition.kind) {
|
|
||||||
case "boolean":
|
|
||||||
return setting.autoWireToggle(key as AllBooleanItemKey, wireOption);
|
|
||||||
case "number":
|
|
||||||
return setting.autoWireNumeric(key as AllNumericItemKey, wireOption);
|
|
||||||
case "password":
|
|
||||||
return setting.autoWireText(key as AllStringItemKey, { ...wireOption, isPassword: true });
|
|
||||||
case "textarea":
|
|
||||||
return setting.autoWireTextArea(key as AllStringItemKey, wireOption);
|
|
||||||
case "select":
|
|
||||||
throw new Error(`Setting '${key}' requires select options`);
|
|
||||||
case "text":
|
|
||||||
return setting.autoWireText(key as AllStringItemKey, wireOption);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +1,41 @@
|
|||||||
import { ChunkAlgorithmNames } from "@lib/common/types.ts";
|
import { ChunkAlgorithmNames } from "@lib/common/types.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
|
|
||||||
export function paneAdvanced(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
export function paneAdvanced(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
||||||
void addPanel(paneEl, "Memory cache").then((paneEl) => {
|
void addPanel(paneEl, "Memory cache").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "hashCacheMaxCount", { clampMin: 10 });
|
new Setting(paneEl).autoWireNumeric("hashCacheMaxCount", { clampMin: 10 });
|
||||||
// renderObsidianSetting(paneEl, "hashCacheMaxAmount", { clampMin: 1 });
|
// new Setting(paneEl).autoWireNumeric("hashCacheMaxAmount", { clampMin: 1 });
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Local Database Tweak").then((paneEl) => {
|
void addPanel(paneEl, "Local Database Tweak").then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
|
|
||||||
const items = ChunkAlgorithmNames;
|
const items = ChunkAlgorithmNames;
|
||||||
renderObsidianSetting(paneEl, "chunkSplitterVersion", {
|
new Setting(paneEl).autoWireDropDown("chunkSplitterVersion", {
|
||||||
options: items,
|
options: items,
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "customChunkSize", { clampMin: 0, acceptZero: true });
|
new Setting(paneEl).autoWireNumeric("customChunkSize", { clampMin: 0, acceptZero: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Transfer Tweak").then((paneEl) => {
|
void addPanel(paneEl, "Transfer Tweak").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "readChunksOnline", { onUpdate: this.onlyOnCouchDB }).setClass("wizardHidden");
|
new Setting(paneEl)
|
||||||
renderObsidianSetting(paneEl, "useOnlyLocalChunk", { onUpdate: this.onlyOnCouchDB }).setClass("wizardHidden");
|
.setClass("wizardHidden")
|
||||||
|
.autoWireToggle("readChunksOnline", { onUpdate: this.onlyOnCouchDB });
|
||||||
|
new Setting(paneEl)
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.autoWireToggle("useOnlyLocalChunk", { onUpdate: this.onlyOnCouchDB });
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "concurrencyOfReadChunksOnline", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("concurrencyOfReadChunksOnline", {
|
||||||
clampMin: 10,
|
clampMin: 10,
|
||||||
onUpdate: this.onlyOnCouchDB,
|
onUpdate: this.onlyOnCouchDB,
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "minimumIntervalOfReadChunksOnline", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("minimumIntervalOfReadChunksOnline", {
|
||||||
clampMin: 10,
|
clampMin: 10,
|
||||||
onUpdate: this.onlyOnCouchDB,
|
onUpdate: this.onlyOnCouchDB,
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
renderObsidianSetting(paneEl, "autoAcceptCompatibleTweak").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("autoAcceptCompatibleTweak");
|
||||||
// new Setting(paneEl)
|
// new Setting(paneEl)
|
||||||
// .setClass("wizardHidden")
|
// .setClass("wizardHidden")
|
||||||
// .autoWireToggle("sendChunksBulk", { onUpdate: onlyOnCouchDB })
|
// .autoWireToggle("sendChunksBulk", { onUpdate: onlyOnCouchDB })
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG, eventHub } from "@/common/events.ts";
|
import { EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG, eventHub } from "@/common/events.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
import { enableOnly, visibleOnly } from "./SettingPane.ts";
|
import { enableOnly, visibleOnly } from "./SettingPane.ts";
|
||||||
export function paneCustomisationSync(
|
export function paneCustomisationSync(
|
||||||
@@ -36,27 +35,27 @@ export function paneCustomisationSync(
|
|||||||
visibleOnly(() => this.isConfiguredAs("usePluginSync", true))
|
visibleOnly(() => this.isConfiguredAs("usePluginSync", true))
|
||||||
);
|
);
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "deviceAndVaultName", {
|
new Setting(paneEl).autoWireText("deviceAndVaultName", {
|
||||||
placeHolder: "desktop",
|
placeHolder: "desktop",
|
||||||
onUpdate: enableOnlyOnPluginSyncIsNotEnabled,
|
onUpdate: enableOnlyOnPluginSyncIsNotEnabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "usePluginSyncV2");
|
new Setting(paneEl).autoWireToggle("usePluginSyncV2");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "usePluginSync", {
|
new Setting(paneEl).autoWireToggle("usePluginSync", {
|
||||||
onUpdate: enableOnly(() => !this.isConfiguredAs("deviceAndVaultName", "")),
|
onUpdate: enableOnly(() => !this.isConfiguredAs("deviceAndVaultName", "")),
|
||||||
});
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "autoSweepPlugins", {
|
new Setting(paneEl).autoWireToggle("autoSweepPlugins", {
|
||||||
onUpdate: visibleOnlyOnPluginSyncEnabled,
|
onUpdate: visibleOnlyOnPluginSyncEnabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "autoSweepPluginsPeriodic", {
|
new Setting(paneEl).autoWireToggle("autoSweepPluginsPeriodic", {
|
||||||
onUpdate: visibleOnly(
|
onUpdate: visibleOnly(
|
||||||
() => this.isConfiguredAs("usePluginSync", true) && this.isConfiguredAs("autoSweepPlugins", true)
|
() => this.isConfiguredAs("usePluginSync", true) && this.isConfiguredAs("autoSweepPlugins", true)
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "notifyPluginOrSettingUpdated", {
|
new Setting(paneEl).autoWireToggle("notifyPluginOrSettingUpdated", {
|
||||||
onUpdate: visibleOnlyOnPluginSyncEnabled,
|
onUpdate: visibleOnlyOnPluginSyncEnabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { $msg, $t } from "@lib/common/i18n.ts";
|
import { $msg, $t } from "@lib/common/i18n.ts";
|
||||||
import { SUPPORTED_I18N_LANGS, type I18N_LANGS } from "@lib/common/rosetta.ts";
|
import { SUPPORTED_I18N_LANGS, type I18N_LANGS } from "@lib/common/rosetta.ts";
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
import { visibleOnly } from "./SettingPane.ts";
|
import { visibleOnly } from "./SettingPane.ts";
|
||||||
@@ -17,20 +16,20 @@ export function paneGeneral(
|
|||||||
// ["", $msg("obsidianLiveSyncSettingTab.defaultLanguage")],
|
// ["", $msg("obsidianLiveSyncSettingTab.defaultLanguage")],
|
||||||
...SUPPORTED_I18N_LANGS.map((e) => [e, $t(`lang-${e}`)]),
|
...SUPPORTED_I18N_LANGS.map((e) => [e, $t(`lang-${e}`)]),
|
||||||
]) as Record<I18N_LANGS, string>;
|
]) as Record<I18N_LANGS, string>;
|
||||||
renderObsidianSetting(paneEl, "displayLanguage", {
|
new Setting(paneEl).autoWireDropDown("displayLanguage", {
|
||||||
options: languages,
|
options: languages,
|
||||||
});
|
});
|
||||||
this.addOnSaved("displayLanguage", () => this.display());
|
this.addOnSaved("displayLanguage", () => this.display());
|
||||||
renderObsidianSetting(paneEl, "showStatusOnEditor");
|
new Setting(paneEl).autoWireToggle("showStatusOnEditor");
|
||||||
this.addOnSaved("showStatusOnEditor", () => {
|
this.addOnSaved("showStatusOnEditor", () => {
|
||||||
eventHub.emitEvent(EVENT_ON_UNRESOLVED_ERROR);
|
eventHub.emitEvent(EVENT_ON_UNRESOLVED_ERROR);
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "showOnlyIconsOnEditor", {
|
new Setting(paneEl).autoWireToggle("showOnlyIconsOnEditor", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("showStatusOnEditor", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("showStatusOnEditor", true)),
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "showStatusOnStatusbar");
|
new Setting(paneEl).autoWireToggle("showStatusOnStatusbar");
|
||||||
renderObsidianSetting(paneEl, "hideFileWarningNotice");
|
new Setting(paneEl).autoWireToggle("hideFileWarningNotice");
|
||||||
renderObsidianSetting(paneEl, "networkWarningStyle", {
|
new Setting(paneEl).autoWireDropDown("networkWarningStyle", {
|
||||||
options: {
|
options: {
|
||||||
[NetworkWarningStyles.BANNER]: "Show full banner",
|
[NetworkWarningStyles.BANNER]: "Show full banner",
|
||||||
[NetworkWarningStyles.ICON]: "Show icon only",
|
[NetworkWarningStyles.ICON]: "Show icon only",
|
||||||
@@ -44,9 +43,9 @@ export function paneGeneral(
|
|||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleLogging")).then((paneEl) => {
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleLogging")).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "lessInformationInLog");
|
new Setting(paneEl).autoWireToggle("lessInformationInLog");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "showVerboseLog", {
|
new Setting(paneEl).autoWireToggle("showVerboseLog", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("lessInformationInLog", false)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("lessInformationInLog", false)),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import { ICHeader, ICXHeader, PSCHeader } from "@/common/types.ts";
|
|||||||
import { HiddenFileSync } from "@/features/HiddenFileSync/CmdHiddenFileSync.ts";
|
import { HiddenFileSync } from "@/features/HiddenFileSync/CmdHiddenFileSync.ts";
|
||||||
import { EVENT_REQUEST_SHOW_HISTORY } from "@/common/obsidianEvents.ts";
|
import { EVENT_REQUEST_SHOW_HISTORY } from "@/common/obsidianEvents.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
import { isNotFoundError } from "@lib/common/utils.doc.ts";
|
import { isNotFoundError } from "@lib/common/utils.doc.ts";
|
||||||
export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
||||||
@@ -88,14 +87,14 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
|
|||||||
eventHub.emitEvent(EVENT_REQUEST_CHECK_REMOTE_SIZE);
|
eventHub.emitEvent(EVENT_REQUEST_CHECK_REMOTE_SIZE);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
renderObsidianSetting(paneEl, "writeLogToTheFile");
|
new Setting(paneEl).autoWireToggle("writeLogToTheFile");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Scram Switches").then((paneEl) => {
|
void addPanel(paneEl, "Scram Switches").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "suspendFileWatching");
|
new Setting(paneEl).autoWireToggle("suspendFileWatching");
|
||||||
this.addOnSaved("suspendFileWatching", () => this.services.appLifecycle.askRestart());
|
this.addOnSaved("suspendFileWatching", () => this.services.appLifecycle.askRestart());
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "suspendParseReplicationResult");
|
new Setting(paneEl).autoWireToggle("suspendParseReplicationResult");
|
||||||
this.addOnSaved("suspendParseReplicationResult", () => this.services.appLifecycle.askRestart());
|
this.addOnSaved("suspendParseReplicationResult", () => this.services.appLifecycle.askRestart());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
} from "@lib/common/types.ts";
|
} from "@lib/common/types.ts";
|
||||||
import { Logger } from "@lib/common/logger.ts";
|
import { Logger } from "@lib/common/logger.ts";
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { addObsidianApplyButton, renderObsidianApplyButton, renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
import { visibleOnly } from "./SettingPane.ts";
|
import { visibleOnly } from "./SettingPane.ts";
|
||||||
@@ -17,17 +16,17 @@ import { migrateDatabases } from "./settingUtils.ts";
|
|||||||
|
|
||||||
export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
||||||
void addPanel(paneEl, "Compatibility (Metadata)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Metadata)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "deleteMetadataOfDeletedFiles").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("deleteMetadataOfDeletedFiles");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "automaticallyDeleteMetadataOfDeletedFiles", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("automaticallyDeleteMetadataOfDeletedFiles", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("deleteMetadataOfDeletedFiles", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("deleteMetadataOfDeletedFiles", true)),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Compatibility (Conflict Behaviour)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Conflict Behaviour)").then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
renderObsidianSetting(paneEl, "disableMarkdownAutoMerge").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("disableMarkdownAutoMerge");
|
||||||
renderObsidianSetting(paneEl, "writeDocumentsIfConflicted").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("writeDocumentsIfConflicted");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Compatibility (Database structure)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Database structure)").then((paneEl) => {
|
||||||
@@ -114,18 +113,18 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderObsidianSetting(paneEl, "handleFilenameCaseSensitive", { holdValue: true }).setClass("wizardHidden");
|
new Setting(paneEl).autoWireToggle("handleFilenameCaseSensitive", { holdValue: true }).setClass("wizardHidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Compatibility (Internal API Usage)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Internal API Usage)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "watchInternalFileChanges", { invert: true });
|
new Setting(paneEl).autoWireToggle("watchInternalFileChanges", { invert: true });
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Compatibility (Remote Database)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Remote Database)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "E2EEAlgorithm", {
|
new Setting(paneEl).autoWireDropDown("E2EEAlgorithm", {
|
||||||
options: E2EEAlgorithmNames,
|
options: E2EEAlgorithmNames,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "useDynamicIterationCount", {
|
new Setting(paneEl).autoWireToggle("useDynamicIterationCount", {
|
||||||
holdValue: true,
|
holdValue: true,
|
||||||
onUpdate: visibleOnly(
|
onUpdate: visibleOnly(
|
||||||
() =>
|
() =>
|
||||||
@@ -135,15 +134,16 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Edge case addressing (Database)").then((paneEl) => {
|
void addPanel(paneEl, "Edge case addressing (Database)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "additionalSuffixOfDatabaseName");
|
new Setting(paneEl)
|
||||||
renderObsidianApplyButton(paneEl, "database-suffix");
|
.autoWireText("additionalSuffixOfDatabaseName", { holdValue: true })
|
||||||
|
.addApplyButton(["additionalSuffixOfDatabaseName"]);
|
||||||
|
|
||||||
this.addOnSaved("additionalSuffixOfDatabaseName", async (key) => {
|
this.addOnSaved("additionalSuffixOfDatabaseName", async (key) => {
|
||||||
Logger("Suffix has been changed. Reopening database...", LOG_LEVEL_NOTICE);
|
Logger("Suffix has been changed. Reopening database...", LOG_LEVEL_NOTICE);
|
||||||
await this.services.databaseEvents.initialiseDatabase();
|
await this.services.databaseEvents.initialiseDatabase();
|
||||||
});
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "hashAlg", {
|
new Setting(paneEl).autoWireDropDown("hashAlg", {
|
||||||
options: {
|
options: {
|
||||||
"": "Old Algorithm",
|
"": "Old Algorithm",
|
||||||
xxhash32: "xxhash32 (Fast but less collision resistance)",
|
xxhash32: "xxhash32 (Fast but less collision resistance)",
|
||||||
@@ -157,15 +157,15 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Edge case addressing (Behaviour)").then((paneEl) => {
|
void addPanel(paneEl, "Edge case addressing (Behaviour)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "doNotSuspendOnFetching");
|
new Setting(paneEl).autoWireToggle("doNotSuspendOnFetching");
|
||||||
renderObsidianSetting(paneEl, "doNotDeleteFolder").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("doNotDeleteFolder");
|
||||||
renderObsidianSetting(paneEl, "processSizeMismatchedFiles");
|
new Setting(paneEl).autoWireToggle("processSizeMismatchedFiles");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, "Edge case addressing (Processing)").then((paneEl) => {
|
void addPanel(paneEl, "Edge case addressing (Processing)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "disableWorkerForGeneratingChunks");
|
new Setting(paneEl).autoWireToggle("disableWorkerForGeneratingChunks");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "processSmallFilesInUIThread", {
|
new Setting(paneEl).autoWireToggle("processSmallFilesInUIThread", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("disableWorkerForGeneratingChunks", false)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("disableWorkerForGeneratingChunks", false)),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -173,11 +173,11 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
// new Setting(paneEl).autoWireToggle("useRequestAPI");
|
// new Setting(paneEl).autoWireToggle("useRequestAPI");
|
||||||
// });
|
// });
|
||||||
void addPanel(paneEl, "Compatibility (Trouble addressed)").then((paneEl) => {
|
void addPanel(paneEl, "Compatibility (Trouble addressed)").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "disableCheckingConfigMismatch");
|
new Setting(paneEl).autoWireToggle("disableCheckingConfigMismatch");
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Remediation").then((paneEl) => {
|
void addPanel(paneEl, "Remediation").then((paneEl) => {
|
||||||
let dateEl: HTMLSpanElement;
|
let dateEl: HTMLSpanElement;
|
||||||
const remediationSetting = new Setting(paneEl)
|
new Setting(paneEl)
|
||||||
.addText((text) => {
|
.addText((text) => {
|
||||||
const updateDateText = () => {
|
const updateDateText = () => {
|
||||||
if (this.editingSettings.maxMTimeForReflectEvents == 0) {
|
if (this.editingSettings.maxMTimeForReflectEvents == 0) {
|
||||||
@@ -212,8 +212,8 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
updateDateText();
|
updateDateText();
|
||||||
return text;
|
return text;
|
||||||
})
|
})
|
||||||
.setAuto("maxMTimeForReflectEvents");
|
.setAuto("maxMTimeForReflectEvents")
|
||||||
addObsidianApplyButton(remediationSetting, "remediation-reflect-events");
|
.addApplyButton(["maxMTimeForReflectEvents"]);
|
||||||
|
|
||||||
this.addOnSaved("maxMTimeForReflectEvents", async (key) => {
|
this.addOnSaved("maxMTimeForReflectEvents", async (key) => {
|
||||||
const buttons = ["Restart Now", "Later"] as const;
|
const buttons = ["Restart Now", "Later"] as const;
|
||||||
@@ -240,6 +240,6 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
|
|||||||
// .setClass("wizardHidden");
|
// .setClass("wizardHidden");
|
||||||
// new Setting(paneEl).autoWireNumeric("maxAgeInEden", { onUpdate: onlyUsingEden }).setClass("wizardHidden");
|
// new Setting(paneEl).autoWireNumeric("maxAgeInEden", { onUpdate: onlyUsingEden }).setClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "enableCompression").setClass("wizardHidden");
|
new Setting(paneEl).autoWireToggle("enableCompression").setClass("wizardHidden");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { type ConfigPassphraseStore } from "@lib/common/types.ts";
|
import { type ConfigPassphraseStore } from "@lib/common/types.ts";
|
||||||
import { renderObsidianApplyButton, renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
|
|
||||||
@@ -21,14 +21,14 @@ export function panePowerUsers(
|
|||||||
this.onlyOnCouchDB
|
this.onlyOnCouchDB
|
||||||
).addClass("wizardHidden");
|
).addClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "batch_size", { clampMin: 2, onUpdate: this.onlyOnCouchDB }).setClass(
|
new Setting(paneEl)
|
||||||
"wizardHidden"
|
.setClass("wizardHidden")
|
||||||
);
|
.autoWireNumeric("batch_size", { clampMin: 2, onUpdate: this.onlyOnCouchDB });
|
||||||
renderObsidianSetting(paneEl, "batches_limit", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("batches_limit", {
|
||||||
clampMin: 2,
|
clampMin: 2,
|
||||||
onUpdate: this.onlyOnCouchDB,
|
onUpdate: this.onlyOnCouchDB,
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
renderObsidianSetting(paneEl, "useTimeouts", { onUpdate: this.onlyOnCouchDB }).setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("useTimeouts", { onUpdate: this.onlyOnCouchDB });
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Configuration Encryption").then((paneEl) => {
|
void addPanel(paneEl, "Configuration Encryption").then((paneEl) => {
|
||||||
const passphrase_options: Record<ConfigPassphraseStore, string> = {
|
const passphrase_options: Record<ConfigPassphraseStore, string> = {
|
||||||
@@ -37,18 +37,23 @@ export function panePowerUsers(
|
|||||||
ASK_AT_LAUNCH: "Ask an passphrase at every launch",
|
ASK_AT_LAUNCH: "Ask an passphrase at every launch",
|
||||||
};
|
};
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "configPassphraseStore", {
|
new Setting(paneEl)
|
||||||
|
.setName("Encrypting sensitive configuration items")
|
||||||
|
.autoWireDropDown("configPassphraseStore", {
|
||||||
options: passphrase_options,
|
options: passphrase_options,
|
||||||
}).setClass("wizardHidden");
|
holdValue: true,
|
||||||
|
})
|
||||||
|
.setClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "configPassphrase")
|
new Setting(paneEl)
|
||||||
|
.autoWireText("configPassphrase", { isPassword: true, holdValue: true })
|
||||||
.setClass("wizardHidden")
|
.setClass("wizardHidden")
|
||||||
.addOnUpdate(() => ({
|
.addOnUpdate(() => ({
|
||||||
disabled: !this.isConfiguredAs("configPassphraseStore", "LOCALSTORAGE"),
|
disabled: !this.isConfiguredAs("configPassphraseStore", "LOCALSTORAGE"),
|
||||||
}));
|
}));
|
||||||
renderObsidianApplyButton(paneEl, "configuration-encryption").setClass("wizardHidden");
|
new Setting(paneEl).addApplyButton(["configPassphrase", "configPassphraseStore"]).setClass("wizardHidden");
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Developer").then((paneEl) => {
|
void addPanel(paneEl, "Developer").then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "enableDebugTools").setClass("wizardHidden");
|
new Setting(paneEl).autoWireToggle("enableDebugTools").setClass("wizardHidden");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
import { Menu, type ButtonComponent } from "@/deps.ts";
|
import { Menu, type ButtonComponent } from "@/deps.ts";
|
||||||
import { $msg } from "@lib/common/i18n.ts";
|
import { $msg } from "@lib/common/i18n.ts";
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
// import { visibleOnly } from "./SettingPane.ts";
|
// import { visibleOnly } from "./SettingPane.ts";
|
||||||
@@ -675,7 +674,7 @@ export function paneRemoteConfig(
|
|||||||
|
|
||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}).then((paneEl) => {
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
renderObsidianSetting(paneEl, "notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden");
|
new Setting(paneEl).autoWireNumeric("notifyThresholdOfRemoteStorageSize", {}).setClass("wizardHidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
// new Setting(paneEl).setClass("wizardOnly").addButton((button) =>
|
// new Setting(paneEl).setClass("wizardOnly").addButton((button) =>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import MultipleRegExpControl from "./MultipleRegExpControl.svelte";
|
|||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { mount } from "svelte";
|
import { mount } from "svelte";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
import { visibleOnly } from "./SettingPane.ts";
|
import { visibleOnly } from "./SettingPane.ts";
|
||||||
export function paneSelector(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
export function paneSelector(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, { addPanel }: PageFunctions): void {
|
||||||
@@ -47,12 +46,12 @@ export function paneSelector(this: ObsidianLiveSyncSettingTab, paneEl: HTMLEleme
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "syncMaxSizeInMB", { clampMin: 0 }).setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("syncMaxSizeInMB", { clampMin: 0 });
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "useIgnoreFiles").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("useIgnoreFiles");
|
||||||
renderObsidianSetting(paneEl, "ignoreFiles", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireTextArea("ignoreFiles", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("useIgnoreFiles", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("useIgnoreFiles", true)),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
});
|
});
|
||||||
void addPanel(paneEl, "Hidden Files", undefined, undefined, LEVEL_ADVANCED).then((paneEl) => {
|
void addPanel(paneEl, "Hidden Files", undefined, undefined, LEVEL_ADVANCED).then((paneEl) => {
|
||||||
const targetPatternSetting = new Setting(paneEl)
|
const targetPatternSetting = new Setting(paneEl)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { DEFAULT_SETTINGS } from "@lib/common/types.ts";
|
|||||||
import { request } from "@/deps.ts";
|
import { request } from "@/deps.ts";
|
||||||
import { SetupManager, UserMode } from "@/modules/features/SetupManager.ts";
|
import { SetupManager, UserMode } from "@/modules/features/SetupManager.ts";
|
||||||
import { LiveSyncError } from "@lib/common/LSError.ts";
|
import { LiveSyncError } from "@lib/common/LSError.ts";
|
||||||
import { renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
export function paneSetup(
|
export function paneSetup(
|
||||||
this: ObsidianLiveSyncSettingTab,
|
this: ObsidianLiveSyncSettingTab,
|
||||||
paneEl: HTMLElement,
|
paneEl: HTMLElement,
|
||||||
@@ -108,9 +107,10 @@ export function paneSetup(
|
|||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleExtraFeatures")).then((paneEl) => {
|
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleExtraFeatures")).then((paneEl) => {
|
||||||
renderObsidianSetting(paneEl, "useAdvancedMode");
|
new Setting(paneEl).autoWireToggle("useAdvancedMode");
|
||||||
renderObsidianSetting(paneEl, "usePowerUserMode");
|
|
||||||
renderObsidianSetting(paneEl, "useEdgeCaseMode");
|
new Setting(paneEl).autoWireToggle("usePowerUserMode");
|
||||||
|
new Setting(paneEl).autoWireToggle("useEdgeCaseMode");
|
||||||
|
|
||||||
this.addOnSaved("useAdvancedMode", () => this.display());
|
this.addOnSaved("useAdvancedMode", () => this.display());
|
||||||
this.addOnSaved("usePowerUserMode", () => this.display());
|
this.addOnSaved("usePowerUserMode", () => this.display());
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { type ObsidianLiveSyncSettings, LOG_LEVEL_NOTICE, REMOTE_COUCHDB, LEVEL_
|
|||||||
import { Logger } from "@lib/common/logger.ts";
|
import { Logger } from "@lib/common/logger.ts";
|
||||||
import { $msg } from "@lib/common/i18n.ts";
|
import { $msg } from "@lib/common/i18n.ts";
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import { renderObsidianApplyButton, renderObsidianSetting } from "./ObsidianSettingRenderer.ts";
|
|
||||||
import { EVENT_REQUEST_COPY_SETUP_URI, eventHub } from "@/common/events.ts";
|
import { EVENT_REQUEST_COPY_SETUP_URI, eventHub } from "@/common/events.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import type { PageFunctions } from "./SettingPane.ts";
|
import type { PageFunctions } from "./SettingPane.ts";
|
||||||
@@ -32,10 +31,12 @@ export function paneSyncSettings(
|
|||||||
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
DISABLE: $msg("obsidianLiveSyncSettingTab.optionDisableAllAutomatic"),
|
||||||
};
|
};
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "preset", {
|
new Setting(paneEl)
|
||||||
|
.autoWireDropDown("preset", {
|
||||||
options: options,
|
options: options,
|
||||||
holdValue: true,
|
holdValue: true,
|
||||||
}).addButton((button) => {
|
})
|
||||||
|
.addButton((button) => {
|
||||||
button.setButtonText($msg("obsidianLiveSyncSettingTab.btnApply"));
|
button.setButtonText($msg("obsidianLiveSyncSettingTab.btnApply"));
|
||||||
button.onClick(async () => {
|
button.onClick(async () => {
|
||||||
// await this.saveSettings(["preset"]);
|
// await this.saveSettings(["preset"]);
|
||||||
@@ -135,7 +136,7 @@ export function paneSyncSettings(
|
|||||||
const onlyOnNonLiveSync = visibleOnly(() => !this.isConfiguredAs("syncMode", "LIVESYNC"));
|
const onlyOnNonLiveSync = visibleOnly(() => !this.isConfiguredAs("syncMode", "LIVESYNC"));
|
||||||
const onlyOnPeriodic = visibleOnly(() => this.isConfiguredAs("syncMode", "PERIODIC"));
|
const onlyOnPeriodic = visibleOnly(() => this.isConfiguredAs("syncMode", "PERIODIC"));
|
||||||
|
|
||||||
const optionsSyncMode: Record<string, string> =
|
const optionsSyncMode =
|
||||||
this.editingSettings.remoteType == REMOTE_COUCHDB
|
this.editingSettings.remoteType == REMOTE_COUCHDB
|
||||||
? {
|
? {
|
||||||
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
ONEVENTS: $msg("obsidianLiveSyncSettingTab.optionOnEvents"),
|
||||||
@@ -147,9 +148,12 @@ export function paneSyncSettings(
|
|||||||
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
PERIODIC: $msg("obsidianLiveSyncSettingTab.optionPeriodicAndEvents"),
|
||||||
};
|
};
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "syncMode", {
|
new Setting(paneEl)
|
||||||
|
.autoWireDropDown("syncMode", {
|
||||||
|
//@ts-ignore
|
||||||
options: optionsSyncMode,
|
options: optionsSyncMode,
|
||||||
}).setClass("wizardHidden");
|
})
|
||||||
|
.setClass("wizardHidden");
|
||||||
this.addOnSaved("syncMode", async (value) => {
|
this.addOnSaved("syncMode", async (value) => {
|
||||||
this.editingSettings.liveSync = false;
|
this.editingSettings.liveSync = false;
|
||||||
this.editingSettings.periodicReplication = false;
|
this.editingSettings.periodicReplication = false;
|
||||||
@@ -163,28 +167,32 @@ export function paneSyncSettings(
|
|||||||
await this.services.control.applySettings();
|
await this.services.control.applySettings();
|
||||||
});
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "periodicReplicationInterval", {
|
new Setting(paneEl)
|
||||||
|
.autoWireNumeric("periodicReplicationInterval", {
|
||||||
clampMax: 5000,
|
clampMax: 5000,
|
||||||
onUpdate: onlyOnPeriodic,
|
onUpdate: onlyOnPeriodic,
|
||||||
}).setClass("wizardHidden");
|
})
|
||||||
|
.setClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "syncMinimumInterval", {
|
new Setting(paneEl).autoWireNumeric("syncMinimumInterval", {
|
||||||
onUpdate: onlyOnNonLiveSync,
|
onUpdate: onlyOnNonLiveSync,
|
||||||
});
|
});
|
||||||
renderObsidianSetting(paneEl, "syncOnSave", { onUpdate: onlyOnNonLiveSync }).setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("syncOnSave", { onUpdate: onlyOnNonLiveSync });
|
||||||
renderObsidianSetting(paneEl, "syncOnEditorSave", { onUpdate: onlyOnNonLiveSync }).setClass("wizardHidden");
|
new Setting(paneEl)
|
||||||
renderObsidianSetting(paneEl, "syncOnFileOpen", { onUpdate: onlyOnNonLiveSync }).setClass("wizardHidden");
|
.setClass("wizardHidden")
|
||||||
renderObsidianSetting(paneEl, "syncOnStart", { onUpdate: onlyOnNonLiveSync }).setClass("wizardHidden");
|
.autoWireToggle("syncOnEditorSave", { onUpdate: onlyOnNonLiveSync });
|
||||||
renderObsidianSetting(paneEl, "syncAfterMerge", { onUpdate: onlyOnNonLiveSync }).setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("syncOnFileOpen", { onUpdate: onlyOnNonLiveSync });
|
||||||
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("syncOnStart", { onUpdate: onlyOnNonLiveSync });
|
||||||
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("syncAfterMerge", { onUpdate: onlyOnNonLiveSync });
|
||||||
// Desktop app only, and only for the sync modes that keep a background replication channel
|
// Desktop app only, and only for the sync modes that keep a background replication channel
|
||||||
// (LiveSync and Periodic). Ignored on mobile, where suspending preserves battery. The
|
// (LiveSync and Periodic). Ignored on mobile, where suspending preserves battery. The
|
||||||
// visibility predicate mirrors the runtime guard in ModuleObsidianEvents.
|
// visibility predicate mirrors the runtime guard in ModuleObsidianEvents.
|
||||||
if (!this.services.API.isMobile()) {
|
if (!this.services.API.isMobile()) {
|
||||||
renderObsidianSetting(paneEl, "keepReplicationActiveInBackground", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("keepReplicationActiveInBackground", {
|
||||||
onUpdate: visibleOnly(
|
onUpdate: visibleOnly(
|
||||||
() => this.isConfiguredAs("syncMode", "LIVESYNC") || this.isConfiguredAs("syncMode", "PERIODIC")
|
() => this.isConfiguredAs("syncMode", "LIVESYNC") || this.isConfiguredAs("syncMode", "PERIODIC")
|
||||||
),
|
),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -195,15 +203,15 @@ export function paneSyncSettings(
|
|||||||
visibleOnly(() => !this.isConfiguredAs("syncMode", "LIVESYNC"))
|
visibleOnly(() => !this.isConfiguredAs("syncMode", "LIVESYNC"))
|
||||||
).then((paneEl) => {
|
).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
renderObsidianSetting(paneEl, "batchSave").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("batchSave");
|
||||||
renderObsidianSetting(paneEl, "batchSaveMinimumDelay", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("batchSaveMinimumDelay", {
|
||||||
acceptZero: true,
|
acceptZero: true,
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true)),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
renderObsidianSetting(paneEl, "batchSaveMaximumDelay", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("batchSaveMaximumDelay", {
|
||||||
acceptZero: true,
|
acceptZero: true,
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true)),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(
|
void addPanel(
|
||||||
@@ -214,9 +222,9 @@ export function paneSyncSettings(
|
|||||||
LEVEL_ADVANCED
|
LEVEL_ADVANCED
|
||||||
).then((paneEl) => {
|
).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
renderObsidianSetting(paneEl, "trashInsteadDelete").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("trashInsteadDelete");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "doNotDeleteFolder").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("doNotDeleteFolder");
|
||||||
});
|
});
|
||||||
void addPanel(
|
void addPanel(
|
||||||
paneEl,
|
paneEl,
|
||||||
@@ -227,11 +235,11 @@ export function paneSyncSettings(
|
|||||||
).then((paneEl) => {
|
).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "resolveConflictsByNewerFile").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("resolveConflictsByNewerFile");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "checkConflictOnlyOnOpen").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("checkConflictOnlyOnOpen");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "showMergeDialogOnlyOnActive").setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("showMergeDialogOnlyOnActive");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(
|
void addPanel(
|
||||||
@@ -242,12 +250,11 @@ export function paneSyncSettings(
|
|||||||
LEVEL_ADVANCED
|
LEVEL_ADVANCED
|
||||||
).then((paneEl) => {
|
).then((paneEl) => {
|
||||||
paneEl.addClass("wizardHidden");
|
paneEl.addClass("wizardHidden");
|
||||||
renderObsidianSetting(paneEl, "settingSyncFile");
|
new Setting(paneEl).autoWireText("settingSyncFile", { holdValue: true }).addApplyButton(["settingSyncFile"]);
|
||||||
renderObsidianApplyButton(paneEl, "setting-sync-file");
|
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "writeCredentialsForSettingSync");
|
new Setting(paneEl).autoWireToggle("writeCredentialsForSettingSync");
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "notifyAllSettingSyncFile");
|
new Setting(paneEl).autoWireToggle("notifyAllSettingSyncFile");
|
||||||
});
|
});
|
||||||
|
|
||||||
void addPanel(
|
void addPanel(
|
||||||
@@ -306,14 +313,14 @@ export function paneSyncSettings(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "suppressNotifyHiddenFilesChange", {}).setClass("wizardHidden");
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("suppressNotifyHiddenFilesChange", {});
|
||||||
renderObsidianSetting(paneEl, "syncInternalFilesBeforeReplication", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireToggle("syncInternalFilesBeforeReplication", {
|
||||||
onUpdate: visibleOnly(() => this.isConfiguredAs("watchInternalFileChanges", true)),
|
onUpdate: visibleOnly(() => this.isConfiguredAs("watchInternalFileChanges", true)),
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
|
|
||||||
renderObsidianSetting(paneEl, "syncInternalFilesInterval", {
|
new Setting(paneEl).setClass("wizardHidden").autoWireNumeric("syncInternalFilesInterval", {
|
||||||
clampMin: 10,
|
clampMin: 10,
|
||||||
acceptZero: true,
|
acceptZero: true,
|
||||||
}).setClass("wizardHidden");
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import { $msg } from "@lib/common/i18n";
|
import { $msg } from "@lib/common/i18n";
|
||||||
import {
|
import { LEVEL_ADVANCED, LEVEL_EDGE_CASE, LEVEL_POWER_USER, type ConfigLevel } from "@lib/common/types";
|
||||||
LEVEL_ADVANCED,
|
|
||||||
LEVEL_EDGE_CASE,
|
|
||||||
LEVEL_POWER_USER,
|
|
||||||
type ConfigLevel,
|
|
||||||
type SettingDefinition,
|
|
||||||
} from "@lib/common/types";
|
|
||||||
import type { AllSettingItemKey, AllSettings } from "./settingConstants";
|
import type { AllSettingItemKey, AllSettings } from "./settingConstants";
|
||||||
|
|
||||||
export const combineOnUpdate = (func1: OnUpdateFunc, func2: OnUpdateFunc): OnUpdateFunc => {
|
export const combineOnUpdate = (func1: OnUpdateFunc, func2: OnUpdateFunc): OnUpdateFunc => {
|
||||||
@@ -83,7 +77,6 @@ export type AutoWireOption = {
|
|||||||
invert?: boolean;
|
invert?: boolean;
|
||||||
onUpdate?: OnUpdateFunc;
|
onUpdate?: OnUpdateFunc;
|
||||||
obsolete?: boolean;
|
obsolete?: boolean;
|
||||||
settingDefinition?: SettingDefinition<AllSettingItemKey>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function findAttrFromParent(el: HTMLElement, attr: string): string {
|
export function findAttrFromParent(el: HTMLElement, attr: string): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user