Skip to content

Bug: Preview link clicks and checkboxes break after switching notes #1922

@gjouret

Description

@gjouret

Summary

When switching between notes in preview mode, clicking links (asset links, external URLs) and toggling checkboxes stops working. The same issue affects scroll position tracking.

Steps to Reproduce

  1. Open Note A in preview mode (Cmd+/)
  2. Click a link in Note A — it works
  3. Switch to Note B (also in preview mode)
  4. Click a link in Note B — may or may not work
  5. Switch back to Note A
  6. Click any link in Note A — nothing happens

Root Cause

The MPreviewView (WKWebView subclass) is reused across note switches — loadMarkdownWebView() only creates a new instance on first use. On subsequent note switches, it calls webView.load(note:force:) which loads new HTML but does NOT update the native WKScriptMessageHandler instances.

Three handlers hold a strong reference to the original note from init() time:

  • HandlerOpen — handles link clicks
  • HandlerCheckbox — handles checkbox toggles
  • PreviewScrollHandler — tracks scroll position

These are added to the WKUserContentController during MPreviewView.init() and never updated. When you switch to Note B, HandlerOpen still resolves asset paths against Note A's directory.

Additionally, the JavaScript <a> click handler used event.target.getAttribute("href") which returns null when the click hits a child element inside the <a> tag (should use event.currentTarget). And MPreviewView.decidePolicyFor uses a weak var note reference that can become nil.

Proposed Fix

  1. Store handlers as properties on MPreviewView and update their note references in load(note:force:):

    public func load(note: Note, force: Bool = false) {
        guard self.note != note || force else { return }
        self.note = note
        handlerOpen.note = note
        handlerCheckbox.note = note
        handlerScroll.note = note
        // ... load HTML ...
    }
  2. Fix JavaScript click handler to use event.currentTarget instead of event.target, and add event.preventDefault() to prevent double-handling via decidePolicyFor.

  3. Add fallback in decidePolicyFor to use ViewController.shared()?.notesTableView.getSelectedNote() when the weak self.note is nil.

Files Changed

  • MPreviewView.swift — Store handler references; update in load(); fix decidePolicyFor fallback
  • index.html — Fix event.targetevent.currentTarget; add event.preventDefault()

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions