Skip to content

Implement onboarding, update management, and version 2.1.0 enhancements#39

Open
vordenken wants to merge 44 commits into
mainfrom
feature/v2.1.0
Open

Implement onboarding, update management, and version 2.1.0 enhancements#39
vordenken wants to merge 44 commits into
mainfrom
feature/v2.1.0

Conversation

@vordenken

@vordenken vordenken commented Jun 16, 2026

Copy link
Copy Markdown
Owner

🚀 Release v2.1.0 — Onboarding & Automated Releases

This PR promotes v2.1.0 from beta to stable after 13 beta releases and extensive testing.


✨ What's New

🎨 Onboarding Flow

First-time users are now guided through a 3-step setup:

  1. Welcome — Introduction to AutoPiP with quick links
  2. Features — Overview of automatic PiP, scroll-PiP, keyboard shortcut, and site control
  3. Updates — Configure update preferences (auto-check, auto-download, beta channel) before opening Safari

State is persisted via UserDefaults (OnboardingCompleted flag) — the flow only runs once per user.

⚙️ Configurable Update Settings

Update preferences are now first-class settings, exposed via the onboarding flow and the main app view:

  • ✅ Automatically check for updates
  • ✅ Automatically download updates (gated by auto-check)
  • ✅ Include beta updates — opt in to test upcoming features

All settings are wired through UpdateController to the underlying Sparkle SPUUpdater.


🔧 Under the Hood

🤖 Automated Builds & Releases

Releases are now fully automated via GitHub Actions (.github/workflows/build-release.yml):

  • semver.txt is the single source of truth for version + changelog
  • Every push to feature/* → auto-incremented v2.1.0-beta{N} (never overwritten)
  • Merge to main with changed semver.txt → stable v2.1.0 release
  • Auto-builds DMG, signs with code certificate + Sparkle EdDSA, publishes GitHub Release, updates appcast.xml
  • Bot-authored commits are skipped to prevent infinite loops
  • Concurrency control cancels in-progress builds when a new push arrives

🧪 Beta Release Channel

Users can now opt in to beta updates through Sparkle's channel mechanism (allowedChannels returns ["beta"] when BetaUpdatesEnabled is true). The appcast marks beta releases with a visible warning banner.

🐛 Bugfix: Keyboard PiP small in corner

Fixed a bug where the keyboard shortcut (⌥P) opened PiP at the video element's CSS-rendered size instead of its intrinsic dimensions. The toggle now prefers the W3C requestPictureInPicture() API and falls back to the WebKit API on failure. This affected YouTube's mini-player (which renders the <video> element very small) and other CSS-scaled video players.


🧪 Testing

This release has been validated through 13 beta releases with no regressions reported. Manual test plan:

  • Fresh install → onboarding flow appears, completes successfully
  • Onboarding toggles persist after quit/relaunch
  • Main view reflects Safari extension enabled/disabled state
  • Toggling beta channel makes v2.1.0 stable visible after next check
  • Keyboard shortcut opens PiP at correct (intrinsic) size
  • Update check finds v2.1.0 stable when upgrading from v2.0.0

📝 Notes

  • Beta-Channel users will need to disable beta updates in settings (or wait for v2.1.0-beta{N+1} to be released, which won't happen) to receive the stable v2.1.0.
  • appcast.xml on main will be auto-updated by the workflow after merge — the beta banner will be removed and the sparkle:channel will be set to stable.
  • No database migrations or data format changes — drop-in upgrade from v2.0.0.

✅ Checklist

  • Version bumped in semver.txt, manifest.json, and Xcode project
  • Changelog entries added
  • Beta tested (beta1–beta13)
  • No new TODOs / FIXMEs introduced
  • No breaking changes for existing users

Summary by Sourcery

Introduce a guided onboarding flow, configurable update channel and settings, and automated build-and-release pipeline for the AutoPiP v2.1.0 release.

New Features:

  • Add a three-step onboarding flow that runs on first launch to introduce AutoPiP, explain key features, and configure update preferences before opening Safari.
  • Expose update preferences (auto-check, auto-download, beta channel) in both the onboarding flow and the main app view, wired through the update controller to Sparkle.
  • Introduce a beta update channel selection backed by Sparkle’s channel mechanism so users can opt in to pre-release builds.

Bug Fixes:

  • Fix keyboard shortcut PiP behavior so it uses intrinsic video dimensions (via the standard Picture-in-Picture API) instead of CSS-rendered size, preventing tiny PiP windows on sites like YouTube.

Enhancements:

  • Redesign the main app HTML/CSS/JS to support multiple pages, shared styling, and in-app update controls, including version display and Safari state messaging.
  • Extend the update controller to manage automatic check/download options and beta channel toggling via Sparkle, persisting state in user defaults.
  • Update the appcast feed to include 2.1.0 beta entries and normalized Sparkle version metadata for historical releases.
  • Add default enabling of automatic update checks in the app’s Info.plist.

Build:

  • Add a GitHub Actions workflow that automates versioning from semver.txt, builds and signs the app, creates DMG artifacts, tags and publishes GitHub releases, and updates the Sparkle appcast across branches.
  • Introduce semver.txt as the single source of truth for app versioning and per-release changelogs used by the CI pipeline.

CI:

  • Configure GitHub Actions to gate main-branch builds on semver.txt changes, auto-increment beta tags for feature branches, skip bot-authored commits, and manage build concurrency.

Documentation:

  • Expand the README with Gatekeeper installation instructions, update guidance, and a link to build/release docs.
  • Add BUILD.md documenting the build-from-source process, release workflow, semver.txt format, and required GitHub secrets and app setup.
  • Add a SECURITY.md describing supported versions and responsible vulnerability reporting.
  • Add GitHub issue templates for bug reports and feature requests, and a pull request template to standardize contributions.

Chores:

  • Expose the update controller from the app delegate so it can be controlled from the WebView onboarding and main UI.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a redesigned onboarding flow for initial setup and configuration.
    • Added configurable update preferences (auto-check, auto-download, and beta channel opt-in).
    • Enabled automatic update notifications.
  • Bug Fixes

    • Improved Picture-in-Picture compatibility by preferring the modern PiP request API with a fallback for older environments.
  • Documentation

    • Updated README installation/update guidance and added BUILD and SECURITY documentation.

vordenken and others added 29 commits April 14, 2026 22:14
Update version to 2.1.0 in manifest and project files
Expose update controller in AppDelegate for onboarding
Enable automatic update checks in Info.plist
Implement onboarding pages for user guidance
Enhance main view with update settings and controls
Refactor update controller to manage beta updates
Handle onboarding completion and settings in ViewController
Create build and release documentation
Establish security policy for vulnerability reporting
Update appcast for new versioning scheme
Add Renovate configuration for dependency management
Set version to 2.1.0 in semver file
@sourcery-ai

sourcery-ai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements a three-step onboarding flow with persisted state, exposes and wires update/beta-channel settings through a new UpdateController API into the WebView UI, introduces a GitHub Actions-based automated build-and-release pipeline around semver.txt and Sparkle, and fixes the keyboard PiP toggle to use the W3C PiP API to avoid CSS-sized PiP windows.

Sequence diagram for onboarding flow and update settings persistence

sequenceDiagram
    actor User
    participant WebViewHTMLJS as WebView_HTML_JS
    participant WKWebView
    participant ViewController
    participant UpdateController
    participant SPUUpdater
    participant SFSafariApplication

    User->>WKWebView: Launch AutoPiP app
    WKWebView->>ViewController: webView(_:didFinish:)
    ViewController->>WKWebView: evaluateJavaScript("setVersion")
    ViewController->>WKWebView: evaluateJavaScript("startOnboarding()")

    User->>WebViewHTMLJS: Click "Done – Open Safari"
    WebViewHTMLJS->>WebViewHTMLJS: Collect onb-auto-check/onb-auto-download/onb-beta
    WebViewHTMLJS->>WKWebView: postMessage("onboarding-done:" + JSON)
    WKWebView->>ViewController: userContentController(_:didReceive:)
    ViewController->>ViewController: handleOnboardingDone(jsonString)
    ViewController->>UpdateController: set automaticallyChecksForUpdates
    ViewController->>UpdateController: set automaticallyDownloadsUpdates
    ViewController->>UpdateController: set isBetaUpdatesEnabled
    UpdateController->>SPUUpdater: automaticallyChecksForUpdates / automaticallyDownloadsUpdates
    UpdateController->>SPUUpdater: resetUpdateCycleAfterShortDelay()

    ViewController->>ViewController: UserDefaults["OnboardingCompleted"] = true
    ViewController->>SFSafariApplication: showPreferencesForExtension
    SFSafariApplication-->>ViewController: completion(error?)
    ViewController->>SFSafariApplication: openApplication (fallback if error)
    ViewController->>NSApplication: terminate(nil)
Loading

Sequence diagram for update and beta channel setting changes in main view

sequenceDiagram
    actor User
    participant WebViewHTMLJS as WebView_HTML_JS
    participant WKWebView
    participant ViewController
    participant UpdateController
    participant UpdaterDelegate
    participant SPUUpdater

    User->>WKWebView: Reopen AutoPiP app
    WKWebView->>ViewController: webView(_:didFinish:)
    ViewController->>WKWebView: evaluateJavaScript("setVersion")
    ViewController->>ViewController: showMainView()
    ViewController->>WKWebView: evaluateJavaScript("show(enabled,useSettings)")
    ViewController->>UpdateController: read automaticallyChecksForUpdates / automaticallyDownloadsUpdates / isBetaUpdatesEnabled
    ViewController->>WKWebView: evaluateJavaScript("setUpdateSettings(settings)")

    User->>WebViewHTMLJS: Toggle "Include beta updates"
    WebViewHTMLJS->>WKWebView: postMessage("set-beta:true")
    WKWebView->>ViewController: userContentController(_:didReceive:)
    ViewController->>UpdateController: isBetaUpdatesEnabled = true
    UpdateController->>UserDefaults: set(BetaUpdatesEnabled,true)
    UpdateController->>SPUUpdater: resetUpdateCycleAfterShortDelay()

    SPUUpdater->>UpdaterDelegate: allowedChannels(for:)
    UpdaterDelegate-->>SPUUpdater: Set(["beta"]) (when BetaUpdatesEnabled)
Loading

Sequence diagram for keyboard PiP toggle using W3C API with WebKit fallback

sequenceDiagram
    actor User
    participant ContentScript as content_js
    participant VideoElement as HTMLVideoElement
    participant BrowserPiP as Browser_PiP_System

    User->>ContentScript: Press keyboard shortcut (⌥P)
    ContentScript->>ContentScript: togglePiP()
    alt PiP currently active
        ContentScript->>ContentScript: disablePiP()
    else No PiP active
        ContentScript->>VideoElement: check typeof video.requestPictureInPicture
        alt requestPictureInPicture available
            ContentScript->>VideoElement: requestPictureInPicture()
            VideoElement-->>BrowserPiP: Open PiP at intrinsic size
            VideoElement-->>ContentScript: Promise reject on error
            ContentScript->>ContentScript: catch(error)
            ContentScript->>ContentScript: setWebkitPresentationMode(video,"picture-in-picture")
        else Only WebKit API available
            ContentScript->>ContentScript: setWebkitPresentationMode(video,"picture-in-picture")
        end
    end
Loading

File-Level Changes

Change Details Files
Add a page-based onboarding and main view UI with shared styling, support links, and integrated update settings, backed by WebView–Swift message handling and persisted onboarding state.
  • Replace the simple single-page HTML with multiple page containers for onboarding steps and the main settings view, including support links and version labels.
  • Refactor CSS into shared page, typography, toggle, settings list, and state visibility styles to support the multi-page layout.
  • Extend the popup script to manage page navigation, surface version text, synchronize update toggles, and send structured commands back to Swift via WKScriptMessageHandler.
  • Update the view controller to inject the app version, decide between onboarding and main view based on a UserDefaults flag, and handle all new message commands for update settings, beta toggle, support links, and onboarding completion before opening Safari and quitting.
AutoPiP/Resources/Style.css
AutoPiP/Resources/Script.js
AutoPiP/Resources/Base.lproj/Main.html
AutoPiP/ViewController.swift
AutoPiP/AppDelegate.swift
Expose Sparkle update and beta-channel configuration through UpdateController, enable automatic checks, and connect those settings to the UI and appcast feed.
  • Introduce an SPUUpdaterDelegate implementation to return the beta channel when a BetaUpdatesEnabled UserDefaults flag is set.
  • Add computed properties on UpdateController for automatically checking and downloading updates and for enabling beta updates, ensuring dependent flags stay consistent and resetting the Sparkle update cycle when the beta state changes.
  • Enable Sparkle’s automatic update checks at the app level and surface update settings into the WebView via JSON from the view controller.
  • Expand appcast.xml with historical beta 2.1.0 entries using build-number-based sparkle:version and sparkle:shortVersionString for all releases.
AutoPiP/UpdateController.swift
AutoPiP/Info.plist
appcast.xml
Fix the keyboard Picture-in-Picture toggle to use intrinsic video dimensions by preferring the modern W3C API and falling back to WebKit when needed.
  • Change the PiP toggle handler in the content script to call video.requestPictureInPicture when available, with error handling and a fallback to webkitSetPresentationMode.
  • Improve logging and exception handling around PiP activation failures to avoid silent errors.
AutoPiP Extension/Resources/content.js
Introduce a fully automated build-and-release pipeline that derives versioning and changelog from semver.txt, signs artifacts, updates the Sparkle appcast, and publishes GitHub releases.
  • Add a GitHub Actions workflow that gates builds on semver.txt changes on main, auto-increments beta tags for feature branches, sets MARKETING_VERSION/CURRENT_PROJECT_VERSION and extension manifest version, builds and signs a DMG, generates Sparkle EdDSA signatures, updates appcast.xml, and creates GitHub releases with changelog-based notes.
  • Implement concurrency controls, bot-actor skipping, and optional GitHub App token support for pushing appcast changes to protected branches.
  • Document build, release, signing, and GitHub App setup in a new BUILD.md and define semver.txt as the single source of truth for versions and changelog entries.
  • Introduce semver.txt, Renovate configuration, and update Xcode project / SwiftPM resolution files as part of the new release process.
.github/workflows/build-release.yml
BUILD.md
semver.txt
AutoPiP.xcodeproj/project.pbxproj
AutoPiP.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
renovate.json
Refresh documentation and repo metadata for CI, security, and contribution flow, and bump the extension manifest version for v2.1.0.
  • Update the README with clearer installation and update instructions, add a build-status badge, and link to BUILD.md for build/release details.
  • Add SECURITY policy and GitHub issue/PR templates for bugs, feature requests, and standardized pull requests, including disabling blank issues.
  • Bump the Safari extension manifest version to 2.1.0 to align with the new release.
README.md
SECURITY.md
.github/ISSUE_TEMPLATE/bug_report.yml
.github/ISSUE_TEMPLATE/feature_request.yml
.github/ISSUE_TEMPLATE/config.yml
.github/pull_request_template.md
AutoPiP Extension/Resources/manifest.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

AutoPiP 2.1.0 introduces a multi-page onboarding flow with configurable Sparkle update settings (auto-check, auto-download, beta channel), updates the PiP toggle to prefer the W3C requestPictureInPicture API, adds a full GitHub Actions macOS release pipeline with EdDSA appcast signing, and adds community health files (issue templates, SECURITY.md, Renovate config).

Changes

Onboarding + Update Settings Feature

Layer / File(s) Summary
Sparkle update channel wiring and controller properties
AutoPiP/UpdateController.swift, AutoPiP/AppDelegate.swift, AutoPiP/Info.plist, AutoPiP.xcodeproj/.../Package.resolved
UpdaterDelegate conditionally allows the "beta" Sparkle channel from UserDefaults. UpdateController gains automaticallyChecksForUpdates, automaticallyDownloadsUpdates, and isBetaUpdatesEnabled computed properties. AppDelegate.updateController is made module-visible. Info.plist enables automatic checks. Sparkle bumped to 2.9.3.
ViewController onboarding gate and message routing
AutoPiP/ViewController.swift
webView(_:didFinish:) injects app version, checks the onboarding completion flag, and routes to either startOnboarding() or showMainView(). Message handler expanded for onboarding-done (JSON parse + persist + quit), open-url, and update-setting commands forwarded to UpdateController.
Onboarding HTML, JS controller, and CSS theme
AutoPiP/Resources/Base.lproj/Main.html, AutoPiP/Resources/Script.js, AutoPiP/Resources/Style.css
Main.html replaces the single-screen UI with three onboarding pages and a reworked main view with toggle switches. Script.js adds showPage, startOnboarding, setVersion, setUpdateSettings, and full DOMContentLoaded event wiring posting webkit.messageHandlers.controller messages. Style.css introduces CSS variables, dark-mode overrides, .btn, .toggle switch, settings rows, feature list, and state-visibility rules.
W3C requestPictureInPicture preference
AutoPiP Extension/Resources/content.js
togglePiP() attempts video.requestPictureInPicture() first; on failure falls back to webkitSetPresentationMode. Environments without the W3C method retain the direct webkit fallback.
Version bump to 2.1.0
AutoPiP Extension/Resources/manifest.json, AutoPiP.xcodeproj/project.pbxproj
MARKETING_VERSION updated from 2.0.0 to 2.1.0 across all Xcode build configurations and the extension manifest.

GitHub Actions Release Pipeline

Layer / File(s) Summary
Workflow triggers, gating job, and versioning
.github/workflows/build-release.yml (triggers, paths-ignore, gating job, version extraction)
Fires on main/feature/* pushes and manual dispatch. A gating job skips builds when semver.txt is unchanged on main or the commit is from github-actions[bot]. The release job extracts version, computes stable/beta tag with auto-incremented suffix, sets prerelease flag, and extracts the matching changelog block.
Code signing, Xcode archive, and DMG creation
.github/workflows/build-release.yml (certificate import, archive, create-dmg, keychain cleanup)
Decodes P12 into a temporary keychain, patches Xcode/manifest versions via sed, resolves Swift packages, archives the app, builds a DMG with create-dmg, and cleans up the keychain unconditionally.
Sparkle EdDSA signing, appcast update, and GitHub Release
.github/workflows/build-release.yml (Sparkle tools, DMG signing, appcast generation, release creation, artifact upload, appcast push)
Downloads Sparkle tools, signs the DMG, generates/deduplicates an appcast item, assembles release notes with beta banner, creates the GitHub Release, pushes appcast.xml back to the working branch and main, and uploads the DMG artifact.
semver.txt, appcast.xml entries, and BUILD.md
semver.txt, appcast.xml, BUILD.md
semver.txt populated with changelogs for versions 0.4–2.1.0. appcast.xml gains two 2.1.0-beta items and updated sparkle:version/sparkle:shortVersionString on all prior enclosures. BUILD.md documents build steps, semver format, release workflow rules, and required secrets.

Community Health and Repository Config

Layer / File(s) Summary
Issue templates, PR template, SECURITY.md, and Renovate
.github/ISSUE_TEMPLATE/*, .github/pull_request_template.md, SECURITY.md, renovate.json
Structured bug_report.yml and feature_request.yml forms, blank issues disabled, PR checklist template, SECURITY.md with supported versions and responsible disclosure, and Renovate recommended preset.
README updates
README.md
Adds GitHub Actions build badge, replaces Quick Start with Gatekeeper workaround and DMG installation steps, updates Sparkle note, and adds a Building & Releasing section linking to BUILD.md.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(173, 216, 230, 0.5)
    Note over WKWebView,UpdateController: App launch onboarding path
  end
  participant WKWebView
  participant ViewController
  participant UpdateController
  participant SafariExtensionState

  WKWebView->>ViewController: webView(_:didFinish:)
  ViewController->>WKWebView: setVersion(v) via JS
  alt Onboarding not complete
    ViewController->>WKWebView: startOnboarding() via JS
    WKWebView->>ViewController: webkit message: onboarding-done JSON
    ViewController->>UpdateController: set auto-check, auto-download, beta channel
    ViewController->>ViewController: persist onboarding flag to UserDefaults
    ViewController->>ViewController: openSafariAndQuit()
  else Onboarding complete
    ViewController->>SafariExtensionState: getStateOfSafariExtension (async)
    SafariExtensionState-->>ViewController: enabled flag
    ViewController->>WKWebView: show(enabled) via JS
    ViewController->>UpdateController: read settings
    ViewController->>WKWebView: setUpdateSettings(settings) via JS
  end
  WKWebView->>ViewController: webkit message: set-auto-check / set-beta / check-for-updates
  ViewController->>UpdateController: mutate properties / checkForUpdates()
Loading
sequenceDiagram
  rect rgba(144, 238, 144, 0.5)
    Note over Workflow,GitHubRelease: CI release pipeline
  end
  participant Workflow
  participant Keychain
  participant Xcode
  participant SparkleTools
  participant appcast as appcast.xml
  participant GitHubRelease

  Workflow->>Workflow: gating job checks semver.txt changed
  Workflow->>Keychain: import P12 into temp keychain
  Workflow->>Xcode: patch versions via sed, archive app, create DMG
  Workflow->>SparkleTools: sign_update DMG → EdDSA signature
  SparkleTools-->>Workflow: edSignature
  Workflow->>appcast: insert new item, deduplicate by shortVersionString
  Workflow->>GitHubRelease: create release + upload DMG
  Workflow->>appcast: git push to branch + main
  Workflow->>Keychain: delete temp keychain (always)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A rabbit hops through onboarding gates,
Checking for betas at configurable rates,
The DMG is signed, the appcast is neat,
With EdDSA hops and a Sparkle heartbeat!
pip pip hooray — the release is complete! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly reflects the main objectives: implementing onboarding flow, update management system, and version 2.1.0 release enhancements, which are all prominent in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feature/v2.1.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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 3 issues, and left some high level feedback:

  • There are several hard-coded UserDefaults keys ("OnboardingCompleted", "BetaUpdatesEnabled", etc.) scattered across ViewController, the updater delegate, and JavaScript; consider centralizing these keys in a single Swift enum/struct (and mirroring them in JS constants) to avoid typos and make future changes safer.
  • The string-based message protocol between the web view and ViewController (e.g. "set-auto-check:true", "open-url:" + href, "onboarding-done:" + JSON) is starting to get complex; you might want to move to a small structured JSON message format with type/payload` fields to make parsing more robust and easier to extend.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There are several hard-coded UserDefaults keys (`"OnboardingCompleted"`, `"BetaUpdatesEnabled"`, etc.) scattered across ViewController, the updater delegate, and JavaScript; consider centralizing these keys in a single Swift enum/struct (and mirroring them in JS constants) to avoid typos and make future changes safer.
- The string-based message protocol between the web view and `ViewController` (e.g. `"set-auto-check:true"`, `"open-url:" + href`, `"onboarding-done:" + JSON) is starting to get complex; you might want to move to a small structured JSON message format with `type`/`payload` fields to make parsing more robust and easier to extend.

## Individual Comments

### Comment 1
<location path="AutoPiP/Resources/Script.js" line_range="118-120" />
<code_context>
+        webkit.messageHandlers.controller.postMessage("check-for-updates");
+    });
+
+    document.getElementById('auto-check-toggle').addEventListener('change', function() {
+        webkit.messageHandlers.controller.postMessage("set-auto-check:" + this.checked);
+        var dl = document.getElementById('auto-download-toggle');
+        dl.disabled = !this.checked;
+        if (!this.checked) dl.checked = false;
</code_context>
<issue_to_address>
**issue (bug_risk):** Keep native `autoDownload` flag in sync when disabling it via the `auto-check` toggle.

In this handler you disable and uncheck `auto-download-toggle` only in the DOM, but you never send `set-auto-download:false` to the native side as is done in onboarding. That leaves Sparkle’s `automaticallyDownloadsUpdates` still `true` after a user turns off auto-checking.

You can align behavior by also posting the native message when auto-check is turned off:
```js
document.getElementById('auto-check-toggle').addEventListener('change', function() {
    webkit.messageHandlers.controller.postMessage("set-auto-check:" + this.checked);
    var dl = document.getElementById('auto-download-toggle');
    dl.disabled = !this.checked;
    if (!this.checked) {
        dl.checked = false;
        webkit.messageHandlers.controller.postMessage("set-auto-download:false");
    }
});
```
</issue_to_address>

### Comment 2
<location path="BUILD.md" line_range="55" />
<code_context>
+### GitHub App for Branch Protection
+
+If `main` has branch protection, the workflow needs a GitHub App to push the appcast update. Create a GitHub App with **Contents: Read & Write** permission, install it on the repo, then:
+- Add variable `CLienT_ID` with the App's client ID
+- Add secret `APP_PRIVATE_KEY` with the App's private key
+- Add the App to the branch protection bypass list
</code_context>
<issue_to_address>
**issue (typo):** Typo in variable name: `CLienT_ID` should be `CLIENT_ID` for consistency

Below you use `CLIENT_ID` in the secrets section. Please update this bullet to `CLIENT_ID` as well so the variable name is consistent and avoids configuration confusion.

```suggestion
- Add variable `CLIENT_ID` with the App's client ID
```
</issue_to_address>

### Comment 3
<location path="BUILD.md" line_range="49" />
<code_context>
+- Sets the version in the Xcode project and `manifest.json`
+- Builds, archives, and creates a DMG
+- Signs the DMG with the code signing certificate and Sparkle EdDSA
+- Creates a git tag and GitHub Release with changelog + installation instructions
+- Updates `appcast.xml` (with changelog as `<description>`) on the working branch and `main`
+
</code_context>
<issue_to_address>
**nitpick (typo):** Consider capitalizing "Git" as a proper noun

Here, "git" should be capitalized as "Git" to match its proper name and stay consistent with "GitHub" in the same sentence.

```suggestion
- Creates a Git tag and GitHub Release with changelog + installation instructions
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread AutoPiP/Resources/Script.js
Comment thread BUILD.md Outdated
Comment thread BUILD.md Outdated
vordenken and others added 3 commits June 16, 2026 21:40
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
.github/workflows/build-release.yml (1)

18-18: Pin GitHub Actions to commit SHAs for supply-chain security.

These actions use tag-pinning (@v*) instead of immutable commit SHAs, which increases supply-chain attack risk. Consider enabling Renovate's helpers:pinGitHubActionDigests preset (or upgrading to config:best-practices) to automatically pin actions to full-length commit SHAs with version comments for maintainability.

Lines: 18, 68, 74, 341, 400

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-release.yml at line 18, The GitHub Actions in this
workflow are pinned to semantic version tags (such as `@v6` in
actions/checkout@v6) instead of immutable commit SHAs, which introduces
supply-chain security risks. Replace each action version tag reference with the
full commit SHA of that action version, and include the version tag as a comment
for maintainability (for example, replace `@v6` with @<full-commit-sha> # v6).
Alternatively, enable Renovate's helpers:pinGitHubActionDigests preset or
upgrade to config:best-practices to automatically manage this pinning going
forward.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/ISSUE_TEMPLATE/config.yml:
- Line 1: In the `.github/ISSUE_TEMPLATE/config.yml` file, rename the
configuration key from `blank_issues` to `blank_issues_enabled`. GitHub's issue
template configuration schema uses `blank_issues_enabled` as the correct key
name to control whether blank issues are available in the issue template
chooser. Update this key name to match the expected schema.

In @.github/workflows/build-release.yml:
- Around line 8-10: The workflow-level permissions are granting write access to
all jobs via `contents: write`, which violates the principle of least privilege.
Remove the workflow-level `contents: write` permission to revert to the default
read-only state, then add a job-level permissions section specifically to the
`build-and-release` job that grants `contents: write` only to that job. This
ensures the `check` job and any other jobs retain read-only permissions while
only the `build-and-release` job has the necessary write access.
- Around line 124-130: The tag existence check in the workflow hard-fails if a
tag already exists, which prevents idempotent reruns when a release partially
succeeds but a later step fails. Instead of exiting with an error when the tag
is detected, modify the logic to handle the existing tag case gracefully by
updating or reconciling the existing release and appcast rather than aborting.
This allows subsequent workflow reruns to recover from failures and complete the
release process without being blocked by the previously-created tag.
- Around line 24-33: Refactor the GitHub Actions workflow to prevent template
injection and spoofing vulnerabilities by moving GitHub context expressions from
direct `run:` script expansion to the `env:` section. Replace the bot detection
logic that uses `github.event.head_commit.author.name` (which is user-controlled
and spoofable) with `github.actor` instead. Define environment variables in the
`env:` block above the `run:` step, then reference them as shell variables
within the script. Apply this same hardening pattern at lines 93 and 417 where
similar direct template expansion and bot detection logic exists.

In `@AutoPiP/UpdateController.swift`:
- Around line 30-38: The setters for automaticallyChecksForUpdates and
automaticallyDownloadsUpdates in UpdateController do not enforce the constraint
that auto-download must be gated by auto-check (auto-download cannot be true if
auto-check is false). Update the setter for automaticallyChecksForUpdates to set
automaticallyDownloadsUpdates to false whenever auto-check is disabled, and
update the setter for automaticallyDownloadsUpdates to prevent enabling
auto-download when auto-check is false (either by rejecting the change or
forcing auto-check to true). This ensures the dependency is enforced at the
controller layer and prevents callers from creating invalid states.

In `@BUILD.md`:
- Line 55: Fix the variable name typo in the GitHub App setup documentation at
line 55 of BUILD.md. The variable name is currently written as `CLienT_ID` with
inconsistent capitalization, which will cause workflow configuration to fail.
Correct this to the proper constant naming convention `CLIENT_ID` to match the
actual variable name used in the application configuration.

In `@README.md`:
- Line 40: The update note in the README at the "Updating" section states that
Sparkle automatically checks for updates once per day as unconditional behavior.
Since auto-update checks are now user-configurable via a toggle, revise this
sentence to clarify that automatic daily checks only occur when the user has
enabled this feature. Reference the new toggle in the statement to make it clear
that users can control whether this automatic checking behavior is active.

---

Nitpick comments:
In @.github/workflows/build-release.yml:
- Line 18: The GitHub Actions in this workflow are pinned to semantic version
tags (such as `@v6` in actions/checkout@v6) instead of immutable commit SHAs,
which introduces supply-chain security risks. Replace each action version tag
reference with the full commit SHA of that action version, and include the
version tag as a comment for maintainability (for example, replace `@v6` with
@<full-commit-sha> # v6). Alternatively, enable Renovate's
helpers:pinGitHubActionDigests preset or upgrade to config:best-practices to
automatically manage this pinning going forward.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a48e89bb-c91e-48e8-8bc8-32b3bd951291

📥 Commits

Reviewing files that changed from the base of the PR and between b8fd22e and 1fb2e6f.

📒 Files selected for processing (22)
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/pull_request_template.md
  • .github/workflows/build-release.yml
  • AutoPiP Extension/Resources/content.js
  • AutoPiP Extension/Resources/manifest.json
  • AutoPiP.xcodeproj/project.pbxproj
  • AutoPiP.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • AutoPiP/AppDelegate.swift
  • AutoPiP/Info.plist
  • AutoPiP/Resources/Base.lproj/Main.html
  • AutoPiP/Resources/Script.js
  • AutoPiP/Resources/Style.css
  • AutoPiP/UpdateController.swift
  • AutoPiP/ViewController.swift
  • BUILD.md
  • README.md
  • SECURITY.md
  • appcast.xml
  • renovate.json
  • semver.txt

Comment thread .github/ISSUE_TEMPLATE/config.yml Outdated
Comment thread .github/workflows/build-release.yml Outdated
Comment thread .github/workflows/build-release.yml Outdated
Comment thread .github/workflows/build-release.yml
Comment thread AutoPiP/UpdateController.swift
Comment thread BUILD.md Outdated
Comment thread README.md
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

❌ Failed to create PR with unit tests: AGENT_CHAT: Failed to open pull request

@vordenken

Copy link
Copy Markdown
Owner Author

@sourcery-ai review

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The GitHub Actions trigger uses paths-ignore: ['.github/**'] while the comment above says “this workflow itself still trigger a build”; if you want changes to workflow files to trigger builds, remove .github/** from paths-ignore or narrow it (e.g. only ignore .github/ISSUE_TEMPLATE/**).
  • The WKWebView evaluateJavaScript("setUpdateSettings(...)" ) call in showMainView() runs outside of a DispatchQueue.main.async block, unlike the extension state call; consider dispatching it explicitly to the main thread to avoid any potential threading issues with WKWebView.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The GitHub Actions trigger uses `paths-ignore: ['.github/**']` while the comment above says “this workflow itself still trigger a build”; if you want changes to workflow files to trigger builds, remove `.github/**` from `paths-ignore` or narrow it (e.g. only ignore `.github/ISSUE_TEMPLATE/**`).
- The WKWebView `evaluateJavaScript("setUpdateSettings(...)" )` call in `showMainView()` runs outside of a `DispatchQueue.main.async` block, unlike the extension state call; consider dispatching it explicitly to the main thread to avoid any potential threading issues with WKWebView.

## Individual Comments

### Comment 1
<location path=".github/workflows/build-release.yml" line_range="143-150" />
<code_context>
+            echo '```' >> "$GITHUB_STEP_SUMMARY"
+          fi
+
+      - name: Check for existing tag
+        run: |
+          TAG="${{ steps.version.outputs.tag }}"
+          if git rev-parse "refs/tags/${TAG}" >/dev/null 2>&1; then
+            echo "::warning::Tag ${TAG} already exists — assuming partial release, will reconcile (re-upload asset, refresh appcast)."
+            echo "tag_exists=true" >> "$GITHUB_OUTPUT"
+          else
+            echo "tag_exists=false" >> "$GITHUB_OUTPUT"
+          fi
+
</code_context>
<issue_to_address>
**nitpick:** The `Check for existing tag` step computes an output that is never consumed, and the step has no `id`.

This step writes `tag_exists` to `$GITHUB_OUTPUT`, but without an `id` the output can’t be used and isn’t referenced anywhere else. Either assign an `id` and consume `steps.<id>.outputs.tag_exists` where needed, or remove the unused output to keep the workflow simpler and clearer.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +143 to +150
- name: Check for existing tag
run: |
TAG="${{ steps.version.outputs.tag }}"
if git rev-parse "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "::warning::Tag ${TAG} already exists — assuming partial release, will reconcile (re-upload asset, refresh appcast)."
echo "tag_exists=true" >> "$GITHUB_OUTPUT"
else
echo "tag_exists=false" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nitpick: The Check for existing tag step computes an output that is never consumed, and the step has no id.

This step writes tag_exists to $GITHUB_OUTPUT, but without an id the output can’t be used and isn’t referenced anywhere else. Either assign an id and consume steps.<id>.outputs.tag_exists where needed, or remove the unused output to keep the workflow simpler and clearer.

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.

1 participant