Skip to content

Add an "Open and Save" toolbar button - #157

Closed
quattromeister wants to merge 6 commits into
SublerApp:mainfrom
quattromeister:feature/save-and-open-toolbar
Closed

quattromeister wants to merge 6 commits into
SublerApp:mainfrom
quattromeister:feature/save-and-open-toolbar

Conversation

@quattromeister

Copy link
Copy Markdown

Adds a toolbar button that saves the current document (through the same save pipeline as File > Save) and then opens the next file to work on, the same way the app's own untitled-launch Open panel does -- so working through a batch of files never requires a trip to the File menu between them.

Bundled with the initial addition were a few real bugs found in the process:

  • The button's target didn't respond to its own action selector, so clicking it silently did nothing even though it correctly showed as enabled (sendAction doesn't walk the responder chain the way toolbar validation does).
  • The button was permanently disabled -- validateUserInterfaceItem(_:) had no case at all for its action, so validation always fell through to false. Now enabled under the same condition as a plain Save.
  • The button originally opened the just-saved file in whatever app macOS registered for its type (e.g. QuickTime) rather than prompting for the next file to open -- fixed to call the same Open-panel path used at launch.
  • Renamed from "Save and Open" to "Open and Save" to match the actual order of operations, and bumped the toolbar's identifier since NSToolbar only reads default items once per identifier -- otherwise an existing saved toolbar layout would never pick up the new button.

Also includes this batch's shared GitHub Actions build check (see the note on the plugin-sources PR above about a possible duplicate landing).

quattromeister and others added 6 commits September 27, 2026 04:22
Saves the current document (same save pipeline as File > Save, so it
respects the existing save options/progress reporting) and then opens
the resulting file in its default application once the save completes.
Matches the style of the existing toolbar buttons (ButtonToolbarItem,
SF Symbol with a legacy template-image fallback).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
Compile-only verification (no signing, no tests) on a macOS runner:
checks out the repo with submodules, then xcodebuilds the Subler
target. Runs on every push and PR to any branch, so a branch shows
red/green on GitHub before anyone has to open Xcode. This is fork/CI
infrastructure, not app code -- merged into every branch that should
get build coverage, but deliberately kept off of main so main stays a
byte-for-byte mirror of upstream for clean rebasing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
Also bump the document window's toolbar identifier
(SublerDocumentToolbar -> SublerDocumentToolbar2). The button was
already wired into toolbarDefaultItemIdentifiers() when it was added,
but with autosavesConfiguration on, NSToolbar only consults the
delegate's defaults the first time it sees a given identifier -- an
install with a toolbar layout already saved from before this button
existed just keeps replaying that old saved layout forever, so the
button never actually showed up for it. Bumping the identifier makes
everyone pick up the current default set again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
The toolbar button's underlying saveAndOpen(_:) was implemented as a
different feature than the one it was meant for: it saved the current
document, then opened the just-saved file in whatever app macOS has
registered for its type (e.g. QuickTime) via NSWorkspace.shared.open(url).
That's not what "open another file without going to the File menu"
means -- the actual goal (the app already opens with a file-open prompt
on an untitled launch, via AppDelegate.applicationShouldOpenUntitledFile)
is to let the user pick the *next* file to open once they're done with
the current one.

Once the save completes, this now calls
NSDocumentController.shared.openDocument(self) instead -- the same
Open panel path used at launch -- so finishing one file and moving to
the next never requires a trip to File > Open.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
ButtonToolbarItem.validate() asks the target's
validateUserInterfaceItem(_:) whether to enable itself, but
Document.validateUserInterfaceItem(_:)'s switch had no case at all for
saveAndOpen(_:) (the button's action) -- every call fell through to
the default `return false`, so the button was permanently disabled
regardless of whether the document actually had unsaved changes.

Added a case matching save(_:)'s own condition (enabled exactly when
isDocumentEdited is true), since "Open and Save" should be available
under the same circumstances as a plain Save.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
The toolbar item's target is DocumentWindowController (not Document),
and NSApplication.sendAction only invokes an action directly on an
explicit target if that target itself responds to the selector -- it
does not fall back to walking the responder chain the way toolbar/menu
validation does (that uses target(forAction:to:from:), which does walk
the chain). DocumentWindowController had no saveAndOpen(_:) of its
own, so clicking the button silently did nothing even though it
correctly showed itself as enabled. Add a forwarding saveAndOpen(_:)
that calls doc.saveAndOpen(_:), matching the existing sendToQueue(_:)
forwarding pattern right above it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ETy3zxWgGdZPVzjN3vqbbC
@galad87 galad87 closed this Sep 27, 2026
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