GeezerVison is showing github.com — feat: v0.2.0 — Firebase sync, window attachment & note security by devohmycode · Pull Request #5 · devohmycode/NoteUI
Conversation
devohmycode
commented
Mar 25, 2026
•
edited by coderabbitai
Bot
Loading
Uh oh!
There was an error while loading. Please reload this page.
Summary
- Note locking & password protection — secure individual notes with a password
- Full Firebase synchronisation — real-time bidirectional sync via RTDB with SSE streaming (replaces 45s polling)
- Window attachment — attach note windows to other application windows and website tabs
- Live refresh — open note windows update automatically when remote changes arrive
- Timezone-safe merge — date comparisons now use
ToUniversalTime() to prevent conflicts
- Title bar collapse fix
Changes
15 files changed, ~2800 insertions across FirebaseSync.cs, MainWindow.xaml.cs, NoteWindow.xaml.cs, NotesManager.cs, WindowAttachmentService.cs, and more.
Test plan
- Create, edit, and delete notes locally — verify persistence
- Connect Firebase and sync notes between two devices
- Verify SSE listener triggers instant refresh on remote changes
- Lock a note with a password, close and reopen — confirm prompt appears
- Attach a note window to another app window, move the target — note should follow
- Attach a note to a browser tab, switch tabs — verify visibility toggle
Summary by CodeRabbit
Release Notes
-
New Features
- Master password protection and note locking capability
- Note window attachment to running applications, folders, and web tabs with auto-show/hide
- Real-time cloud synchronization with improved conflict resolution
- Window position and size persistence across sessions
- Password reset functionality in settings
- Resizable note and notepad windows
-
UI/UX Enhancements
- Reorganized title bar: sync button added, settings button moved to status bar
- Lock and attachment icons on note windows
- Improved compact mode behavior with better width/height handling
-
Localization
- Added strings for lock, password, attachment, and sync features
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
- Added functionality to lock notes with a master password, enhancing security for sensitive information.
- Introduced UI elements for locking and unlocking notes, including a lock button in the NoteWindow.
- Implemented password creation and validation processes, ensuring only authorized access to locked notes.
- Enhanced AppSettings to manage master password storage securely using DPAPI.
- Updated localization for new locking features and associated warnings.
- Added reset options for master password and notes, allowing users to manage their data effectively.
- Added WindowAttachmentService to manage notes attached to running processes or folders.
- Introduced methods to save and load note positions, sizes, and attachment states.
- Enhanced UI to support attaching notes to visible windows, including new icons and menus.
- Updated AppSettings to store additional properties for note positions and attachment settings.
- Improved MainWindow and NoteWindow to handle resizing and attachment interactions.
- Added localization for new attachment features and UI elements.
- Bumped application version from 0.1.1 to 0.2.0.
- Added support for attaching notes to visible website tabs in addition to processes and folders.
- Enhanced UI to include options for selecting and attaching to website tabs.
- Updated localization for new attachment options related to website tabs.
- Refactored attachment logic to accommodate window titles and improve user experience.
Switch from 45-second DispatcherTimer polling to Server-Sent Events
streaming for instant sync. Open note windows now refresh automatically
when remote changes arrive. Fix timezone-aware date comparisons using
ToUniversalTime() and prevent sync loops with localOnly save flag.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
coderabbitai
Bot
commented
Mar 25, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
Caution
Review failed
The pull request is closed.
ℹ️ Recent review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 90776faf-1475-4aac-90a0-9372ef3a7169
📥 Commits
Reviewing files that changed from the base of the PR and between 7dcbe7a and ffc9ce8.
📒 Files selected for processing (15)
ActionPanel.cs
AppSettings.cs
FirebaseSync.cs
Lang.cs
MainWindow.xaml
MainWindow.xaml.cs
NoteWindow.xaml
NoteWindow.xaml.cs
NotepadWindow.xaml
NotepadWindow.xaml.cs
NotesManager.cs
WindowAttachmentHelper.cs
WindowAttachmentService.cs
WindowHelper.cs
installer.iss
📝 Walkthrough
Walkthrough
This pull request introduces master-password-protected note locking, real-time Firebase SSE synchronization, automatic window attachment system to show/hide notes based on foreground process or folder context, enhanced window position/size persistence, and localization updates. The installer version is bumped to 0.2.0.
Changes
| Cohort / File(s) |
Summary |
Master Password & Lock Management ActionPanel.cs, AppSettings.cs, NotesManager.cs |
Added password creation/entry flyout helpers in ActionPanel; DPAPI-backed master password storage in AppSettings; lock toggle on NoteEntry with ToggleLock() method and IsLocked property; password verification and note lock/unlock UI flows. |
Firebase Real-Time Sync FirebaseSync.cs |
Introduced SSE listener (StartListening/StopListening), NoteDeletionEntry model, merged pull-notes dictionary fetch, deletion tombstone tracking, and read-modify-write PATCH flow that combines remote/local notes using "ever seen" IDs and previous deletion state. |
Window Attachment System WindowAttachmentHelper.cs, WindowAttachmentService.cs, MainWindow.xaml.cs, NoteWindow.xaml.cs |
New WindowAttachmentHelper enumerates visible processes/web tabs via Win32; WindowAttachmentService monitors foreground/folder changes and triggers show/hide for attached notes; MainWindow coordinates attachment lifecycle and refresh; NoteWindow supports attach/detach actions with icon/tooltip feedback. |
Window Position & Resize Persistence AppSettings.cs, MainWindow.xaml.cs, NoteWindow.xaml.cs, NotepadWindow.xaml.cs, WindowHelper.cs |
Expanded MainWindow/Notepad position persistence to include width/height; NoteWindow now saves position/size/compact state on close; added AddResizeGrips() and borderless-resize hit-testing via WM_NCHITTEST for all window types. |
Data Model Extensions NotesManager.cs |
Added IsLocked property and window placement fields (PosX, PosY, Width, Height, IsCompact) plus attachment fields (AttachTarget, AttachMode, AttachOffsetX, AttachOffsetY) to NoteEntry; Save() accepts localOnly flag to skip cloud sync. |
UI Layout Updates MainWindow.xaml, NoteWindow.xaml, NotepadWindow.xaml |
Repositioned SettingsButton from title bar to status bar; added SyncButton and SyncIcon to title bar; added AttachIcon and LockButton to NoteWindow title bar; repositioned DragBar in NotepadWindow. |
Localization Lang.cs |
Added keys for sync tooltip, lock/unlock actions, master-password dialogs, reset workflows, and attachment-related strings (attach/detach/select) in both English and French. |
Version Metadata installer.iss |
Bumped AppVersion from 0.1.1 to 0.2.0. |
Sequence Diagram(s)
sequenceDiagram
participant User
participant MainWindow
participant WindowAttachmentService
participant NoteWindow
participant AppSettings
User->>MainWindow: Set note to attach to process
MainWindow->>NoteWindow: Store AttachTarget, AttachMode
NoteWindow->>AppSettings: Save position & attachment config
loop Continuous Monitoring
WindowAttachmentService->>WindowAttachmentService: Poll foreground window
alt Foreground matches AttachTarget
WindowAttachmentService->>MainWindow: ShowRequested event
MainWindow->>NoteWindow: Show & position near target
else No match & threshold reached
WindowAttachmentService->>MainWindow: HideRequested event
MainWindow->>NoteWindow: Hide note
end
end
User->>NoteWindow: Detach from process
NoteWindow->>NoteWindow: Clear AttachTarget/Mode
NoteWindow->>AppSettings: Save updated attachment state
NoteWindow->>MainWindow: Fire AttachmentChanged event
Loading
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
Poem
🐰 A rabbit bounds through windows with glee,
SSE streams real-time, notes locked securely!
Attachments track processes, positions persist—
Where windows are foreground, small notes shan't be missed! 🔐✨
✨ Finishing Touches
📝 Generate docstrings
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
0.2.0
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
Comment @coderabbitai help to get the list of available commands and usage tips.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Review Summary by Qodo
v0.2.0 — Firebase real-time sync, window attachment, and note security
✨ Enhancement 🐞 Bug fix

Walkthroughs
Description
• **Note locking & password protection** — secure individual notes with master password; locked
notes show obfuscated preview and require password to open/delete
• **Firebase real-time synchronization** — replaced 45-second polling with SSE streaming listener
for instant bidirectional sync and live refresh of note windows
• **Window attachment** — attach note windows to running processes, browser tabs, and Explorer
folders with auto-show/hide behavior based on foreground window
• **Timezone-safe conflict resolution** — implemented merge logic using UTC comparisons matching web
client behavior, with deletion tombstone tracking
• **Window resizing** — made all windows resizable with visual grips, persist window positions and
sizes across sessions
• **Enhanced UI** — added sync button to main window title bar, relocated settings button to status
bar, added lock and attachment indicators to note windows
• **Localization** — added 32+ new localization keys for security, attachment, and sync features in
English and French
• **Bug fix** — corrected drag bar z-order in notepad window to prevent blocking title bar
interactions
Diagram
flowchart LR
A["Local Notes"] -->|"SSE Listener"| B["Firebase RTDB"]
B -->|"Instant Sync"| C["Remote Devices"]
D["Note Window"] -->|"Attach"| E["Process/Tab/Folder"]
E -->|"Monitor"| F["WindowAttachmentService"]
F -->|"Auto Show/Hide"| D
G["Master Password"] -->|"Encrypt"| H["Note Lock"]
H -->|"Protect"| A
I["Merge Logic"] -->|"UTC Compare"| J["Conflict Resolution"]
J -->|"Sync"| B
Loading

