diff --git a/ARCHIVE_POST_ACTION_SETUP.md b/ARCHIVE_POST_ACTION_SETUP.md
deleted file mode 100644
index 4cd6e62..0000000
--- a/ARCHIVE_POST_ACTION_SETUP.md
+++ /dev/null
@@ -1,201 +0,0 @@
-# Archive Post-Action Setup (REQUIRED for App Store)
-
-## The Problem
-
-App Store validation fails with:
-```
-App sandbox not enabled. The following executables must include the
-"com.apple.security.app-sandbox" entitlement...
-Sparkle.framework/Versions/B/Autoupdate
-Sparkle.framework/Versions/B/Updater.app
-...
-```
-
-Sparkle.framework **must be physically removed** from the app bundle for App Store distribution.
-
-## Why Build Phase Scripts Don't Work
-
-Build Phase scripts run during compilation when files are code-signed and locked by macOS. Even with `chmod` and `chflags`, you get "Operation not permitted" due to System Integrity Protection.
-
-## The Solution: Archive Post-Action
-
-Archive Post-Actions run **after** the archive completes, when files are no longer locked. This is the correct place to remove Sparkle.
-
----
-
-## Setup Instructions (2 minutes)
-
-### 1. Open Scheme Editor
-In Xcode: **Product → Scheme → Edit Scheme...** (or press **⌘<**)
-
-### 2. Select Archive
-Click **Archive** in the left sidebar
-
-### 3. Add Post-Action Script
-- At the bottom, under "Post-actions", click the **+** button
-- Select **New Run Script Action**
-
-### 4. Configure the Action
-
-**Provide build settings from:** Select **Gaze** from the dropdown (IMPORTANT!)
-
-**Shell:** Leave as `/bin/bash`
-
-**Script:** Copy and paste this entire script:
-
-```bash
-if [[ "${OTHER_SWIFT_FLAGS}" == *"APPSTORE"* ]]; then
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
- echo "🗑️ Removing Sparkle from archived app..."
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
-
- SPARKLE_PATH="${ARCHIVE_PATH}/Products/Applications/Gaze.app/Contents/Frameworks/Sparkle.framework"
-
- if [ -d "$SPARKLE_PATH" ]; then
- echo "📂 Found Sparkle at: $SPARKLE_PATH"
-
- # Make writable and remove
- chmod -R u+w "$SPARKLE_PATH" 2>/dev/null || true
- chflags -R nouchg "$SPARKLE_PATH" 2>/dev/null || true
- rm -rf "$SPARKLE_PATH"
-
- if [ ! -d "$SPARKLE_PATH" ]; then
- echo "✅ Sparkle framework removed successfully!"
- else
- echo "❌ ERROR: Could not remove Sparkle framework"
- echo " This will cause App Store validation to fail"
- exit 1
- fi
- else
- echo "ℹ️ Sparkle framework not found (already removed)"
- fi
-
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
- echo "✅ Archive ready for App Store distribution"
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
-else
- echo "✓ Self-distribution archive - Sparkle retained"
-fi
-```
-
-### 5. Save
-Click **Close** to save the scheme changes
-
----
-
-## Verification Steps
-
-### Test the Archive
-
-1. **Switch to App Store mode:**
- ```bash
- ./switch_to appstore
- ```
-
-2. **Archive in Xcode:**
- - **Product → Archive** (or **⌘⇧B** then Archive)
- - Watch the build log - you should see the post-action output
-
-3. **Check the archive contents:**
- - **Window → Organizer**
- - Select your latest Gaze archive
- - Right-click → **Show in Finder**
- - Right-click the `.xcarchive` file → **Show Package Contents**
- - Navigate to: `Products/Applications/Gaze.app/Contents/Frameworks/`
- - **Verify:** Only `Lottie.framework` should be present ✅
-
-4. **Distribute to App Store:**
- - In Organizer, click **Distribute App**
- - Choose **App Store Connect**
- - Complete the distribution wizard
- - **Validation should now pass!** ✅
-
----
-
-## What You Should See
-
-### In the Build Log (after archiving):
-```
-━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-🗑️ Removing Sparkle from archived app...
-━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-📂 Found Sparkle at: [path]
-✅ Sparkle framework removed successfully!
-━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-✅ Archive ready for App Store distribution
-━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-```
-
-### In the Frameworks folder:
-```
-Gaze.app/Contents/Frameworks/
-└── Lottie.framework/
-```
-
-No Sparkle.framework! ✅
-
----
-
-## Troubleshooting
-
-### "I don't see the post-action output"
-- Make sure you selected **Gaze** in "Provide build settings from"
-- Check View → Navigators → Show Report Navigator (⌘9)
-- Select the Archive action to see full logs
-
-### "Sparkle is still in the archive"
-- Verify `./switch_to status` shows "App Store" for all items
-- Check the script exactly matches (copy/paste the entire script)
-- Try cleaning: Product → Clean Build Folder (⌘⇧K)
-
-### "Script says 'Sparkle framework not found'"
-- This means Sparkle wasn't embedded (good!)
-- Continue with distribution - validation should pass
-
-### "Archive Post-Action section doesn't exist"
-- Make sure you're editing the **Archive** section, not Run or Test
-- Click the triangle next to "Archive" to expand it
-
----
-
-## Optional: Remove Old Build Phase Script
-
-If you previously added a Build Phase script (which doesn't work due to file locking), you can remove it:
-
-1. Gaze target → Build Phases
-2. Find "Remove Sparkle for App Store" or "Run Script"
-3. Click the **X** to delete it
-
-The Archive Post-Action is the correct and only solution needed.
-
----
-
-## Why This Is Required
-
-Even though:
-- ✅ Sparkle code is disabled via `#if !APPSTORE`
-- ✅ Info.plist has no Sparkle keys
-- ✅ Entitlements have no Sparkle exceptions
-
-App Store validation **still checks** for the physical presence of unsandboxed executables in frameworks. Sparkle contains XPC services that aren't App Store compatible, so the entire framework must be removed.
-
----
-
-## For Self-Distribution
-
-When building for self-distribution (`./switch_to self`), the script detects the absence of the APPSTORE flag and leaves Sparkle intact. You don't need to change anything!
-
-```bash
-./switch_to self
-./self_distribute # Sparkle is retained and works normally
-```
-
----
-
-## Summary
-
-✅ **One-time setup:** Add Archive Post-Action script
-✅ **Works automatically:** Removes Sparkle only for App Store builds
-✅ **Zero maintenance:** Once configured, runs automatically forever
-
-This is the **correct and only working solution** for removing Sparkle from App Store builds!
diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md
deleted file mode 100644
index db7ea4c..0000000
--- a/DEPLOYMENT.md
+++ /dev/null
@@ -1,296 +0,0 @@
-# Gaze Release Deployment Process
-
-## Overview
-
-This document describes the complete process for building and deploying new releases of Gaze with Sparkle auto-update support.
-
-## Prerequisites
-
-- Xcode with Gaze project configured
-- `create-dmg` tool installed (`brew install create-dmg`)
-- Sparkle EdDSA signing keys in macOS Keychain (see Key Management below)
-- AWS credentials configured in `.env` file for S3 upload
-- Access to freno.me hosting infrastructure
-
-## Version Management
-
-Version numbers are managed in Xcode project settings:
-- **Marketing Version** (`MARKETING_VERSION`): User-facing version (e.g., "0.1.1")
-- **Build Number** (`CURRENT_PROJECT_VERSION`): Internal build number (e.g., "1")
-
-These must be incremented before each release and kept in sync with `build_dmg` script.
-
-## Release Checklist
-
-### 1. Prepare Release
-
-- [ ] Update version numbers in Xcode:
- - Project Settings → General → Identity
- - Set Marketing Version (e.g., "0.1.2")
- - Increment Build Number (e.g., "2")
-- [ ] Update `VERSION` and `BUILD_NUMBER` in `build_dmg` script
-- [ ] Update CHANGELOG or release notes
-- [ ] Commit version changes: `git commit -am "Bump version to X.Y.Z"`
-- [ ] Create git tag: `git tag v0.1.2`
-
-### 2. Build Application
-
-```bash
-# Build the app in Xcode (Product → Archive → Export)
-# Or use the run script
-./run build
-
-# Verify the app runs correctly
-open Gaze.app
-```
-
-### 3. Create DMG and Appcast
-
-```bash
-# Run the build_dmg script
-./build_dmg
-
-# This will:
-# - Create versioned DMG file
-# - Generate appcast.xml with EdDSA signature
-# - Upload to S3 if AWS credentials are configured
-# - Display next steps
-```
-
-### 4. Verify Artifacts
-
-Check that the following files were created in `./releases/`:
-- `Gaze-X.Y.Z.dmg` - Installable disk image
-- `appcast.xml` - Update feed with signature
-- `Gaze-X.Y.Z.delta` (optional) - Delta update from previous version
-
-### 5. Upload to Hosting (if not using S3 auto-upload)
-
-**DMG File:**
-```bash
-# Upload to: https://freno.me/downloads/
-scp ./releases/Gaze-X.Y.Z.dmg your-server:/path/to/downloads/
-```
-
-**Appcast File:**
-```bash
-# Upload to: https://freno.me/api/Gaze/
-scp ./releases/appcast.xml your-server:/path/to/api/Gaze/
-```
-
-### 6. Verify Deployment
-
-Test that files are accessible via HTTPS:
-
-```bash
-# Test appcast accessibility
-curl -I https://freno.me/api/Gaze/appcast.xml
-# Should return: HTTP/2 200, content-type: application/xml
-
-# Test DMG accessibility
-curl -I https://freno.me/downloads/Gaze-X.Y.Z.dmg
-# Should return: HTTP/2 200, content-type: application/octet-stream
-
-# Validate appcast XML structure
-curl https://freno.me/api/Gaze/appcast.xml | xmllint --format -
-```
-
-### 7. Test Update Flow
-
-**Manual Testing:**
-1. Install previous version of Gaze
-2. Launch app and check Settings → General → Software Updates
-3. Click "Check for Updates Now"
-4. Verify update notification appears
-5. Complete update installation
-6. Verify new version launches correctly
-
-**Automatic Update Testing:**
-1. Set `SUScheduledCheckInterval` to a low value (e.g., 60 seconds) for testing
-2. Install previous version
-3. Wait for automatic check
-4. Verify update notification appears
-
-### 8. Finalize Release
-
-- [ ] Push git tag: `git push origin v0.1.2`
-- [ ] Create GitHub release (optional)
-- [ ] Announce release to users
-- [ ] Monitor for update errors in the first 24 hours
-
-## Hosting Configuration
-
-### Current Setup
-
-- **Appcast URL:** `https://freno.me/api/Gaze/appcast.xml`
-- **Download URL:** `https://freno.me/downloads/Gaze-{VERSION}.dmg`
-- **Hosting:** AWS S3 with freno.me domain
-- **SSL:** HTTPS enabled (required by App Transport Security)
-
-### AWS S3 Configuration
-
-Create a `.env` file in the project root with:
-
-```bash
-AWS_ACCESS_KEY_ID=your_access_key
-AWS_SECRET_ACCESS_KEY=your_secret_key
-AWS_BUCKET_NAME=your_bucket_name
-AWS_REGION=us-east-1
-```
-
-**Note:** `.env` is gitignored to protect credentials.
-
-### S3 Bucket Structure
-
-```
-your-bucket/
-├── downloads/
-│ ├── Gaze-0.1.1.dmg
-│ ├── Gaze-0.1.2.dmg
-│ └── ...
-└── api/
- └── Gaze/
- └── appcast.xml
-```
-
-## Key Management
-
-### EdDSA Signing Keys
-
-**Location:**
-- **Public Key:** In `Gaze/Info.plist` as `SUPublicEDKey`
-- **Private Key:** In macOS Keychain as "Sparkle EdDSA Private Key"
-- **Backup:** `~/sparkle_private_key_backup.pem` (keep secure!)
-
-**Current Public Key:**
-```
-Z2RmohI1y2bgeGQQUDqO9F0HNF2AzFotOt8CwGB6VJM=
-```
-
-**Security:**
-- Never commit private key to version control
-- Keep backup in secure location (password manager, encrypted drive)
-- Private key is required to sign all future updates
-
-### Regenerating Keys (Emergency Only)
-
-If private key is lost, you must:
-1. Generate new key pair: `./generate_keys`
-2. Update `SUPublicEDKey` in Info.plist
-3. Release new version with new public key
-4. Previous versions won't be able to update (users must manually install)
-
-## Troubleshooting
-
-### Appcast Generation Fails
-
-**Problem:** `generate_appcast` tool not found
-
-**Solution:**
-```bash
-# Build the app first to generate Sparkle tools
-xcodebuild -project Gaze.xcodeproj -scheme Gaze -configuration Release
-
-# Find Sparkle tools
-find ~/Library/Developer/Xcode/DerivedData/Gaze-* -name "generate_appcast"
-```
-
-### Update Check Fails in App
-
-**Problem:** No updates found or connection error
-
-**Diagnostics:**
-```bash
-# Check Console.app for Sparkle logs
-# Filter by process: Gaze
-# Look for:
-# - "Downloading appcast..."
-# - "Appcast downloaded successfully"
-# - Connection errors
-# - Signature verification errors
-```
-
-**Common Issues:**
-- Appcast URL not accessible (check HTTPS)
-- Signature mismatch (wrong private key used)
-- XML malformed (validate with xmllint)
-- Version number not higher than current version
-
-### DMG Not Downloading
-
-**Problem:** Update found but download fails
-
-**Check:**
-- DMG URL is correct in appcast
-- DMG file is accessible via HTTPS
-- File size in appcast matches actual DMG size
-- No CORS issues (check browser console)
-
-## Delta Updates
-
-Sparkle automatically generates delta updates when multiple versions exist in `./releases/`:
-
-```bash
-# Keep previous versions for delta generation
-releases/
-├── Gaze-0.1.1.dmg
-├── Gaze-0.1.2.dmg
-├── Gaze-0.1.1-to-0.1.2.delta # Generated automatically
-└── appcast.xml
-```
-
-**Benefits:**
-- Much smaller downloads (MB vs GB)
-- Faster updates for users
-- Generated automatically by `generate_appcast`
-
-**Note:** First-time users still download full DMG.
-
-## Testing with Local Appcast
-
-For testing without deploying:
-
-1. Modify Info.plist temporarily:
-```xml
-SUFeedURL
-file:///Users/mike/Code/Gaze/releases/appcast.xml
-```
-
-2. Build and run app
-3. Check for updates
-4. Revert Info.plist before committing
-
-## Release Notes
-
-Release notes are embedded in appcast XML as CDATA:
-
-```xml
-What's New in Version X.Y.Z
-
- - Feature 1
- - Bug fix 2
-
-]]>
-```
-
-**Tips:**
-- Use simple HTML (h2, ul, li, p, strong, em)
-- No external resources (images, CSS, JS)
-- Keep concise and user-focused
-- Highlight breaking changes
-
-## References
-
-- [Sparkle Documentation](https://sparkle-project.org/documentation/)
-- [Publishing Updates](https://sparkle-project.org/documentation/publishing/)
-- [Sandboxed Apps](https://sparkle-project.org/documentation/sandboxing/)
-- [Gaze Repository](https://github.com/YOUR_USERNAME/Gaze)
-
-## Support
-
-For issues with deployment:
-1. Check Console.app for Sparkle errors
-2. Verify appcast validation with xmllint
-3. Test with file:// URL first
-4. Check AWS S3 permissions and CORS
diff --git a/DISTRIBUTION.md b/DISTRIBUTION.md
deleted file mode 100644
index 08bbc69..0000000
--- a/DISTRIBUTION.md
+++ /dev/null
@@ -1,214 +0,0 @@
-# Gaze Distribution Guide
-
-This guide explains how to build and distribute Gaze for both the Mac App Store and direct distribution with auto-updates.
-
-## Distribution Methods
-
-Gaze supports two distribution methods:
-
-1. **Self-Distribution** (Direct Download) - Includes Sparkle for automatic updates
-2. **Mac App Store** - Uses Apple's update mechanism, no Sparkle
-
-## Quick Start
-
-### Switching Between Distributions
-
-Use the `switch_to` script to configure the project for each distribution method:
-
-```bash
-# For self-distribution with Sparkle auto-updates
-./switch_to self
-
-# For Mac App Store submission
-./switch_to appstore
-
-# Check current configuration
-./switch_to status
-```
-
-### What Gets Changed
-
-The `switch_to` script automatically manages:
-
-**Self-Distribution Mode:**
-- ✅ Adds Sparkle keys to `Info.plist` (SUPublicEDKey, SUFeedURL, etc.)
-- ✅ Adds Sparkle entitlements for XPC services
-- ✅ Removes `APPSTORE` compiler flag
-- ✅ Enables UpdateManager with Sparkle framework
-
-**App Store Mode:**
-- ✅ Removes all Sparkle keys from `Info.plist`
-- ✅ Removes Sparkle entitlements
-- ✅ Adds `-D APPSTORE` compiler flag
-- ✅ Disables Sparkle code at compile time
-
-## Building for Self-Distribution
-
-```bash
-# 1. Switch to self-distribution mode
-./switch_to self
-```
-
-The script will:
-- Prompt for version bump (major/minor/patch)
-- Build and code sign with Developer ID
-- Notarize the app with Apple
-- Create a signed DMG
-- Generate Sparkle appcast with EdDSA signature
-- (Optional) Upload to S3 if credentials are configured
-
-## Building for Mac App Store
-
-```bash
-# 1. Switch to App Store mode
-./switch_to appstore
-
-# 2. Add Run Script Phase in Xcode (one-time setup)
-# See section below
-
-# 3. Archive and distribute via Xcode
-# Product → Archive
-# Window → Organizer → Distribute App → App Store Connect
-```
-
-### Required: Run Script Phase
-
-For App Store builds, you **must** add this Run Script phase in Xcode:
-
-1. Open Gaze.xcodeproj in Xcode
-2. Select the Gaze target → Build Phases
-3. Click + → New Run Script Phase
-4. Name it: "Remove Sparkle for App Store"
-5. Place it **after** "Embed Frameworks"
-6. Add this script:
-
-```bash
-#!/bin/bash
-if [[ "${OTHER_SWIFT_FLAGS}" == *"APPSTORE"* ]]; then
- echo "Removing Sparkle framework for App Store build..."
- rm -rf "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework"
- echo "Sparkle framework removed successfully"
-fi
-```
-
-This ensures Sparkle.framework is removed from the app bundle before submission.
-
-## Configuration Files
-
-Configuration backups are stored in `.distribution_configs/`:
-- `.distribution_configs/appstore/` - App Store configuration
-- `.distribution_configs/self/` - Self-distribution configuration
-
-These backups are created automatically and used when switching between modes.
-
-## Validation
-
-Before submitting to App Store Connect, verify your configuration:
-
-```bash
-./switch_to status
-```
-
-Expected output for App Store:
-```
-Info.plist: App Store (no Sparkle keys)
-Entitlements: App Store (no Sparkle exceptions)
-Build Settings: App Store (has APPSTORE flag)
-```
-
-Expected output for Self-Distribution:
-```
-Info.plist: Self-Distribution (has Sparkle keys)
-Entitlements: Self-Distribution (has Sparkle exceptions)
-Build Settings: Self-Distribution (no APPSTORE flag)
-```
-
-## Troubleshooting
-
-### App Store Validation Fails
-
-**Error: "App sandbox not enabled" with Sparkle executables**
-- Solution: Make sure you ran `./switch_to appstore` and added the Run Script phase
-
-**Error: "Bad Bundle Executable" or "CFBundlePackageType"**
-- Solution: These are now fixed in the Info.plist
-
-**Error: Still seeing Sparkle in the build**
-- Solution: Clean build folder (⌘⇧K) and rebuild
-
-### Self-Distribution Issues
-
-**Sparkle updates not working**
-- Verify: `./switch_to status` shows "Self-Distribution" mode
-- Check: Info.plist contains SUPublicEDKey and SUFeedURL
-- Verify: Appcast is accessible at the SUFeedURL
-
-**Code signing issues**
-- Check `.env` file has correct credentials
-- Verify Developer ID certificate: `security find-identity -v -p codesigning`
-
-## Environment Variables
-
-For self-distribution, create a `.env` file with:
-
-```bash
-# Required for code signing
-DEVELOPER_ID_APPLICATION="Developer ID Application: Your Name (TEAM_ID)"
-APPLE_TEAM_ID="XXXXXXXXXX"
-
-# Required for notarization
-NOTARY_KEYCHAIN_PROFILE="notary-profile"
-
-# Optional for S3 upload
-AWS_ACCESS_KEY_ID="your-key"
-AWS_SECRET_ACCESS_KEY="your-secret"
-AWS_BUCKET_NAME="your-bucket"
-AWS_REGION="us-east-1"
-```
-
-Setup notarization profile (one-time):
-```bash
-xcrun notarytool store-credentials "notary-profile" \
- --apple-id "your@email.com" \
- --team-id "TEAM_ID"
-```
-
-## Version Management
-
-The `self_distribute` script handles version bumping:
-- **Major** (X.0.0) - Breaking changes
-- **Minor** (x.X.0) - New features
-- **Patch** (x.x.X) - Bug fixes
-- **Custom** - Any version string
-- **Keep** - Increment build number only
-
-Git tags are created automatically for new versions.
-
-## Testing
-
-### Test Self-Distribution Build
-```bash
-./switch_to self
-# Test the DMG on a clean macOS system
-```
-
-### Test App Store Build
-```bash
-./switch_to appstore
-# Archive in Xcode
-# Use TestFlight for testing before release
-```
-
-## Best Practices
-
-1. **Always use `switch_to`** - Don't manually edit configuration files
-2. **Check status before building** - Use `./switch_to status`
-3. **Clean builds** - Run Clean Build Folder when switching modes
-4. **Test thoroughly** - Test both distribution methods separately
-5. **Commit before switching** - Use git to track configuration changes
-
-## Support
-
-For issues or questions:
-- GitHub Issues: https://github.com/mikefreno/Gaze/issues
-- Check AGENTS.md for development guidelines
diff --git a/Gaze.xcodeproj/project.pbxproj b/Gaze.xcodeproj/project.pbxproj
index 2ba1ab2..93d0cee 100644
--- a/Gaze.xcodeproj/project.pbxproj
+++ b/Gaze.xcodeproj/project.pbxproj
@@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */
275915892F132A9200D0E60D /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 27AE10B12F10B1FC00E00DBC /* Lottie */; };
- 275915902F132B0000D0E60D /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 27AE10B22F10B20000E00DBC /* Sparkle */; settings = {ATTRIBUTES = (Weak, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -71,7 +70,6 @@
buildActionMask = 2147483647;
files = (
275915892F132A9200D0E60D /* Lottie in Frameworks */,
- 275915902F132B0000D0E60D /* Sparkle in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -133,7 +131,6 @@
name = Gaze;
packageProductDependencies = (
27AE10B12F10B1FC00E00DBC /* Lottie */,
- 27AE10B22F10B20000E00DBC /* Sparkle */,
);
productName = Gaze;
productReference = 27A21B3C2F0F69DC0018C4F3 /* Gaze.app */;
@@ -219,7 +216,6 @@
minimizedProjectReferenceProxies = 1;
packageReferences = (
27AE10B02F10B1FC00E00DBC /* XCRemoteSwiftPackageReference "lottie-spm" */,
- 27AE10B32F10B21000E00DBC /* XCRemoteSwiftPackageReference "Sparkle" */,
);
preferredProjectObjectVersion = 77;
productRefGroup = 27A21B3D2F0F69DC0018C4F3 /* Products */;
@@ -424,7 +420,7 @@
CODE_SIGN_ENTITLEMENTS = Gaze/Gaze.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = 6GK4F9L62V;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
@@ -460,7 +456,7 @@
CODE_SIGN_ENTITLEMENTS = Gaze/Gaze.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = 6GK4F9L62V;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
@@ -618,14 +614,6 @@
minimumVersion = 4.6.0;
};
};
- 27AE10B32F10B21000E00DBC /* XCRemoteSwiftPackageReference "Sparkle" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/sparkle-project/Sparkle";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 2.0.0;
- };
- };
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@@ -634,11 +622,6 @@
package = 27AE10B02F10B1FC00E00DBC /* XCRemoteSwiftPackageReference "lottie-spm" */;
productName = Lottie;
};
- 27AE10B22F10B20000E00DBC /* Sparkle */ = {
- isa = XCSwiftPackageProductDependency;
- package = 27AE10B32F10B21000E00DBC /* XCRemoteSwiftPackageReference "Sparkle" */;
- productName = Sparkle;
- };
/* End XCSwiftPackageProductDependency section */
};
rootObject = 27A21B342F0F69DC0018C4F3 /* Project object */;
diff --git a/Gaze.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Gaze.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index b3cf5c5..de23afb 100644
--- a/Gaze.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/Gaze.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,5 @@
{
- "originHash" : "513d974fbede884a919977d3446360023f6e3239ac314f4fbd9657e80aca7560",
+ "originHash" : "6b3386dc9ff1f3a74f1534de9c41d47137eae0901cfe819ed442f1b241549359",
"pins" : [
{
"identity" : "lottie-spm",
@@ -9,15 +9,6 @@
"revision" : "69faaefa7721fba9e434a52c16adf4329c9084db",
"version" : "4.6.0"
}
- },
- {
- "identity" : "sparkle",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/sparkle-project/Sparkle",
- "state" : {
- "revision" : "5581748cef2bae787496fe6d61139aebe0a451f6",
- "version" : "2.8.1"
- }
}
],
"version" : 3
diff --git a/Gaze.xcodeproj/xcshareddata/xcschemes/Gaze.xcscheme b/Gaze.xcodeproj/xcshareddata/xcschemes/Gaze.xcscheme
index e7dc879..b02b961 100644
--- a/Gaze.xcodeproj/xcshareddata/xcschemes/Gaze.xcscheme
+++ b/Gaze.xcodeproj/xcshareddata/xcschemes/Gaze.xcscheme
@@ -98,23 +98,5 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/switch_to b/switch_to
index 87e831a..9c83c8e 100755
--- a/switch_to
+++ b/switch_to
@@ -12,12 +12,17 @@ NC='\033[0m' # No Color
INFO_PLIST="Gaze/Info.plist"
ENTITLEMENTS="Gaze/Gaze.entitlements"
PROJECT_FILE="Gaze.xcodeproj/project.pbxproj"
+PACKAGE_RESOLVED="Gaze.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved"
BACKUP_DIR=".distribution_configs"
# Distribution configurations
APPSTORE_CONFIG="${BACKUP_DIR}/appstore"
SELF_CONFIG="${BACKUP_DIR}/self"
+# Sparkle package details
+SPARKLE_REPO="https://github.com/sparkle-project/Sparkle"
+SPARKLE_VERSION="2.8.1"
+
# Function to print colored messages
print_info() {
echo -e "${BLUE}ℹ${NC} $1"
@@ -35,6 +40,113 @@ print_error() {
echo -e "${RED}✗${NC} $1"
}
+# Function to check if Sparkle is in Package.resolved
+has_sparkle_package() {
+ if [ -f "${PACKAGE_RESOLVED}" ]; then
+ grep -q "Sparkle" "${PACKAGE_RESOLVED}"
+ return $?
+ fi
+ return 1
+}
+
+# Function to remove Sparkle from Xcode project
+remove_sparkle_package() {
+ print_info "Removing Sparkle package dependency..."
+
+ # Check if Sparkle exists in the project
+ if ! has_sparkle_package && ! grep -q "Sparkle" "${PROJECT_FILE}"; then
+ print_info "Sparkle already removed"
+ return 0
+ fi
+
+ # Backup project file
+ cp "${PROJECT_FILE}" "${PROJECT_FILE}.backup"
+
+ # Remove Sparkle from Package.resolved
+ if [ -f "${PACKAGE_RESOLVED}" ]; then
+ # Create a temp file without Sparkle entry
+ python3 -c "
+import json
+import sys
+
+try:
+ with open('${PACKAGE_RESOLVED}', 'r') as f:
+ data = json.load(f)
+
+ # Filter out Sparkle from pins
+ if 'pins' in data:
+ data['pins'] = [pin for pin in data['pins'] if 'sparkle' not in pin.get('identity', '').lower()]
+
+ with open('${PACKAGE_RESOLVED}', 'w') as f:
+ json.dump(data, f, indent=2)
+
+ print('✓ Updated Package.resolved')
+except Exception as e:
+ print(f'Error: {e}', file=sys.stderr)
+ sys.exit(1)
+"
+ if [ $? -ne 0 ]; then
+ print_error "Failed to update Package.resolved"
+ mv "${PROJECT_FILE}.backup" "${PROJECT_FILE}"
+ return 1
+ fi
+ fi
+
+ # Remove Sparkle references from project.pbxproj
+ # This removes: package references, product dependencies, and framework build files
+
+ # Remove XCRemoteSwiftPackageReference for Sparkle
+ sed -i '' '/XCRemoteSwiftPackageReference "Sparkle"/,/};/d' "${PROJECT_FILE}"
+
+ # Remove XCSwiftPackageProductDependency for Sparkle
+ sed -i '' '/XCSwiftPackageProductDependency "Sparkle"/,/};/d' "${PROJECT_FILE}"
+
+ # Remove Sparkle from packageProductDependencies array
+ sed -i '' '/\/\* Sparkle \*\/,/d' "${PROJECT_FILE}"
+
+ # Remove Sparkle from Frameworks build phase
+ sed -i '' '/Sparkle in Frameworks/d' "${PROJECT_FILE}"
+
+ # Clean up empty lines
+ sed -i '' '/^[[:space:]]*$/d' "${PROJECT_FILE}"
+
+ rm -f "${PROJECT_FILE}.backup"
+
+ print_success "Removed Sparkle package dependency"
+ print_info "Xcode will resolve packages on next build"
+}
+
+# Function to add Sparkle to Xcode project
+add_sparkle_package() {
+ print_info "Adding Sparkle package dependency..."
+
+ # Check if Sparkle already exists
+ if has_sparkle_package || grep -q "Sparkle" "${PROJECT_FILE}"; then
+ print_info "Sparkle already present"
+ return 0
+ fi
+
+ print_warning "Sparkle package must be added manually in Xcode:"
+ echo ""
+ echo " 1. Open Gaze.xcodeproj in Xcode"
+ echo " 2. Select the project in the navigator"
+ echo " 3. Go to 'Package Dependencies' tab"
+ echo " 4. Click '+' button"
+ echo " 5. Enter: ${SPARKLE_REPO}"
+ echo " 6. Select version ${SPARKLE_VERSION}"
+ echo " 7. Click 'Add Package'"
+ echo " 8. Select 'Sparkle' product and add to Gaze target"
+ echo ""
+ print_info "Or run this from command line:"
+ echo " xed Gaze.xcodeproj"
+ echo ""
+
+ # Note: Programmatically adding Swift packages via pbxproj is extremely complex
+ # and error-prone. Manual addition via Xcode UI is recommended.
+
+ return 0
+}
+
# Function to create backup directories
create_backup_dirs() {
mkdir -p "${APPSTORE_CONFIG}"
@@ -233,6 +345,13 @@ show_current_mode() {
echo " Build Settings: ${GREEN}Self-Distribution${NC} (no APPSTORE flag)"
fi
+ # Check for Sparkle package dependency
+ if has_sparkle_package || grep -q "Sparkle" "${PROJECT_FILE}" 2>/dev/null; then
+ echo " Package Dependency: ${GREEN}Self-Distribution${NC} (has Sparkle)"
+ else
+ echo " Package Dependency: ${BLUE}App Store${NC} (no Sparkle)"
+ fi
+
echo ""
}
@@ -246,18 +365,17 @@ switch_to_appstore() {
backup_current_config "self-distribution" "${SELF_CONFIG}"
fi
+ # Remove Sparkle package dependency
+ remove_sparkle_package
+ echo ""
+
# Restore App Store config
restore_config "App Store" "${APPSTORE_CONFIG}"
echo ""
print_success "Switched to App Store distribution mode"
- print_warning "Remember to add the Run Script phase to remove Sparkle framework!"
- echo ""
- echo "Run Script to add in Xcode Build Phases:"
- echo '#!/bin/bash'
- echo 'if [[ "${OTHER_SWIFT_FLAGS}" == *"APPSTORE"* ]]; then'
- echo ' rm -rf "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework"'
- echo 'fi'
+ print_info "Sparkle framework has been removed from dependencies"
+ print_info "You can now archive and submit to App Store"
}
# Function to switch to self-distribution configuration
@@ -273,9 +391,19 @@ switch_to_self() {
# Restore self-distribution config
restore_config "self-distribution" "${SELF_CONFIG}"
+ echo ""
+
+ # Add Sparkle package dependency
+ add_sparkle_package
+
echo ""
print_success "Switched to self-distribution mode"
print_info "Sparkle auto-updates enabled"
+
+ if ! has_sparkle_package; then
+ echo ""
+ print_warning "Remember to add Sparkle package in Xcode (see instructions above)"
+ fi
}
# Function to show usage
@@ -288,11 +416,13 @@ ${GREEN}Usage:${NC}
${GREEN}Commands:${NC}
appstore Switch to App Store distribution configuration
+ - Removes Sparkle package dependency from project
- Removes Sparkle keys from Info.plist
- Removes Sparkle entitlements
- Adds APPSTORE compiler flag
self Switch to self-distribution configuration
+ - Prompts to add Sparkle package dependency
- Adds Sparkle keys to Info.plist
- Adds Sparkle entitlements for XPC services
- Removes APPSTORE compiler flag