Compare commits

..
1 Commits
Author SHA1 Message Date
Ian 9f57dbf29a Prompt to update when a newer release is out 2026-11-13 15:22:11 -05:00
5 changed files with 55 additions and 4 deletions

No files matched your search

+13
View File
@@ -55,6 +55,7 @@ final class FirewallModel: NSObject, ObservableObject {
@Published private(set) var removed = false
@Published private(set) var screening = false
@Published private(set) var blocked: [BlockedPackage] = []
@Published private(set) var update: String?
private let logger = Logger(subsystem: FirewallIDs.appBundleID, category: "installer")
private var pendingRequest: (request: OSSystemExtensionRequest, continuation: CheckedContinuation<Void, Error>)?
@@ -76,6 +77,7 @@ final class FirewallModel: NSObject, ObservableObject {
Task { await install() }
}
Task { await watchBlocks() }
Task { await watchUpdates() }
}
// MARK: - Flows
@@ -246,6 +248,17 @@ final class FirewallModel: NSObject, ObservableObject {
}
}
/// Asks again every day until the user updates.
private func watchUpdates() async {
while true {
if let version = await Updates.available() {
update = version
Updates.prompt(version)
}
try? await Task.sleep(nanoseconds: 86_400_000_000_000)
}
}
private func stage(_ step: ReferenceWritableKeyPath<FirewallModel, StepStatus>,
running: String,
work: @MainActor () async throws -> String) async -> Bool {
+6
View File
@@ -7,6 +7,12 @@ struct MenuBarView: View {
var body: some View {
Text(model.screening ? "Screening downloads" : "Not running")
if let version = model.update {
Button("Update to \(version)") {
Updates.download(version)
}
}
Divider()
Button("Setup") {
+32
View File
@@ -0,0 +1,32 @@
import AppKit
enum Updates {
static let current = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
private struct Release: Decodable {
let tag_name: String
}
/// The latest release's version, when it is newer than this app.
static func available() async -> String? {
let latest = URL(string: "https://api.github.com/repos/usestrix/firewall/releases/latest")!
guard let (data, _) = try? await URLSession.shared.data(from: latest),
let release = try? JSONDecoder().decode(Release.self, from: data) else { return nil }
let version = release.tag_name.hasPrefix("v") ? String(release.tag_name.dropFirst()) : release.tag_name
return version.compare(current, options: .numeric) == .orderedDescending ? version : nil
}
static func download(_ version: String) {
NSWorkspace.shared.open(URL(string: "https://github.com/usestrix/firewall/releases/download/v\(version)/Firewall.pkg")!)
}
@MainActor static func prompt(_ version: String) {
let alert = NSAlert()
alert.messageText = "Firewall \(version) is available"
alert.informativeText = "You have \(current). Download the installer and open it to update."
alert.addButton(withTitle: "Download")
alert.addButton(withTitle: "Later")
NSApp.activate(ignoringOtherApps: true)
if alert.runModal() == .alertFirstButtonReturn { download(version) }
}
}
+2 -2
View File
@@ -28,7 +28,7 @@ export NE_PROVIDER
APP_ID=com.usestrix.firewall
EXT_ID=com.usestrix.firewall.extension
VERSION=0.1
VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' ../core/Cargo.toml)
INSTALLER_IDENTITY=${INSTALLER_IDENTITY:-Developer ID Installer}
PROFILES="$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"
@@ -48,7 +48,7 @@ build() {
xcodegen generate >/dev/null
xcodebuild -project Firewall.xcodeproj -scheme StrixFirewall -configuration $CONFIGURATION \
-destination generic/platform=macOS \
-derivedDataPath build CURRENT_PROJECT_VERSION="$(date +%s)" CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO \
-derivedDataPath build CURRENT_PROJECT_VERSION="$(date +%s)" MARKETING_VERSION="$VERSION" CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_IDENTITY="" CODE_SIGN_ENTITLEMENTS="" build >/dev/null
}
+2 -2
View File
@@ -43,7 +43,7 @@ targets:
path: Extension/Info.plist
properties:
CFBundlePackageType: SYSX
CFBundleShortVersionString: "0.1"
CFBundleShortVersionString: $(MARKETING_VERSION)
CFBundleVersion: $(CURRENT_PROJECT_VERSION)
NSSystemExtensionUsageDescription: Firewall uses a network extension to screen package downloads before they install.
NetworkExtension:
@@ -104,7 +104,7 @@ targets:
info:
path: App/Info.plist
properties:
CFBundleShortVersionString: "0.1"
CFBundleShortVersionString: $(MARKETING_VERSION)
CFBundleVersion: $(CURRENT_PROJECT_VERSION)
LSMinimumSystemVersion: $(MACOSX_DEPLOYMENT_TARGET)
NSSystemExtensionUsageDescription: Firewall uses a network extension to screen package downloads before they install.