File Changes
1. MainWindow.xaml.cs
✨ Enhancement +657/-50
Firebase real-time sync, window attachment, and note locking
• Added WindowAttachmentService integration for attaching notes to running processes, browser
tabs, and Explorer folders with auto-show/hide behavior
• Implemented Firebase real-time SSE listener (StartFirebaseListener, StopFirebaseListener)
replacing 45-second polling with instant refresh
• Added note locking with master password support; locked notes show obfuscated preview and require
password to open/delete
• Enhanced window resizing: made windows resizable, added resize grips, and persist window
positions/sizes for main window and individual notes
• Added attachment UI in note context menu with process picker, web tab picker, and folder picker
• Improved compact mode to preserve pre-compact dimensions and animate width changes
MainWindow.xaml.cs
2. WindowAttachmentService.cs
✨ Enhancement +698/-0
New service for window attachment and auto-visibility
• New service that monitors foreground windows and Explorer folders to auto-show/hide attached notes
• Implements Win32 event hooks (SetWinEventHook) for foreground window changes and timers for
Explorer folder polling
• Supports three attachment modes: process (running application), title (browser tab by window
title), and folder (Explorer path)
• Provides helper methods to get visible windows, web tabs, and open Explorer paths with active tab
detection
• Calculates and saves relative note position offsets to target windows for consistent placement
WindowAttachmentService.cs
3. NoteWindow.xaml.cs
✨ Enhancement +259/-22
Note locking, attachment UI, and sync reload support
• Added lock button and attachment icon to note title bar with visual indicators
• Implemented ReloadAfterSync() to update note content when remote changes arrive via Firebase
• Added attachment menu with process, web tab, and folder picker options
• Enhanced compact mode to preserve pre-compact width/height and animate width during state
transitions
• Improved text color handling for full-color note style to maintain readability on pastel
backgrounds
• Added SetPinnedOnTop() method and lock toggle handler with password creation/verification
NoteWindow.xaml.cs
View more (12)
4. FirebaseSync.cs
✨ Enhancement +338/-8
Firebase real-time SSE listener and conflict resolution
• Added MergePullWithLocal() and MergeNotesForPush() methods implementing conflict resolution
matching web client (timezone-safe UTC comparisons)
• Implemented SSE real-time listener (StartListening, ListenLoopAsync) for instant Firebase RTDB
updates with skip logic for local writes
• Added PullNoteDeletionsAsync() to fetch tombstone records and MergeNoteDeletionsForPush() for
deletion tracking
• Added NoteDeletionEntry class for RTDB tombstone entries under users/{uid}/noteDeletions
• Changed PullNotesAsync() to use dictionary format internally for merge operations
FirebaseSync.cs
5. ActionPanel.cs
✨ Enhancement +250/-1
Password management and reset UI flyouts
• Added ShowCreatePasswordFlyout() and ShowEnterPasswordFlyout() for master password creation
and verification flows
• Added reset sub-panel with password and notes reset options, including confirmation dialogs with
warnings
• Integrated password validation and error messaging in reset confirmation UI
• Extended CreateSettings() signature to accept onResetPassword and onResetNotes callbacks
ActionPanel.cs
6. WindowHelper.cs
✨ Enhancement +154/-2
Borderless window resizing with visual grips
• Enhanced RemoveWindowBorderKeepResize() to handle WM_NCHITTEST for resize edge detection while
keeping borderless appearance
• Added AddResizeGrips() method that creates invisible XAML resize grips on edges and corners with
pointer capture for native resize behavior
• Implemented ResizeGrip helper class with cursor shape feedback for different resize directions
• Added Win32 P/Invoke declarations for GetWindowRect, GetCursorPos, and related resize
constants
WindowHelper.cs
7. NotesManager.cs
✨ Enhancement +57/-16
Note locking, attachment properties, and improved sync
• Added ToggleLock() method to toggle note lock state and update timestamp
• Added DeleteAllNotes() method for bulk deletion
• Added window position/size properties to NoteEntry: PosX, PosY, Width, Height,
IsCompact
• Added attachment properties to NoteEntry: AttachTarget, AttachMode, AttachOffsetX,
AttachOffsetY
• Added IsLocked property to NoteEntry
• Updated SyncFromFirebase() to use new merge logic with deletion tombstones and ever-seen
tracking
• Updated SyncSettingsToFirebase() and SyncSettingsFromFirebase() to handle master password hash
• Modified Save() to accept localOnly parameter to skip cloud push when merging remote data
NotesManager.cs
8. AppSettings.cs
✨ Enhancement +129/-4
Master password encryption and window position persistence
• Added master password management with DPAPI encryption: SaveMasterPasswordHash(),
LoadMasterPasswordHash(), DeleteMasterPassword(), HashPassword()
• Added Firebase ever-seen note IDs tracking: LoadFirebaseEverSeenNoteIds(),
SaveFirebaseEverSeenNoteIds() for conflict resolution
• Added notepad window position/size persistence: SaveNotepadPosition(), LoadNotepadPosition()
• Updated SaveMainWindowPosition() and LoadMainWindowPosition() to include width and height
AppSettings.cs
9. NotepadWindow.xaml.cs
✨ Enhancement +1/-0
Enable notepad window resizing
• Added WindowHelper.AddResizeGrips() call to enable resizing for notepad window
NotepadWindow.xaml.cs
10. Lang.cs Localization +58/-0
Localization strings for sync, security, and attachment features
• Added tip_sync tooltip label for synchronization button in English and French
• Added 18 new localization keys for note locking/password protection features (lock, unlock, master
password, password validation messages, etc.)
• Added 14 new localization keys for window/tab attachment features (attach to
window/program/website/folder, detach, selection prompts)
• Translations provided for both English and French language dictionaries
Lang.cs
11. WindowAttachmentHelper.cs ✨ Enhancement +149/-0
Window and browser tab enumeration helper for attachment
• New utility class providing window and web tab enumeration for attachment picker UI
• GetVisibleWindows() method enumerates visible application windows using Win32 API, filters
system processes, and deduplicates by process name
• GetVisibleWebTabs() method identifies browser windows (Chrome, Edge, Firefox, Brave, etc.) and
extracts normalized tab titles
• Helper method NormalizeBrowserTitle() strips browser-specific suffixes from window titles for
cleaner display
WindowAttachmentHelper.cs
12. installer.iss ⚙️ Configuration changes +1/-1
Version bump to 0.2.0
• Updated AppVersion from 0.1.1 to 0.2.0 to reflect the new release version
installer.iss
13. MainWindow.xaml ✨ Enhancement +22/-15
UI layout refactor with sync button and settings relocation
• Added new SyncButton with sync icon in the title bar for Firebase synchronization
• Moved SettingsButton from title bar to status bar (bottom-right) with adjusted styling
• Renamed status bar grid to StatusBar and repositioned QuickAccessButton to left alignment
• Settings button now uses smaller icon (14x14) and positioned in status bar with CornerRadius
MainWindow.xaml
14. NotepadWindow.xaml 🐞 Bug fix +8/-6
Drag bar z-order fix for title bar interaction
• Removed DragBar from its original position at the beginning of the title bar grid
• Re-added DragBar at the end of the title bar with explicit height (12px) and top alignment for
proper z-order layering
• This ensures the drag bar appears on top of other title bar elements without blocking interactions
NotepadWindow.xaml
15. NoteWindow.xaml ✨ Enhancement +11/-0
Lock and attachment status indicators in note window
• Added AttachIcon (link icon) to display when a note is attached to a window/tab, positioned left
of title with 50% opacity
• Added LockButton in the title bar button stack with lock icon for note password protection
• Lock button includes hover animation support via AnimatedButton_PointerEntered/Exited handlers
NoteWindow.xaml


