From 6e00b8195aa696e196a6a52e18badc455c65570c Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Fri, 17 Jul 2026 14:55:30 +0000 Subject: [PATCH] fix: remove ineffective trash setting toggle --- docs/settings.md | 4 +- package.json | 1 + .../SettingDialogue/PaneSyncSettings.ts | 2 - test/e2e-obsidian/README.md | 6 +- test/e2e-obsidian/scripts/local-suite.ts | 1 + test/e2e-obsidian/scripts/settings-ui.ts | 93 +++++++++++++++++++ updates.md | 4 + 7 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 test/e2e-obsidian/scripts/settings-ui.ts diff --git a/docs/settings.md b/docs/settings.md index 995aed28..4b2108ff 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -514,10 +514,10 @@ Saving will be performed forcefully after this number of seconds. ### 4. Deletion Propagation (Advanced) -#### Use the trash bin +#### Legacy trash setting Setting key: trashInsteadDelete -Move remotely deleted files to the trash, instead of deleting. On Obsidian v1.7.2 or newer, file deletion respects the user's deletion preferences (by utilising the `FileManager.trashFile` API), regardless of this setting. +This key remains accepted for settings imports, Setup URIs, and compatibility with earlier versions, but it is no longer shown in the settings interface. Remote file deletion follows the user's Obsidian deletion preferences through the `FileManager.trashFile` API, regardless of this legacy value. #### Keep empty folder diff --git a/package.json b/package.json index 64ce9893..cb216d00 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "test:e2e:obsidian:debug-ui": "tsx test/e2e-obsidian/scripts/debug-ui.ts", "test:e2e:obsidian:smoke": "tsx test/e2e-obsidian/scripts/smoke.ts", "test:e2e:obsidian:dialog-mounts": "tsx test/e2e-obsidian/scripts/dialog-mounts.ts", + "test:e2e:obsidian:settings-ui": "tsx test/e2e-obsidian/scripts/settings-ui.ts", "test:e2e:obsidian:vault-reflection": "tsx test/e2e-obsidian/scripts/vault-reflection.ts", "test:e2e:obsidian:couchdb-upload": "tsx test/e2e-obsidian/scripts/couchdb-upload.ts", "test:e2e:obsidian:cli-to-obsidian-sync": "tsx test/e2e-obsidian/scripts/cli-to-obsidian-sync.ts", diff --git a/src/modules/features/SettingDialogue/PaneSyncSettings.ts b/src/modules/features/SettingDialogue/PaneSyncSettings.ts index 6599d0ce..6a2c03f9 100644 --- a/src/modules/features/SettingDialogue/PaneSyncSettings.ts +++ b/src/modules/features/SettingDialogue/PaneSyncSettings.ts @@ -222,8 +222,6 @@ export function paneSyncSettings( LEVEL_ADVANCED ).then((paneEl) => { paneEl.addClass("wizardHidden"); - new Setting(paneEl).setClass("wizardHidden").autoWireToggle("trashInsteadDelete"); - new Setting(paneEl).setClass("wizardHidden").autoWireToggle("doNotDeleteFolder"); }); void addPanel( diff --git a/test/e2e-obsidian/README.md b/test/e2e-obsidian/README.md index b02965da..53d6ef81 100644 --- a/test/e2e-obsidian/README.md +++ b/test/e2e-obsidian/README.md @@ -56,6 +56,7 @@ npm run test:e2e:obsidian:discover npm run test:e2e:obsidian:cli-help -- vaults verbose npm run test:e2e:obsidian:smoke npm run test:e2e:obsidian:dialog-mounts +npm run test:e2e:obsidian:settings-ui npm run test:e2e:obsidian:vault-reflection npm run test:e2e:obsidian:couchdb-upload npm run test:e2e:obsidian:cli-to-obsidian-sync @@ -75,9 +76,11 @@ npm run test:e2e:obsidian:local-suite:services `test:e2e:obsidian:dialog-mounts` starts a temporary real Obsidian session and exercises two representative Svelte dialogue routes: remote server selection through `SetupManager`, and Setup URI entry through the registered command. The session pre-seeds a configured, inactive plug-in state so that onboarding and migration prompts do not interfere with the dialogues under test. It requires each dialogue title and its principal controls to be visible, captures desktop and mobile screenshots, closes them through their normal user controls, and verifies that the remote-selection promise settles without an error. This covers the host, context, component, and result boundaries moved during the Commonlib package extraction without applying settings or contacting a remote service. +`test:e2e:obsidian:settings-ui` opens Self-hosted LiveSync's settings in a temporary real Obsidian session and selects the Synchronisation Settings pane through its user-facing control. It verifies that the deletion panel still exposes the effective 'Keep empty folder' setting without presenting the legacy `trashInsteadDelete` control, whose value no longer changes Obsidian deletion behaviour. + The mobile pass uses Obsidian's `app.emulateMobile(true)`, a 390 by 844 CSS-pixel viewport, and explicit iPhone-style safe-area insets of 47 pixels at the top and 34 pixels at the bottom. The public `@vrtmrz/obsidian-test-session` layout assertions require each modal to remain within the viewport and safe area without horizontal overflow. They also require the Obsidian Close control to remain within the safe area and provide at least a 44 by 44 CSS-pixel touch target. The runner clicks that control to verify actionability, then completes the explicit cancellation path. These simulated checks cover deterministic layout and interaction boundaries; they do not claim to reproduce a native operating-system overlay. -`test:e2e:obsidian:local-suite` builds the plug-in and, unless `LIVESYNC_CLI_COMMAND` selects an external CLI, the local LiveSync CLI. It then runs discovery, smoke, Svelte dialogue mounting, vault reflection, CouchDB upload, CLI-to-Obsidian synchronisation, Object Storage upload, startup scan, two-vault synchronisation, Hidden File Sync, Customisation Sync, and setting Markdown export in sequence. Start the local CouchDB and MinIO fixtures before running it, or use `test:e2e:obsidian:local-suite:services` to let the wrapper stop leftover fixtures, start fresh fixtures, and stop them again after the run. +`test:e2e:obsidian:local-suite` builds the plug-in and, unless `LIVESYNC_CLI_COMMAND` selects an external CLI, the local LiveSync CLI. It then runs discovery, smoke, Svelte dialogue mounting, settings UI, vault reflection, CouchDB upload, CLI-to-Obsidian synchronisation, Object Storage upload, startup scan, two-vault synchronisation, Hidden File Sync, Customisation Sync, and setting Markdown export in sequence. Start the local CouchDB and MinIO fixtures before running it, or use `test:e2e:obsidian:local-suite:services` to let the wrapper stop leftover fixtures, start fresh fixtures, and stop them again after the run. `test:e2e:obsidian:couchdb-upload` reuses the CouchDB variables from `.test.env` or the process environment. It expects a reachable CouchDB service, creates a unique database, configures Self-hosted LiveSync through `obsidian-cli eval`, creates a note in real Obsidian, commits the note into the local database, runs one-shot synchronisation, and verifies that the remote database contains both the metadata document and its chunk documents. @@ -139,6 +142,7 @@ Useful environment variables: - `E2E_OBSIDIAN_SKIP_EXTRACT=true`: download the AppImage without extracting it. - `E2E_OBSIDIAN_SMOKE_TIMEOUT_MS`: smoke timeout in milliseconds. - `E2E_OBSIDIAN_DIALOG_TIMEOUT_MS`: timeout for a representative Svelte dialogue to mount, expose its principal controls, and close; default is 10 seconds. +- `E2E_OBSIDIAN_SETTINGS_TIMEOUT_MS`: timeout for the settings pane and its deletion controls to become visible; default is 10 seconds. - `E2E_OBSIDIAN_READY_TIMEOUT_MS`: plug-in readiness timeout in milliseconds. - `E2E_OBSIDIAN_CLI_READY_TIMEOUT_MS`: timeout for waiting until the vault-side Obsidian CLI exposes the plug-in catalogue. - `E2E_OBSIDIAN_CLI_TIMEOUT_MS`: timeout for each `obsidian-cli` invocation. diff --git a/test/e2e-obsidian/scripts/local-suite.ts b/test/e2e-obsidian/scripts/local-suite.ts index 496a2fb8..9dc76b63 100644 --- a/test/e2e-obsidian/scripts/local-suite.ts +++ b/test/e2e-obsidian/scripts/local-suite.ts @@ -14,6 +14,7 @@ const testSteps: Step[] = [ { name: "discover", args: ["run", "test:e2e:obsidian:discover"] }, { name: "smoke", args: ["run", "test:e2e:obsidian:smoke"] }, { name: "Svelte dialogue mounts", args: ["run", "test:e2e:obsidian:dialog-mounts"] }, + { name: "settings UI", args: ["run", "test:e2e:obsidian:settings-ui"] }, { name: "vault reflection", args: ["run", "test:e2e:obsidian:vault-reflection"] }, { name: "CouchDB upload", args: ["run", "test:e2e:obsidian:couchdb-upload"] }, { diff --git a/test/e2e-obsidian/scripts/settings-ui.ts b/test/e2e-obsidian/scripts/settings-ui.ts new file mode 100644 index 00000000..835b6daa --- /dev/null +++ b/test/e2e-obsidian/scripts/settings-ui.ts @@ -0,0 +1,93 @@ +import { discoverObsidianCli, requireObsidianBinary } from "../runner/environment.ts"; +import { waitForLiveSyncCoreReady } from "../runner/liveSyncWorkflow.ts"; +import { startObsidianLiveSyncSession, type ObsidianLiveSyncSession } from "../runner/session.ts"; +import { obsidianRemoteDebuggingPort, withObsidianPage } from "../runner/ui.ts"; +import { createTemporaryVault } from "../runner/vault.ts"; + +const uiTimeoutMs = Number(process.env.E2E_OBSIDIAN_SETTINGS_TIMEOUT_MS ?? 10000); + +type ObsidianSettingsController = { + open(): void; + openTabById(tabId: string): void; +}; + +type ObsidianTestApp = { + setting?: ObsidianSettingsController; +}; + +type ObsidianTestGlobal = typeof globalThis & { app?: ObsidianTestApp }; + +async function verifyDeletionSettings(): Promise { + await withObsidianPage(obsidianRemoteDebuggingPort(), async (page) => { + await page.evaluate(() => { + const setting = (globalThis as ObsidianTestGlobal).app?.setting; + if (setting === undefined) throw new Error("Obsidian settings are unavailable"); + setting.open(); + setting.openTabById("obsidian-livesync"); + }); + + const liveSyncSettings = page.locator(".sls-setting"); + await liveSyncSettings.waitFor({ state: "visible", timeout: uiTimeoutMs }); + await liveSyncSettings.locator('.sls-setting-menu-btn[title="Sync Settings"]').click(); + + const deletionPanel = liveSyncSettings + .locator("h4.sls-setting-panel-title") + .filter({ hasText: "Deletion Propagation" }) + .locator(".."); + await deletionPanel + .getByText("Keep empty folder", { exact: true }) + .waitFor({ state: "visible", timeout: uiTimeoutMs }); + + const obsoleteToggleCount = await deletionPanel.getByText("Use the trash bin", { exact: true }).count(); + if (obsoleteToggleCount !== 0) { + throw new Error( + `The obsolete LiveSync trash toggle is still present in the settings UI (${obsoleteToggleCount} found).` + ); + } + }); +} + +async function main(): Promise { + const binary = requireObsidianBinary(); + const cli = discoverObsidianCli(); + if (!cli.binary) { + throw new Error(`Could not find obsidian-cli. Checked paths: ${cli.checked.join(", ")}`); + } + const vault = await createTemporaryVault(); + let session: ObsidianLiveSyncSession | undefined; + try { + session = await startObsidianLiveSyncSession({ + binary, + cliBinary: cli.binary, + vault, + startupGraceMs: Number(process.env.E2E_OBSIDIAN_STARTUP_GRACE_MS ?? 1000), + pluginData: { + doctorProcessedVersion: "0.25.27", + isConfigured: true, + lastReadUpdates: Number.MAX_SAFE_INTEGER, + liveSync: false, + notifyThresholdOfRemoteStorageSize: 0, + syncOnStart: false, + syncOnSave: false, + syncOnEditorSave: false, + syncOnFileOpen: false, + syncAfterMerge: false, + periodicReplication: false, + useAdvancedMode: true, + }, + }); + await waitForLiveSyncCoreReady(cli.binary, session.cliEnv); + await verifyDeletionSettings(); + console.log("Deletion settings expose only effective user controls."); + } finally { + if (session) { + await session.app.stop(); + } + await vault.dispose(); + } +} + +main().catch((error: unknown) => { + console.error(error instanceof Error ? error.stack : error); + process.exit(1); +}); diff --git a/updates.md b/updates.md index e9d1f9cf..209ba551 100644 --- a/updates.md +++ b/updates.md @@ -5,6 +5,10 @@ The head note of 0.25 is now in [updates_old.md](https://github.com/vrtmrz/obsid ## Unreleased +### Improved + +- Removed the ineffective 'Use the trash bin' toggle from the settings interface. Remote deletions continue to follow Obsidian's deletion preference, while the legacy setting key remains accepted for compatibility. + ### Miscellaneous - Replaced the embedded Commonlib source and generated fallback declarations with a locked compiled package, reducing duplicated release and repository-scanner inputs without changing synchronisation behaviour.