diff --git a/Gaze/Views/Setup/GeneralSetupView.swift b/Gaze/Views/Setup/GeneralSetupView.swift index 0e5ef19..ee29026 100644 --- a/Gaze/Views/Setup/GeneralSetupView.swift +++ b/Gaze/Views/Setup/GeneralSetupView.swift @@ -55,27 +55,37 @@ struct GeneralSetupView: View { // Software Updates Section if !isAppStoreVersion { - VStack(alignment: .leading, spacing: 12) { - Text("Software Updates") - .font(.headline) + HStack { + VStack(alignment: .leading, spacing: 4) { + Text("Software Updates") + .font(.headline) - Toggle("Automatically check for updates", isOn: $updateManager.automaticallyChecksForUpdates) - .help("Check for new versions of Gaze in the background") - - if let lastCheck = updateManager.lastUpdateCheckDate { - Text("Last checked: \(lastCheck, style: .relative)") - .font(.caption) - .foregroundColor(.secondary) - } else { - Text("Never checked for updates") - .font(.caption) - .foregroundColor(.secondary) + if let lastCheck = updateManager.lastUpdateCheckDate { + Text("Last checked: \(lastCheck, style: .relative)") + .font(.caption) + .foregroundColor(.secondary) + .italic() + } else { + Text("Never checked for updates") + .font(.caption) + .foregroundColor(.secondary) + .italic() + } } + Spacer() + Button("Check for Updates Now") { updateManager.checkForUpdates() } .buttonStyle(.bordered) + + Toggle( + "Automatically check for updates", + isOn: $updateManager.automaticallyChecksForUpdates + ) + .labelsHidden() + .help("Check for new versions of Gaze in the background") } .padding() .glassEffectIfAvailable(GlassStyle.regular, in: .rect(cornerRadius: 12)) diff --git a/build_dmg b/build_dmg index 97441bd..3d143fe 100755 --- a/build_dmg +++ b/build_dmg @@ -6,9 +6,24 @@ if [ -f .env ]; then export $(grep -v '^#' .env | xargs) fi -# Configuration -VERSION="0.1.1" # Should match MARKETING_VERSION in project -BUILD_NUMBER="1" # Should match CURRENT_PROJECT_VERSION in project +# Extract version from Xcode project (Release configuration) +PROJECT_FILE="Gaze.xcodeproj/project.pbxproj" +VERSION=$(grep -A 1 "MARKETING_VERSION" "$PROJECT_FILE" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1) +BUILD_NUMBER=$(grep -A 1 "CURRENT_PROJECT_VERSION" "$PROJECT_FILE" | grep -o '[0-9]\+' | head -1) + +# Fallback to manual values if extraction fails +if [ -z "$VERSION" ]; then + echo "⚠️ Could not extract MARKETING_VERSION from project, using fallback" + VERSION="0.1.1" +fi + +if [ -z "$BUILD_NUMBER" ]; then + echo "⚠️ Could not extract CURRENT_PROJECT_VERSION from project, using fallback" + BUILD_NUMBER="1" +fi + +echo "📦 Building Gaze v${VERSION} (build ${BUILD_NUMBER})" + RELEASES_DIR="./releases" APPCAST_OUTPUT="${RELEASES_DIR}/appcast.xml" FEED_URL="https://freno.me/api/Gaze/appcast.xml" @@ -50,9 +65,22 @@ if [ -n "$SPARKLE_BIN" ] && [ -d "$SPARKLE_BIN" ]; then echo "" echo "Generating appcast..." - # Generate appcast with download URL prefix + # Check for private key (Keychain or file) + PRIVATE_KEY_FILE="$HOME/sparkle_private_key_backup.pem" + KEY_OPTION="" + + if [ -f "$PRIVATE_KEY_FILE" ]; then + echo "Using private key from: $PRIVATE_KEY_FILE" + KEY_OPTION="--ed-key-file $PRIVATE_KEY_FILE" + else + echo "Using private key from Keychain (account: ed25519)" + KEY_OPTION="--account ed25519" + fi + + # Generate appcast with download URL prefix and key "$SPARKLE_BIN/generate_appcast" \ --download-url-prefix "https://freno.me/downloads/" \ + $KEY_OPTION \ "$RELEASES_DIR" # Verify appcast was generated @@ -60,20 +88,48 @@ if [ -n "$SPARKLE_BIN" ] && [ -d "$SPARKLE_BIN" ]; then echo "✅ Appcast generated successfully" echo "📋 Appcast location: $APPCAST_OUTPUT" - # Show signature verification + # Check for signature - if missing, add it manually if grep -q "edSignature" "$APPCAST_OUTPUT"; then echo "✅ EdDSA signature verified in appcast" else - echo "⚠️ Warning: No EdDSA signature found in appcast" + echo "⚠️ No signature found, generating manually with sign_update..." + + # Get signature for the DMG + SIGNATURE_OUTPUT=$("$SPARKLE_BIN/sign_update" "$RELEASES_DIR/$DMG_NAME" 2>&1) + + if echo "$SIGNATURE_OUTPUT" | grep -q "edSignature"; then + # Extract the signature + ED_SIGNATURE=$(echo "$SIGNATURE_OUTPUT" | grep -o 'sparkle:edSignature="[^"]*"' | sed 's/sparkle:edSignature="\([^"]*\)"/\1/') + FILE_LENGTH=$(echo "$SIGNATURE_OUTPUT" | grep -o 'length="[^"]*"' | sed 's/length="\([^"]*\)"/\1/') + + echo "✅ Generated signature: ${ED_SIGNATURE:0:20}..." + + # Add signature to appcast XML + # Find the enclosure line and add sparkle:edSignature attribute + sed -i '' "s| + + + Gaze + + 0.1.1 + Sun, 11 Jan 2026 18:07:02 -0500 + 1 + 0.1.1 + 14.6 + + + + \ No newline at end of file