|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Code Review by Qodo
🐞 Bugs (6) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)


1. Locked notes not encrypted 🐞 Bug ⛨ Security
Description
The new lock feature only gates UI access; locked note Content is still serialized to notes.json and
pushed to Firebase/WebDAV in plaintext, so “password protection” does not protect confidentiality.
Anyone with local file access or sync/RTDB access can read locked note content directly.
Code
NotesManager.cs[R49-52]
+ public void Save(bool localOnly = false)
{
try
{
Evidence
Notes are persisted and synced by serializing the full NoteEntry list (including Content) regardless
of IsLocked. The PR introduces IsLocked but does not add any encryption layer before writing
notes.json or pushing to cloud.
NotesManager.cs[49-66]
NotesManager.cs[480-503]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Locked notes are not actually protected: `NoteEntry.Content` is written and synced in plaintext even when `IsLocked=true`.
## Issue Context
Current implementation adds `IsLocked` and password prompts, but storage/sync paths still serialize the entire note model unchanged.
## Fix Focus Areas
- NotesManager.cs[49-66]
- NotesManager.cs[453-503]
## Implementation notes
- Encrypt `Content` (and any other sensitive fields) when `IsLocked=true` before persisting/syncing.
- Store encryption metadata per note (e.g., version, salt, nonce/IV) and decrypt only after successful password entry.
- Use a slow KDF (e.g., PBKDF2) to derive a key from the master password; avoid raw SHA-256 as a key/verification primitive.
- Ensure Firebase/WebDAV payloads never include plaintext for locked notes.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
2. Master hash synced remotely 🐞 Bug ⛨ Security
Description
The master password hash is uploaded to Firebase settings and later restored, enabling offline
brute-force if RTDB is accessed and making local DPAPI protection irrelevant. A local “reset
password” can also be undone by the next settings pull (rehydrating the remote hash).
Code
NotesManager.cs[R185-193]
["theme"] = AppSettings.LoadThemeSetting(),
["backdrop"] = AppSettings.LoadSettings().Type,
};
+ var masterPwHash = AppSettings.LoadMasterPasswordHash();
+ if (!string.IsNullOrEmpty(masterPwHash))
+ settings["masterPasswordHash"] = masterPwHash;
await Firebase.PushSettingsAsync(settings);
}
Evidence
SyncSettingsToFirebase includes masterPasswordHash in the uploaded settings, and
SyncSettingsFromFirebase writes any remote value back locally via DPAPI. This explicitly moves the
hash to cloud storage.
NotesManager.cs[178-222]
AppSettings.cs[38-78]
NotesManager.cs[149-163]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The master password hash is synced to Firebase, enabling offline brute force and negating local DPAPI protection.
## Issue Context
`SyncSettingsToFirebase` uploads `masterPasswordHash`, and `SyncSettingsFromFirebase` restores it on startup.
## Fix Focus Areas
- NotesManager.cs[178-222]
- NotesManager.cs[149-163]
## Implementation notes
- Remove `masterPasswordHash` from settings sync entirely (keep it local-only).
- If cross-device unlock is required, store only an encrypted key-wrapping artifact (e.g., a random key encrypted with a password-derived key) rather than a reusable verifier/hash.
- Ensure reset password cannot be reverted by remote settings pulls.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

