From f990abb7ef040027fb0911307fbc2fcfd5981e6b Mon Sep 17 00:00:00 2001 From: Felvesthe <23108389+Felvesthe@users.noreply.github.com> Date: Sun, 30 Nov 2025 18:24:43 +0100 Subject: [PATCH] Add option to prevent editing in normally locked notes * Add "Prevent editing in locked notes" setting (default: off) * Hide edit buttons when prevention is enabled * Force preview mode when prevention is enabled for locked notes * Normally locked notes are editable when prevention is disabled Signed-off-by: Felvesthe <23108389+Felvesthe@users.noreply.github.com> --- src/main.ts | 115 ++++++++++++++++++++++++++------------------ src/models/types.ts | 4 +- src/settings.ts | 17 ++++++- 3 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/main.ts b/src/main.ts index eceba9d..e311dbf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -459,7 +459,7 @@ export default class NoteLockerPlugin extends Plugin { return false; } - private updateLeafMode(leaf: WorkspaceLeaf | null) { + public updateLeafMode(leaf: WorkspaceLeaf | null) { if (!leaf || !(leaf.view instanceof MarkdownView)) return; const { view } = leaf; @@ -486,7 +486,7 @@ export default class NoteLockerPlugin extends Plugin { } } else if (isLocked) { const state = leaf.getViewState(); - if (state.state?.mode === 'source') { + if (this.settings.preventEditInLockedNotes && state.state?.mode === 'source') { leaf.setViewState({ ...state, state: { ...state.state, mode: 'preview' }, @@ -495,55 +495,76 @@ export default class NoteLockerPlugin extends Plugin { } if (isStrictLocked) { - const container = view.containerEl; - const allActions = container.querySelectorAll('.view-action'); - - allActions.forEach(btn => { - if (btn instanceof HTMLElement) { - const ariaLabel = btn.getAttribute('aria-label') || ''; - const hasPencilIcon = !!btn.querySelector('.lucide-pencil'); - - if (hasPencilIcon || ariaLabel.includes('Edit') || ariaLabel.includes('edit') || ariaLabel.includes('Switch to editing')) { - btn.style.display = 'none'; - } - } - }); - - let lockBtn = container.querySelector('.note-locker-strict-btn'); - if (!lockBtn) { - lockBtn = document.createElement('div'); - lockBtn.addClass('view-action', 'clickable-icon', 'note-locker-strict-btn'); - lockBtn.setAttribute('aria-label', 'Strictly Locked'); - lockBtn.innerHTML = ''; - - lockBtn.addEventListener('click', () => { - new StrictUnlockModal(this.app, () => { - this.toggleStrictLock(path); - }).open(); - }); - - const actionsContainer = container.querySelector('.view-actions'); - if (actionsContainer) { - actionsContainer.prepend(lockBtn); - } - } + this.hideEditButtons(view); + this.addStrictLockButton(view, path); + } else if (isLocked && this.settings.preventEditInLockedNotes) { + this.hideEditButtons(view); + this.removeStrictLockButton(view); } else { - const container = view.containerEl; - const editBtns = container.querySelectorAll('.view-action'); - editBtns.forEach(btn => { - if (btn instanceof HTMLElement) { - if (btn.getAttribute('aria-label')?.includes('Edit') || - btn.getAttribute('aria-label')?.includes('edit') || - btn.querySelector('.lucide-pencil')) { - btn.style.display = ''; - } - } - }); - const lockBtn = container.querySelector('.note-locker-strict-btn'); - if (lockBtn) lockBtn.remove(); + this.showEditButtons(view); + this.removeStrictLockButton(view); } } + private hideEditButtons(view: MarkdownView) { + const container = view.containerEl; + const allActions = container.querySelectorAll('.view-action'); + + allActions.forEach(btn => { + if (btn instanceof HTMLElement) { + const ariaLabel = btn.getAttribute('aria-label') || ''; + const hasPencilIcon = !!btn.querySelector('.lucide-pencil'); + + if (hasPencilIcon || ariaLabel.includes('Edit') || ariaLabel.includes('edit') || ariaLabel.includes('Switch to editing')) { + btn.style.display = 'none'; + } + } + }); + } + + private showEditButtons(view: MarkdownView) { + const container = view.containerEl; + const editBtns = container.querySelectorAll('.view-action'); + editBtns.forEach(btn => { + if (btn instanceof HTMLElement) { + if (btn.getAttribute('aria-label')?.includes('Edit') || + btn.getAttribute('aria-label')?.includes('edit') || + btn.querySelector('.lucide-pencil')) { + btn.style.display = ''; + } + } + }); + } + + private addStrictLockButton(view: MarkdownView, path: string) { + const container = view.containerEl; + let lockBtn = container.querySelector('.note-locker-strict-btn'); + if (!lockBtn) { + lockBtn = document.createElement('div'); + lockBtn.addClass('view-action', 'clickable-icon', 'note-locker-strict-btn'); + lockBtn.setAttribute('aria-label', 'Strictly Locked'); + lockBtn.innerHTML = ''; + + lockBtn.addEventListener('click', () => { + new StrictUnlockModal(this.app, () => { + this.toggleStrictLock(path); + }).open(); + }); + + const actionsContainer = container.querySelector('.view-actions'); + if (actionsContainer) { + actionsContainer.prepend(lockBtn); + } + } + } + + private removeStrictLockButton(view: MarkdownView) { + const container = view.containerEl; + const lockBtn = container.querySelector('.note-locker-strict-btn'); + if (lockBtn) lockBtn.remove(); + } + + async loadSettings() { const loaded = await this.loadData(); if (loaded) { diff --git a/src/models/types.ts b/src/models/types.ts index d4dc261..ffe6fd2 100644 --- a/src/models/types.ts +++ b/src/models/types.ts @@ -7,6 +7,7 @@ export interface NoteLockerSettings { showFileExplorerIcons: boolean; showStatusBarButton: boolean; showNotifications: boolean; + preventEditInLockedNotes: boolean; } export const DEFAULT_SETTINGS: NoteLockerSettings = { @@ -17,5 +18,6 @@ export const DEFAULT_SETTINGS: NoteLockerSettings = { desktopNotificationMaxLength: 22, showFileExplorerIcons: true, showStatusBarButton: true, - showNotifications: true + showNotifications: true, + preventEditInLockedNotes: false }; diff --git a/src/settings.ts b/src/settings.ts index 7b8e626..9c1c592 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,4 +1,4 @@ -import { App, Platform, PluginSettingTab, Setting } from "obsidian"; +import { App, Platform, PluginSettingTab, Setting, MarkdownView } from "obsidian"; import type NoteLockerPlugin from "./main"; export class NoteLockerSettingTab extends PluginSettingTab { @@ -41,6 +41,21 @@ export class NoteLockerSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })); + new Setting(containerEl) + .setName('Prevent editing in locked notes') + .setDesc('If enabled, normally locked notes will be read-only. If disabled, you can switch to edit mode.') + .addToggle(toggle => toggle + .setValue(this.plugin.settings.preventEditInLockedNotes) + .onChange(async (value) => { + this.plugin.settings.preventEditInLockedNotes = value; + await this.plugin.saveSettings(); + this.plugin.app.workspace.iterateAllLeaves((leaf) => { + if (leaf.view instanceof MarkdownView && leaf.view.file) { + this.plugin.updateLeafMode(leaf); + } + }); + })); + const mobileNotificationSetting = new Setting(containerEl) .setName('Mobile notification max length') .setDesc('Maximum length of file names in notifications on mobile devices')