mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-15 08:50:57 +00:00
.
This commit is contained in:
parent
2efba1bc21
commit
be28d59873
@ -46,22 +46,16 @@ import Observation
|
||||
|
||||
/// Manually trigger an update check.
|
||||
public func checkForUpdates() async throws {
|
||||
let releaseData = try await withXPCCall(to: "com.maxgoedjen.Secretive.ReleasesDownloader", ReleasesDownloaderProtocol.self) {
|
||||
try await $0.downloadReleases()
|
||||
let session: XPCSession
|
||||
if #available(macOS 26.0, *) {
|
||||
session = try XPCSession(xpcService: "com.maxgoedjen.Secretive.ReleasesDownloader", requirement: .isFromSameTeam())
|
||||
} else {
|
||||
session = try XPCSession(xpcService: "com.maxgoedjen.Secretive.ReleasesDownloader")
|
||||
}
|
||||
let releases = try JSONDecoder().decode([Release].self, from: releaseData)
|
||||
await evaluate(releases: releases)
|
||||
await evaluate(releases: try await session.send())
|
||||
session.cancel(reason: "Done")
|
||||
}
|
||||
|
||||
func withXPCCall<ServiceProtocol, Result>(to service: String, _: ServiceProtocol.Type, closure: (ServiceProtocol) async throws -> Result) async rethrows -> Result {
|
||||
let connectionToService = NSXPCConnection(serviceName: "com.maxgoedjen.Secretive.ReleasesDownloader")
|
||||
connectionToService.remoteObjectInterface = NSXPCInterface(with: (any ReleasesDownloaderProtocol).self)// fixme
|
||||
connectionToService.resume()
|
||||
let service = connectionToService.remoteObjectProxy as! ServiceProtocol
|
||||
let result = try await closure(service)
|
||||
connectionToService.invalidate()
|
||||
return result
|
||||
}
|
||||
|
||||
/// Ignores a specified release. `update` will be nil if the user has ignored the latest available release.
|
||||
/// - Parameter release: The release to ignore.
|
||||
@ -110,3 +104,32 @@ extension Updater {
|
||||
|
||||
}
|
||||
|
||||
private extension XPCSession {
|
||||
|
||||
func send<Response: Decodable & Sendable>(_ message: some Encodable = XPCSession.emptyMessage) async throws -> Response {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
do {
|
||||
try send(message) { result in
|
||||
switch result {
|
||||
case .success(let message):
|
||||
do {
|
||||
let decoded = try message.decode(as: Response.self)
|
||||
continuation.resume(returning: decoded)
|
||||
} catch {
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static var emptyMessage: some Encodable {
|
||||
Data()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import Foundation
|
||||
import Brief
|
||||
|
||||
final class ReleasesDownloader: NSObject, ReleasesDownloaderProtocol {
|
||||
|
||||
@objc func downloadReleases(with reply: @escaping (Data?, (any Error)?) -> Void) {
|
||||
Task {
|
||||
do {
|
||||
let (data, _) = try await URLSession.shared.data(from: Constants.updateURL)
|
||||
let releases = try JSONDecoder().decode([Release].self, from: data)
|
||||
print(releases)
|
||||
let jsonOut = try JSONEncoder().encode(releases)
|
||||
reply(jsonOut, nil)
|
||||
} catch {
|
||||
reply(nil, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ReleasesDownloader {
|
||||
|
||||
enum Constants {
|
||||
static let updateURL = URL(string: "https://api.github.com/repos/maxgoedjen/secretive/releases")!
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +1,44 @@
|
||||
import Foundation
|
||||
import XPC
|
||||
import OSLog
|
||||
import Brief
|
||||
|
||||
class ServiceDelegate: NSObject, NSXPCListenerDelegate {
|
||||
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.ReleasesDownloader", category: "ReleasesDownloader")
|
||||
|
||||
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
|
||||
newConnection.exportedInterface = NSXPCInterface(with: (any ReleasesDownloaderProtocol).self)
|
||||
let exportedObject = ReleasesDownloader()
|
||||
newConnection.exportedObject = exportedObject
|
||||
newConnection.resume()
|
||||
return true
|
||||
enum Constants {
|
||||
static let updateURL = URL(string: "https://api.github.com/repos/maxgoedjen/secretive/releases")!
|
||||
}
|
||||
|
||||
func handleRequest(_ request: XPCListener.IncomingSessionRequest) -> XPCListener.IncomingSessionRequest.Decision {
|
||||
logger.log("ReleasesDownloader received inbound request")
|
||||
return request.accept { xpcDictionary in
|
||||
xpcDictionary.handoffReply(to: .global(qos: .userInteractive)) {
|
||||
logger.log("ReleasesDownloader accepted inbound request")
|
||||
Task {
|
||||
do {
|
||||
let (data, _) = try await URLSession.shared.data(from: Constants.updateURL)
|
||||
let releases = try JSONDecoder().decode([Release].self, from: data)
|
||||
xpcDictionary.reply(releases)
|
||||
} catch {
|
||||
logger.error("ReleasesDownloader failed with unknown error \(error)")
|
||||
xpcDictionary.reply([] as [Release])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let delegate = ServiceDelegate()
|
||||
let listener = NSXPCListener.service()
|
||||
listener.delegate = delegate
|
||||
listener.resume()
|
||||
do {
|
||||
if #available(macOS 26.0, *) {
|
||||
_ = try XPCListener(
|
||||
service: "com.maxgoedjen.Secretive.ReleasesDownloader",
|
||||
requirement: .isFromSameTeam(),
|
||||
incomingSessionHandler: handleRequest(_:)
|
||||
)
|
||||
} else {
|
||||
_ = try XPCListener(service: "com.maxgoedjen.Secretive.ReleasesDownloader", incomingSessionHandler: handleRequest(_:))
|
||||
}
|
||||
logger.log("ReleasesDownloader initialized")
|
||||
dispatchMain()
|
||||
} catch {
|
||||
logger.error("Failed to create ReleasesDownloader, error: \(error)")
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import SecretAgentKit
|
||||
import Brief
|
||||
|
||||
/// Delegates all agent input parsing to an XPC service which wraps OpenSSH
|
||||
public final class XPCAgentInputParser: SSHAgentInputParserProtocol {
|
||||
@ -16,7 +17,6 @@ public final class XPCAgentInputParser: SSHAgentInputParserProtocol {
|
||||
Task {
|
||||
// Warm up the XPC endpoint.
|
||||
_ = try? await parse(data: Data())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
501577C82E6BC5B4004A37D0 /* ReleasesDownloader.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 501577BD2E6BC5B4004A37D0 /* ReleasesDownloader.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
501577CF2E6BC5D4004A37D0 /* ReleasesDownloader.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 501577BD2E6BC5B4004A37D0 /* ReleasesDownloader.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
501577DA2E6BC5F3004A37D0 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501577D62E6BC5F3004A37D0 /* main.swift */; };
|
||||
501577DB2E6BC5F3004A37D0 /* ReleasesDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501577D72E6BC5F3004A37D0 /* ReleasesDownloader.swift */; };
|
||||
501577DF2E6BC647004A37D0 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 501577DE2E6BC647004A37D0 /* Brief */; };
|
||||
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501578122E6C0479004A37D0 /* XPCInputParser.swift */; };
|
||||
5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; };
|
||||
@ -180,7 +179,6 @@
|
||||
501577BD2E6BC5B4004A37D0 /* ReleasesDownloader.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = ReleasesDownloader.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
501577D52E6BC5F3004A37D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
501577D62E6BC5F3004A37D0 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
501577D72E6BC5F3004A37D0 /* ReleasesDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleasesDownloader.swift; sourceTree = "<group>"; };
|
||||
501578122E6C0479004A37D0 /* XPCInputParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCInputParser.swift; sourceTree = "<group>"; };
|
||||
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
|
||||
504788EB2E680DC400B4556F /* URLs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLs.swift; sourceTree = "<group>"; };
|
||||
@ -293,7 +291,6 @@
|
||||
children = (
|
||||
501577D52E6BC5F3004A37D0 /* Info.plist */,
|
||||
501577D62E6BC5F3004A37D0 /* main.swift */,
|
||||
501577D72E6BC5F3004A37D0 /* ReleasesDownloader.swift */,
|
||||
);
|
||||
path = ReleasesDownloader;
|
||||
sourceTree = "<group>";
|
||||
@ -674,7 +671,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
501577DA2E6BC5F3004A37D0 /* main.swift in Sources */,
|
||||
501577DB2E6BC5F3004A37D0 /* ReleasesDownloader.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user