3. Reset confirm password bypass 🐞 Bug ⛨ Security
Description
Reset-confirm flow accepts any non-empty password when LoadMasterPasswordHash() returns null
(missing/corrupt/DPAPI failure), because the mismatch check is skipped. This allows deleting the
local master password without actually verifying it in those cases.
Code
ActionPanel.cs[R790-804]
+ if (requirePassword && passwordBox != null && errorText != null)
+ {
+ if (string.IsNullOrEmpty(passwordBox.Password))
+ {
+ errorText.Text = Lang.T("password_required");
+ errorText.Visibility = Visibility.Visible;
+ return;
+ }
+ var storedHash = AppSettings.LoadMasterPasswordHash();
+ if (storedHash != null && AppSettings.HashPassword(passwordBox.Password) != storedHash)
+ {
+ errorText.Text = Lang.T("wrong_password");
+ errorText.Visibility = Visibility.Visible;
+ return;
+ }
Evidence
The confirm handler checks for mismatch only when storedHash != null; LoadMasterPasswordHash()
returns null on exceptions or missing file, causing the verification branch to be skipped.
ActionPanel.cs[788-807]
AppSettings.cs[56-66]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Password verification for reset is bypassed when the stored hash cannot be loaded.
## Issue Context
`storedHash != null` gates the mismatch check; null means no verification occurs.
## Fix Focus Areas
- ActionPanel.cs[788-807]
- AppSettings.cs[56-66]
## Implementation notes
- If `requirePassword` and `storedHash` is null/empty, show an error and block the reset (or require an alternate stronger confirmation flow).
- Consider loading the hash at click-time and treating load failures as hard failures for destructive actions.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
4. Detached notes never hidden 🐞 Bug ✓ Correctness
Description
Window attachment tracking uses _visibleNoteIds, but hide logic only iterates notes that currently
have AttachMode set; if a note is detached (AttachMode cleared) or removed, its id can remain
visible and HideRequested will never fire. This can leave attached note windows stuck visible
after detaching/deleting.
Code
WindowAttachmentService.cs[R130-165]
+ private void EvaluateProcessAttachments(string? foregroundProcess, IntPtr hwnd)
+ {
+ var processNotes = _notes.Notes
+ .Where(n => n.AttachMode == "process" && !string.IsNullOrEmpty(n.AttachTarget))
+ .ToList();
+
+ var isOwnProcessForeground = IsOwnProcessForeground(foregroundProcess);
+
+ foreach (var note in processNotes)
+ {
+ var matches = IsSameProcessTarget(note.AttachTarget, foregroundProcess);
+
+ if (matches && !IsIconic(hwnd))
+ {
+ MarkAttachmentMatch(note.Id);
+ if (_visibleNoteIds.Add(note.Id))
+ ShowRequested?.Invoke(note, hwnd);
+ }
+ else if (isOwnProcessForeground && _visibleNoteIds.Contains(note.Id))
+ {
+ // Keep already-attached note visible while user interacts with it
+ // (drag/edit focuses NoteUI, not the target process),
+ // but only while the target window is still actually visible.
+ if (HasAnyVisibleWindowForProcess(note.AttachTarget))
+ {
+ MarkAttachmentMatch(note.Id);
+ continue;
+ }
+ }
+
+ if (ShouldHideAfterMiss(note.Id) && _visibleNoteIds.Remove(note.Id))
+ {
+ ClearAttachmentState(note.Id);
+ HideRequested?.Invoke(note.Id);
+ }
+ }
Evidence
EvaluateProcessAttachments/EvaluateWindowTitleAttachments iterate only notes where AttachMode is
'process'/'title', so detached notes are excluded from evaluation and can’t be removed from
_visibleNoteIds. Refresh() just re-runs these checks and doesn’t reconcile _visibleNoteIds
against current note attachment state.
WindowAttachmentService.cs[120-165]
WindowAttachmentService.cs[71-76]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Detached/deleted notes can remain in `_visibleNoteIds` and never get hidden.
## Issue Context
Hide logic only runs for notes still matching attachment filters.
## Fix Focus Areas
- WindowAttachmentService.cs[71-76]
- WindowAttachmentService.cs[130-165]
- WindowAttachmentService.cs[201-236]
- WindowAttachmentService.cs[390-433]
## Implementation notes
- Before evaluating attachments, reconcile `_visibleNoteIds` with current notes/attachment state:
- Remove ids that no longer exist.
- Remove ids whose note no longer has an attachment mode/target.
- Fire `HideRequested` for any removed-visible ids.
- Alternatively, iterate over `_visibleNoteIds` and validate each id against current note state each tick.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
5. Explorer COM objects not released 🐞 Bug ⛯ Reliability
Description
GetOpenExplorerPaths creates COM objects via dynamic (Shell.Application, ShellWindows, window items)
without deterministic release; called every 1.5s, this can accumulate COM references and degrade
memory/performance over long runtimes. Relying on GC for COM cleanup is non-deterministic.
Code
WindowAttachmentService.cs[R499-528]
+ var shellType = Type.GetTypeFromProgID("Shell.Application");
+ if (shellType == null) return [];
+ dynamic shell = Activator.CreateInstance(shellType)!;
+ dynamic windows = shell.Windows();
+ int count = windows.Count;
+ for (int i = 0; i < count; i++)
+ {
+ try
+ {
+ dynamic w = windows.Item(i);
+ string? fullName = w.FullName;
+ if (fullName == null || !fullName.EndsWith("explorer.exe", StringComparison.OrdinalIgnoreCase))
+ continue;
+ string? url = w.LocationURL;
+ if (string.IsNullOrEmpty(url)) continue;
+ var uri = new Uri(url);
+ if (!uri.IsFile) continue;
+
+ var hwnd = (IntPtr)(long)w.HWND;
+ string locationName = "";
+ try { locationName = w.LocationName ?? ""; } catch { }
+
+ var localPath = NormalizePath(uri.LocalPath);
+ if (string.IsNullOrWhiteSpace(localPath)) continue;
+
+ allShellWindows.Add((localPath, hwnd, locationName));
+ }
+ catch { }
+ }
+ }
Evidence
The method constructs COM objects with Activator.CreateInstance and iterates windows.Item(i) but
never calls Marshal.ReleaseComObject/FinalReleaseComObject. The service polls this on a timer,
so cleanup timing depends on GC rather than being deterministic.
WindowAttachmentService.cs[493-529]
WindowAttachmentService.cs[35-40]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
COM objects created in `GetOpenExplorerPaths` are not explicitly released.
## Issue Context
Method runs frequently via `_explorerTimer`, so COM references can accumulate.
## Fix Focus Areas
- WindowAttachmentService.cs[493-529]
## Implementation notes
- Use `Marshal.ReleaseComObject` / `Marshal.FinalReleaseComObject` in `finally` blocks for:
- `shell`
- `windows`
- each `w = windows.Item(i)`
- Prefer strongly-typed COM interop wrappers if available; avoid `dynamic` where possible.
- Ensure exceptions still release any partially created COM objects.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

6. Reset ignores attached windows 🐞 Bug ✓ Correctness
Description
Reset notes closes only windows in _openNoteWindows and deletes notes, but it does not close
windows opened via window attachment (_attachedNoteWindows). This can leave attached note windows
open while their underlying notes have been deleted until some later cleanup happens.
Code
MainWindow.xaml.cs[R1195-1201]
+ onResetNotes: () =>
+ {
+ foreach (var w in _openNoteWindows.ToList())
+ try { w.Close(); } catch { }
+ _openNoteWindows.Clear();
+ _notes.DeleteAllNotes();
+ RefreshCurrentView();
Evidence
Attached windows are tracked in a separate _attachedNoteWindows dictionary and are created outside
_openNoteWindows. The reset handler only closes and clears _openNoteWindows and does not touch
_attachedNoteWindows.
MainWindow.xaml.cs[33-38]
MainWindow.xaml.cs[967-1028]
MainWindow.xaml.cs[1195-1201]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Resetting notes does not close note windows created by the attachment system.
## Issue Context
Attached note windows are tracked separately from manually opened note windows.
## Fix Focus Areas
- MainWindow.xaml.cs[1195-1201]
- MainWindow.xaml.cs[967-1028]
## Implementation notes
- In `onResetNotes`, iterate `_attachedNoteWindows.Values` and close them, then clear `_attachedNoteWindows` / `_attachedTargetHwnds`.
- Optionally call `_attachmentService?.Refresh()` after clearing notes to ensure service state is consistent.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

ⓘ The new review experience is currently in Beta. Learn more


|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Comment on lines
+49
to
52
|
|
public void Save(bool localOnly = false)
|
|
|
{
|
|
|
try
|
|
|
{
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.

1. Locked notes not encrypted 🐞 Bug ⛨ Security
The new lock feature only gates UI access; locked note Content is still serialized to notes.json and
pushed to Firebase/WebDAV in plaintext, so “password protection” does not protect confidentiality.
Anyone with local file access or sync/RTDB access can read locked note content directly.
Agent Prompt
## Issue description
Locked notes are not actually protected: `NoteEntry.Content` is written and synced in plaintext even when `IsLocked=true`.
## Issue Context
Current implementation adds `IsLocked` and password prompts, but storage/sync paths still serialize the entire note model unchanged.
## Fix Focus Areas
- NotesManager.cs[49-66]
- NotesManager.cs[453-503]
## Implementation notes
- Encrypt `Content` (and any other sensitive fields) when `IsLocked=true` before persisting/syncing.
- Store encryption metadata per note (e.g., version, salt, nonce/IV) and decrypt only after successful password entry.
- Use a slow KDF (e.g., PBKDF2) to derive a key from the master password; avoid raw SHA-256 as a key/verification primitive.
- Ensure Firebase/WebDAV payloads never include plaintext for locked notes.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Comment on lines
185
to
193
|
|
["theme"] = AppSettings.LoadThemeSetting(),
|
|
|
["backdrop"] = AppSettings.LoadSettings().Type,
|
|
|
};
|
|
|
var masterPwHash = AppSettings.LoadMasterPasswordHash();
|
|
|
if (!string.IsNullOrEmpty(masterPwHash))
|
|
|
settings["masterPasswordHash"] = masterPwHash;
|
|
|
await Firebase.PushSettingsAsync(settings);
|
|
|
}
|
|
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.

2. Master hash synced remotely 🐞 Bug ⛨ Security
The master password hash is uploaded to Firebase settings and later restored, enabling offline
brute-force if RTDB is accessed and making local DPAPI protection irrelevant. A local “reset
password” can also be undone by the next settings pull (rehydrating the remote hash).
Agent Prompt
## Issue description
The master password hash is synced to Firebase, enabling offline brute force and negating local DPAPI protection.
## Issue Context
`SyncSettingsToFirebase` uploads `masterPasswordHash`, and `SyncSettingsFromFirebase` restores it on startup.
## Fix Focus Areas
- NotesManager.cs[178-222]
- NotesManager.cs[149-163]
## Implementation notes
- Remove `masterPasswordHash` from settings sync entirely (keep it local-only).
- If cross-device unlock is required, store only an encrypted key-wrapping artifact (e.g., a random key encrypted with a password-derived key) rather than a reusable verifier/hash.
- Ensure reset password cannot be reverted by remote settings pulls.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
1 more reviewer
Reviewers whose approvals may not affect merge requirements
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|