Skip to content

Add sandboxed Mac App Store build variant - #56

Merged
Mario Hewardt (MarioHewardt) merged 8 commits into
mainfrom
marioh/store
Aug 18, 2026
Merged

Add sandboxed Mac App Store build variant#56
Mario Hewardt (MarioHewardt) merged 8 commits into
mainfrom
marioh/store

Conversation

@MarioHewardt

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI lite review requested due to automatic review settings August 18, 2026 14:53
@MarioHewardt

Copy link
Copy Markdown
Contributor Author

Copilot resolve the merge conflicts in this pull request

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Mac App Store–style sandboxed build variant to the ZoomIt for Mac codebase, including conditional compilation to remove non-App Store functionality and new security-scoped bookmark handling for user-selected resources.

Changes:

  • Introduces ZOOMIT_APP_STORE build flag and ZOOMIT_DISTRIBUTION build variant selection (Homebrew vs App Store) with dedicated entitlements and build-number stamping.
  • Adds security-scoped bookmark persistence/access for user-selected break sound/background and snip save directory, plumbing access through capture/export and break-timer paths.
  • Compiles out DemoType UI, hotkeys, and self-tests for the App Store surface; adds a self-test validating distribution-specific Settings tabs.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Sources/ZoomItMacCore/Settings/UserSelectedResourceAccess.swift Adds bookmark persistence + withAccess wrapper for security-scoped resource access.
Sources/ZoomItMacCore/Settings/SettingsWindowController.swift Saves bookmarks on user selection; conditionally removes DemoType settings surface for App Store builds.
Sources/ZoomItMacCore/SelfTest/SelfTestRunner.swift Skips DemoType tests in App Store builds; adds tab-surface self-test.
Sources/ZoomItMacCore/Overlay/ZoomCanvasView.swift Routes snip directory writes through updated exporter with bookmark-based access.
Sources/ZoomItMacCore/Overlay/OverlayWindowController.swift Injects UserSelectedResourceAccess into overlay/canvas creation.
Sources/ZoomItMacCore/Overlay/BreakTimerController.swift Loads background/sound via security-scoped access; adds break-timer error for access failures.
Sources/ZoomItMacCore/Hotkeys/HotkeyService.swift Compiles out DemoType hotkeys/commands for App Store builds.
Sources/ZoomItMacCore/Core/ModeCoordinator.swift Plumbs UserSelectedResourceAccess; compiles out DemoType controller/commands for App Store builds.
Sources/ZoomItMacCore/Core/AppCommand.swift Compiles out DemoType commands for App Store builds.
Sources/ZoomItMacCore/Capture/SnipController.swift Passes UserSelectedResourceAccess into image export pipeline.
Sources/ZoomItMacCore/Capture/PanoramaController.swift Passes UserSelectedResourceAccess into image export pipeline.
Sources/ZoomItMacCore/Capture/ImageExporter.swift Adds bookmark-aware directory writes and Boolean success signaling with fallback to Save panel.
Sources/ZoomItMacCore/App/DistributionChannel.swift Adds compile-time DistributionChannel.isAppStore flag.
Sources/ZoomItMacCore/App/DemoTypeController.swift Compiles out DemoType implementation for App Store builds.
Sources/ZoomItMacCore/App/AppDelegate.swift Creates and injects UserSelectedResourceAccess; updates overlay/mode wiring.
Sources/ZoomItMacCore/App/AppController.swift Passes UserSelectedResourceAccess into Settings window wiring.
Scripts/ZoomIt-AppStore.entitlements Adds sandbox + bookmarks + mic/camera entitlements for App Store variant.
Scripts/build-app.sh Adds distribution selection, compiler flags, entitlements switching, and independent build-number stamping.
README.md Documents App Store compiler-condition self-tests and build variants/usage.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Sources/ZoomItMacCore/Capture/ImageExporter.swift
Comment thread Sources/ZoomItMacCore/Settings/UserSelectedResourceAccess.swift
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 18, 2026 15:01
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
# Conflicts:
#	Sources/ZoomItMacCore/Core/ModeCoordinator.swift
#	Sources/ZoomItMacCore/Hotkeys/HotkeyService.swift
#	Sources/ZoomItMacCore/SelfTest/SelfTestRunner.swift
#	Sources/ZoomItMacCore/Settings/SettingsWindowController.swift

Co-authored-by: MarioHewardt <15442480+MarioHewardt@users.noreply.github.com>
Copilot AI and others added 3 commits August 18, 2026 15:03
Co-authored-by: MarioHewardt <15442480+MarioHewardt@users.noreply.github.com>
Co-authored-by: MarioHewardt <15442480+MarioHewardt@users.noreply.github.com>
Co-authored-by: MarioHewardt <15442480+MarioHewardt@users.noreply.github.com>

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Copilot resolve the merge conflicts in this pull request

Resolved the merge conflicts with origin/main in d6f3ce0 and pushed the updates. Follow-up review fixes are included in 1b77c7b and 1f32ec1.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Comment on lines +331 to +335
try userSelectedResourceAccess.withAccess(
to: .breakSound,
legacyPath: settings.breakSoundFile
) { url in
NSSound(contentsOf: url, byReference: false)?.play()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BreakTimerView now takes a userSelectedResourceAccess: UserSelectedResourceAccess in its initializer, and the controller passes its own instance when constructing the view (commit 84c5899). Note: the push to marioh/store was rejected by repository ruleset protection ("Cannot update this protected ref"), so the commit exists locally but could not be pushed.

Copilot AI review requested due to automatic review settings August 18, 2026 15:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Suppressed comments (1)

Sources/ZoomItMacCore/Capture/DemoMirrorController.swift:468

  • MainActor.assumeIsolated in the Timer callback can trap at runtime if the timer ever fires off the main actor (e.g. if scheduled on a non-main run loop). You can avoid the runtime precondition by moving the self access entirely into a Task { @MainActor … }, which is safe regardless of which thread the timer callback runs on.
        trackingTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in
            MainActor.assumeIsolated {
                guard let self else { return }
                Task { @MainActor in
                    await self.refreshTrackedWindow(source: source)

Co-authored-by: MarioHewardt <15442480+MarioHewardt@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Sources/ZoomItMacCore/Capture/ImageExporter.swift:75

  • In the App Store build, snipSaveDirectory == "" (meaning “Documents”) will always lack a security-scoped bookmark. writeToDirectory currently turns that into an error alert, then callers fall back to showing a Save panel anyway—so users will see a confusing alert before the expected Save dialog when they enable “save to directory” without explicitly choosing a folder. It would be better to treat an empty directory as “no configured directory” for App Store builds and immediately return false to trigger the Save panel without an alert.
    @discardableResult
    static func writeToDirectory(
        _ image: CGImage,
        directoryPath: String,
        userSelectedResourceAccess: UserSelectedResourceAccess

Sources/ZoomItMacCore/Settings/UserSelectedResourceAccess.swift:84

  • On non‑App Store builds, the generic catch block swallows any error from the bookmark path and then falls back to the legacy path. This can cause operation to be executed twice on failures (bookmark URL first, legacy URL second), which is risky for non-idempotent operations like writing files.
            } catch {
                if DistributionChannel.isAppStore {
                    throw error
                }
            }

@chakrik73
chakrik73 self-requested a review August 18, 2026 17:27
@MarioHewardt
Mario Hewardt (MarioHewardt) merged commit a3e6501 into main Aug 18, 2026
4 checks passed
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.

4 participants