Skip to content

Address issue #313: make toolbar fully delegate-driven so Flexible Space can be dropped#473

Merged
schuyler merged 1 commit into
mainfrom
claude/jolly-shannon-89sokz
Jun 24, 2026
Merged

Address issue #313: make toolbar fully delegate-driven so Flexible Space can be dropped#473
schuyler merged 1 commit into
mainfrom
claude/jolly-shannon-89sokz

Conversation

@schuyler

Copy link
Copy Markdown
Owner

Summary

Fixes the long-standing inability to drop a Flexible Space into the document toolbar via Customize Toolbar (issue #313). Regular Space dropped fine; Flexible Space showed the green (+) on hover but was rejected mid-drag — still broken as of v3000.0.6.

Root cause. The toolbar was configured in two places at once: MPToolbarController (the delegate) already advertised Flexible Space, Space, and Separator in toolbarAllowedItemIdentifiers: (the #322 work), and MPDocument.xib separately archived nib instances of Space and Flexible Space inside <allowedToolbarItems>. In that hybrid IB-configured + delegate-driven state, AppKit reuses the single archived Flexible Space instance instead of vending a fresh one per drop, so the drop is rejected. The earlier fix was only delegate-unit-tested, which couldn't catch a defect that lives in the nib/AppKit layer.

The change (a single XIB edit, MacDown/Localization/Base.lproj/MPDocument.xib):

  • Remove <allowedToolbarItems> (the archived Space + Flexible Space nib instances) and the empty <defaultToolbarItems/>, so allowed/default/selectable items come entirely from the delegate.
  • Replace the auto-generated implicitIdentifier with a stable identifier="MPDocumentToolbar".
  • Set allowsUserCustomization="YES" and autosavesConfiguration="YES" so customizations persist across launches.

The delegate behavior is unchanged and remains covered by the existing MPToolbarControllerTests (~40 tests).

Related Issue

Related to #313

Testing

  • Automated: existing MPToolbarControllerTests continue to lock down the delegate's allowed/default/selectable identifiers (including Flexible Space, Space, Separator). The delegate is unchanged, so no test changes were needed. The actual drag-drop fix is in the nib/AppKit layer and cannot be exercised by the macOS unit-test target.
  • Independent review: the change was reviewed by a second agent — verdict approve-with-nits, no blocking issues. Confirmed the removed nib ids are referenced nowhere, the toolbar outlet still resolves, identifier is the correct persistence key, and there is no stale-config risk (nothing was ever persisted before).

Manual Testing Plan (verify on a real macOS build)

  1. Core repro: Customize Toolbar → drag Flexible Space onto the toolbar → release → confirm it actually lands (not just the green +) and pushes items left. Repeat for Space and Separator.
  2. Multiple flexible spaces: drop two or three — confirm each is an independent instance and they don't collapse/replace one another (the exact "single reused archived instance" failure mode).
  3. Default layout, fresh launch (no saved config): confirm the toolbar shows the delegate default — 11 custom items with 5 flexible spaces, in the order asserted by testDefaultIdentifiersExactOrder.
  4. Autosave round-trip: customize the toolbar, quit, relaunch → confirm the customization persists (validates the new MPDocumentToolbar identifier + autosavesConfiguration).
  5. Existing-user upgrade: because the persistence key is brand new, existing users get the default layout on first launch after upgrade — confirm that's acceptable (no empty/garbled toolbar).

Review Notes

  • Non-blocking nit from review: there is no automated regression test for the fix itself — inherent to a nib/AppKit drag-drop change; manual verification covers it.

Generated by Claude Code

…ace can be dropped

The toolbar was configured both in MPDocument.xib (archived nib instances
of Space and Flexible Space inside <allowedToolbarItems>) and via the
MPToolbarController delegate. In that hybrid state AppKit reuses the single
archived Flexible Space instance instead of vending a fresh one per drop,
so dragging Flexible Space onto the toolbar was rejected even though it
showed the green (+) on hover (regular Space happened to still work).

Remove the XIB's <allowedToolbarItems> and empty <defaultToolbarItems/> so
allowed/default/selectable items come entirely from the delegate, which
already advertises Flexible Space, Space, and Separator. Also give the
toolbar a stable identifier and enable allowsUserCustomization and
autosavesConfiguration so customizations persist across launches.

The delegate behavior is unchanged and remains covered by the existing
MPToolbarControllerTests; the drag-drop fix itself is in the nib/AppKit
layer and is verified manually.

Related to #313
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Report

Current Coverage: 62.03%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       63.50% (9151/14411) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Utility/MPMathJaxListener.m                                                61.54% (16/26)      
        -[MPMathJaxListener callbacks]                                                                                                 100.00% (5/5)       
        -[MPMathJaxListener addCallback:forKey:]                                                                                       100.00% (3/3)       
        -[MPMathJaxListener invokeCallbackForKey:]                                                                                     100.00% (8/8)       
        +[MPMathJaxListener isSelectorExcludedFromWebScript:]                                                                          0.00% (0/5)         
        +[MPMathJaxListener isKeyExcludedFromWebScript:]                                                                               0.00% (0/5)         
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Document/MPDocument.m                                                      63.61% (1631/2564)  
        MPEditorPreferenceKeyWithValueKey                                                                                              85.71% (6/7)        
        MPEditorKeysToObserve                                                                                                          100.00% (15/15)     
        __MPEditorKeysToObserve_block_invoke                                                                                           100.00% (10/10)     
        MPEditorPreferencesToObserve                                                                                                   100.00% (14/14)     
        __MPEditorPreferencesToObserve_block_invoke                                                                                    100.00% (9/9)       
        MPRectStringForAutosaveName                                                                                                    100.00% (6/6)       
        MPAreNilableStringsEqual                                                                                                       100.00% (3/3)       
        MPGetWebViewBackgroundColor                                                                                                    0.00% (0/9)         
        -[NSURL(Convert) absoluteBaseURLString]                                                                                        0.00% (0/6)         
        -[WebView(Shortcut) enclosingScrollView]                                                                                       100.00% (3/3)       
        -[MPPreferences(Hoedown) extensionFlags]                                                                                       78.57% (22/28)      
        -[MPPreferences(Hoedown) rendererFlags]                                                                                        75.00% (9/12)       
        MPGetPreviewLoadingCompletionHandler                                                                                           100.00% (30/30)     
        __MPGetPreviewLoadingCompletionHandler_block_invoke                                                                            100.00% (27/27)     
        MPScanFenceMarker                                                                                                              100.00% (28/28)     
        -[MPDocument preferences]                                                                                                      100.00% (3/3)       
        -[MPDocument markdown]                                                                                                         100.00% (3/3)       
        -[MPDocument setMarkdown:]                                                                                                     100.00% (3/3)       
        -[MPDocument html]                                                                                                             0.00% (0/3)         
        -[MPDocument toolbarVisible]                                                                                                   0.00% (0/3)         
        -[MPDocument previewVisible]                                                                                                   100.00% (3/3)       
        -[MPDocument editorVisible]                                                                                                    100.00% (3/3)       
        -[MPDocument needsHtml]                                                                                                        80.00% (4/5)        
        -[MPDocument wordCountTitleForKey:number:]                                                                                     100.00% (5/5)       
        -[MPDocument applyWordsTitle:selected:]                                                                                        100.00% (5/5)       
        -[MPDocument applyCharactersTitle:selected:]                                                                                   100.00% (6/6)       
        -[MPDocument applyCharactersNoSpacesTitle:selected:]                                                                           100.00% (6/6)       
        -[MPDocument setTotalWords:]                                                                                                   100.00% (5/5)       
        -[MPDocument setTotalCharacters:]                                                                                              100.00% (5/5)       
        -[MPDocument setTotalCharactersNoSpaces:]                                                                                      100.00% (5/5)       
        -[MPDocument setAutosaveName:]                                                                                                 100.00% (4/4)       
        -[MPDocument mathJaxRenderGeneration]                                                                                          100.00% (3/3)       
        -[MPDocument init]                                                                                                             90.91% (10/11)      
        -[MPDocument windowNibName]                                                                                                    100.00% (3/3)       
        -[MPDocument windowControllerDidLoadNib:]                                                                                      100.00% (108/108)   
        __41-[MPDocument windowControllerDidLoadNib:]_block_invoke                                                                     100.00% (3/3)       
        __41-[MPDocument windowControllerDidLoadNib:]_block_invoke.259                                                                 100.00% (15/15)     
        -[MPDocument reloadFromLoadedString]                                                                                           93.75% (15/16)      
        -[MPDocument close]                                                                                                            12.90% (4/31)       

... (3320 more lines truncated)

📊 **Full coverage report available in workflow artifacts**

@schuyler schuyler merged commit effc5ba into main Jun 24, 2026
9 checks passed
@schuyler schuyler deleted the claude/jolly-shannon-89sokz branch June 24, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants