B55403EA2A79A434004BCBAB /* ScriptedPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55403E92A79A434004BCBAB /* ScriptedPreferences.swift */; };
B55403EB2A7A2AD2004BCBAB /* Captura.sdef in Resources */ = {isa = PBXBuildFile; fileRef = B5278B482A781B78009F6462 /* Captura.sdef */; };
B55403ED2A7A388B004BCBAB /* RecordCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55403EC2A7A388B004BCBAB /* RecordCommand.swift */; };
+ B55541E52C95801B0015F522 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = B55541E42C95801B0015F522 /* Sparkle */; };
B55DDFCC2A6F0253001A5E76 /* Notification+AppEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55DDFCB2A6F0253001A5E76 /* Notification+AppEvents.swift */; };
B55DDFCE2A6F069D001A5E76 /* RecordingWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B55DDFCD2A6F069D001A5E76 /* RecordingWindow.swift */; };
B56C70CD2A6EFDF4009B97EB /* CaptureState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C70CC2A6EFDF4009B97EB /* CaptureState.swift */; };
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ B55541E52C95801B0015F522 /* Sparkle in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
path = Scripting;
sourceTree = "<group>";
};
+ B55541E32C95801B0015F522 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
B5F915452A6EF80D007ECE8E = {
isa = PBXGroup;
children = (
B5F915642A6EF80E007ECE8E /* CapturaTests */,
B5F9156E2A6EF80E007ECE8E /* CapturaUITests */,
B5F9154F2A6EF80D007ECE8E /* Products */,
+ B55541E32C95801B0015F522 /* Frameworks */,
);
sourceTree = "<group>";
};
);
name = Captura;
packageProductDependencies = (
+ B55541E42C95801B0015F522 /* Sparkle */,
);
productName = Captura;
productReference = B5F9154E2A6EF80D007ECE8E /* Captura.app */;
);
mainGroup = B5F915452A6EF80D007ECE8E;
packageReferences = (
+ B55541E22C94F86A0015F522 /* XCRemoteSwiftPackageReference "Sparkle" */,
);
productRefGroup = B5F9154F2A6EF80D007ECE8E /* Products */;
projectDirPath = "";
CODE_SIGN_ENTITLEMENTS = Captura/Captura.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 3;
+ CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_ASSET_PATHS = "\"Captura/Preview Content\"";
DEVELOPMENT_TEAM = S68NHQVJXW;
ENABLE_HARDENED_RUNTIME = YES;
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = pizza.unlimited.Captura;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
CODE_SIGN_ENTITLEMENTS = Captura/Captura.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 3;
+ CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_ASSET_PATHS = "\"Captura/Preview Content\"";
DEVELOPMENT_TEAM = S68NHQVJXW;
ENABLE_HARDENED_RUNTIME = YES;
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = pizza.unlimited.Captura;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
};
/* End XCConfigurationList section */
+/* Begin XCRemoteSwiftPackageReference section */
+ B55541E22C94F86A0015F522 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/sparkle-project/Sparkle";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 2.6.4;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ B55541E42C95801B0015F522 /* Sparkle */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = B55541E22C94F86A0015F522 /* XCRemoteSwiftPackageReference "Sparkle" */;
+ productName = Sparkle;
+ };
+/* End XCSwiftPackageProductDependency section */
+
/* Begin XCVersionGroup section */
B5278B3C2A74420F009F6462 /* Captura.xcdatamodeld */ = {
isa = XCVersionGroup;
--- /dev/null
+{
+ "originHash" : "e721da7f9826abdffcb6185e886155efa2514bd6234475f1afa893e29eb258d6",
+ "pins" : [
+ {
+ "identity" : "sparkle",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/sparkle-project/Sparkle",
+ "state" : {
+ "revision" : "0ef1ee0220239b3776f433314515fd849025673f",
+ "version" : "2.6.4"
+ }
+ }
+ ],
+ "version" : 3
+}
filePath = "Captura/CapturaApp.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "346"
- endingLineNumber = "346"
+ startingLineNumber = "356"
+ endingLineNumber = "356"
landmarkName = "failed(_:)"
landmarkType = "7">
</BreakpointContent>
filePath = "Captura/CapturaApp.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "291"
- endingLineNumber = "291"
- landmarkName = "startRecording()"
- landmarkType = "7">
- </BreakpointContent>
- </BreakpointProxy>
- <BreakpointProxy
- BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
- <BreakpointContent
- uuid = "A8CCA767-DD2D-482B-8F95-026C4A0BD9FA"
- shouldBeEnabled = "No"
- ignoreCount = "0"
- continueAfterRunningActions = "No"
- filePath = "Captura/Domain/CapturaCaptureSession.swift"
- startingColumnNumber = "9223372036854775807"
- endingColumnNumber = "9223372036854775807"
- startingLineNumber = "42"
- endingLineNumber = "42"
- landmarkName = "startRecording()"
- landmarkType = "7">
- </BreakpointContent>
- </BreakpointProxy>
- <BreakpointProxy
- BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
- <BreakpointContent
- uuid = "DE0C260E-5AA4-404B-B50E-83DAF27C9532"
- shouldBeEnabled = "No"
- ignoreCount = "0"
- continueAfterRunningActions = "No"
- filePath = "Captura/Domain/CapturaCaptureSession.swift"
- startingColumnNumber = "9223372036854775807"
- endingColumnNumber = "9223372036854775807"
- startingLineNumber = "37"
- endingLineNumber = "37"
+ startingLineNumber = "301"
+ endingLineNumber = "301"
landmarkName = "startRecording()"
landmarkType = "7">
</BreakpointContent>
import Cocoa
import Combine
import AVFoundation
+import Sparkle
@main
struct CapturaApp: App {
var remoteFiles: [CapturaRemoteFile] = []
var captureSessionConfiguration: CaptureSessionConfiguration = CaptureSessionConfiguration()
+ // Sparkle Configuration
+ @IBOutlet var checkForUpdatesMenuItem: NSMenuItem!
+ let updaterController: SPUStandardUpdaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
+
@objc dynamic var scriptedPreferences: ScriptedPreferences = ScriptedPreferences()
func applicationDidFinishLaunching(_ notification: Notification) {
statusItem.menu?.addItem(NSMenuItem.separator())
statusItem.menu?.addItem(NSMenuItem(title: "Open Local Folder", action: #selector(CapturaAppDelegate.onOpenFolder), keyEquivalent: ""))
statusItem.menu?.addItem(NSMenuItem.separator())
+
+ checkForUpdatesMenuItem = NSMenuItem(title: "Check for Updates", action: #selector(SPUStandardUpdaterController.checkForUpdates(_:)), keyEquivalent: "")
+ checkForUpdatesMenuItem.target = updaterController
+ statusItem.menu?.addItem(checkForUpdatesMenuItem)
+
statusItem.menu?.addItem(NSMenuItem(title: "Preferences", action: #selector(CapturaAppDelegate.onOpenPreferences), keyEquivalent: ""))
statusItem.menu?.addItem(NSMenuItem(title: "Quit", action: #selector(CapturaAppDelegate.onQuit), keyEquivalent: ""))
}
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>SUFeedURL</key>
+ <string>https://captura.tranquil.systems/appcast.xml</string>
+ <key>SUPublicEDKey</key>
+ <string>lacD9VFVjJO55y+hEy+ReU4S0xbrnbdhncui1qLsmfI=</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
--- /dev/null
+project_name := Captura
+derived_data_path := ~/Library/Developer/Xcode/DerivedData
+sparkle_path := $(shell find $(derived_data_path) -type d -path '*artifacts/sparkle/Sparkle' -print -quit)
+build_directory := builds
+sparkle_account := tranquil.systems
+
+
+distribute: archive package generate_appcast
+
+package:
+ @scripts/package.sh "$(project_name)" "$(build_directory)"
+
+generate_appcast:
+ @$(sparkle_path)/bin/generate_appcast --account $(sparkle_account) $(build_directory)
+
+archive: prepare
+ xcodebuild -project $(project_name).xcodeproj -scheme $(project_name) -configuration Release -archivePath $(build_directory)/$(project_name).xcarchive archive && xcodebuild -exportArchive -archivePath $(build_directory)/$(project_name).xcarchive -exportPath $(build_directory) -exportOptionsPlist export_options.plist
+
+prepare:
+ mkdir -p $(build_directory)
+
+.PHONY: package prepare archive generate_appcast package distribute
Any response code other than 201 Created will be treated as an error. Captura
will not re-attempt an upload.
+
+## Building
+
+For development, build the app using xcode. For release, a makefile is provided
+with commands to archive and package. If you just want the built and signed app
+you can use `make archive`. To generate the whole package use `make distribute`
+
+### Signing
+
+There's no automated handling of signing. For the app to be signed correctly,
+update the signing configuration in the xcode project.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>method</key>
+ <string>developer-id</string>
+ <key>signingStyle</key>
+ <string>automatic</string>
+</dict>
+</plist>
--- /dev/null
+#!/usr/bin/env bash
+
+set -e
+
+
+if [ "$#" -ne 2 ]; then
+ echo "Usage: $0 <project_name> <build_directory>"
+ exit 1
+fi
+
+project_name="$1"
+build_directory="$2"
+
+app_path="${build_directory}/${project_name}.app"
+app_version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ${app_path}/Contents/Info.plist)
+tmp_dir=$(mktemp -d)
+dmg_path="${build_directory}/${project_name}-${app_version}.dmg"
+cp -R "${app_path}" "${tmp_dir}"
+ln -s /Applications "${tmp_dir}/Applications"
+hdiutil create -volname "${project_name}" -srcfolder "${tmp_dir}" -ov -format UDZO "${dmg_path}"
+rm -rf "${tmp_dir}"