Private
Public Access
1
0

Get swifty

This commit is contained in:
2025-08-24 18:54:50 -07:00
parent b38df68eb2
commit 126a4cc55f
3 changed files with 94 additions and 53 deletions

View File

@@ -93,16 +93,13 @@ enum Serialized
init?(xpc dict: xpc_object_t) init?(xpc dict: xpc_object_t)
{ {
guard let g: String = dict["guid"] else { return nil } guard let d = XPCDictionary(dict), let g: String = d["guid"] else { return nil }
let dn: String? = dict["display_name"] let dn: String? = d["display_name"]
let lmp: String? = dict["last_message_preview"] let lmp: String? = d["last_message_preview"]
let names: [String] = d["participants"] ?? []
let names: [String] = dict["participants"] ?? [] let unread: Int = d["unread_count"] ?? 0
let dt: Date = d["date"] ?? Date(timeIntervalSince1970: 0)
let unread: Int = dict["unread_count"] ?? 0
let dt: Date = dict["date"] ?? Date(timeIntervalSince1970: 0)
self.guid = g self.guid = g
self.displayName = dn self.displayName = dn
@@ -122,16 +119,16 @@ enum Serialized
init?(xpc dict: xpc_object_t) init?(xpc dict: xpc_object_t)
{ {
guard let g: String = dict["id"] else { return nil } guard let d = XPCDictionary(dict), let g: String = d["id"] else { return nil }
let s: String = dict["sender"] ?? "" let s: String = d["sender"] ?? ""
let t: String = dict["text"] ?? "" let t: String = d["text"] ?? ""
let d: Date = dict["date"] ?? Date(timeIntervalSince1970: 0) let dd: Date = d["date"] ?? Date(timeIntervalSince1970: 0)
self.guid = g self.guid = g
self.sender = s self.sender = s
self.text = t self.text = t
self.date = d self.date = dd
} }
} }
} }

View File

@@ -182,48 +182,48 @@ extension XPCClient
} }
private func handleIncomingXPCEvent(_ event: xpc_object_t) { private func handleIncomingXPCEvent(_ event: xpc_object_t) {
let type = xpc_get_type(event) switch xpc_get_type(event) {
switch type { case XPC_TYPE_DICTIONARY:
case XPC_TYPE_DICTIONARY: guard let eventDict = XPCDictionary(event), let name: String = eventDict["name"] else { return }
guard let namePtr = xpc_dictionary_get_string(event, "name") else { return }
let name = String(cString: namePtr)
var signal: Signal? let args = eventDict.object("arguments").flatMap { XPCDictionary($0) }
if name == "ConversationsUpdated" { let signal: Signal? = {
signal = .conversationsUpdated switch name {
} else if name == "MessagesUpdated" { case "ConversationsUpdated":
if let args = xpc_dictionary_get_value(event, "arguments"), xpc_get_type(args) == XPC_TYPE_DICTIONARY, return .conversationsUpdated
let cidPtr = xpc_dictionary_get_string(args, "conversation_id") { case "MessagesUpdated":
signal = .messagesUpdated(conversationId: String(cString: cidPtr)) if let args, let cid: String = args["conversation_id"] { return .messagesUpdated(conversationId: cid) }
return nil
case "AttachmentDownloadCompleted":
if let args, let aid: String = args["attachment_id"] { return .attachmentDownloaded(attachmentId: aid) }
return nil
case "AttachmentUploadCompleted":
if let args,
let uploadGuid: String = args["upload_guid"],
let attachmentGuid: String = args["attachment_guid"] {
return .attachmentUploaded(uploadGuid: uploadGuid, attachmentGuid: attachmentGuid)
} }
} else if name == "AttachmentDownloadCompleted" { return nil
if let args = xpc_dictionary_get_value(event, "arguments"), xpc_get_type(args) == XPC_TYPE_DICTIONARY, case "UpdateStreamReconnected":
let aidPtr = xpc_dictionary_get_string(args, "attachment_id") { return .updateStreamReconnected
signal = .attachmentDownloaded(attachmentId: String(cString: aidPtr)) default:
} return nil
} else if name == "AttachmentUploadCompleted" {
if let args = xpc_dictionary_get_value(event, "arguments"), xpc_get_type(args) == XPC_TYPE_DICTIONARY,
let ugPtr = xpc_dictionary_get_string(args, "upload_guid"),
let agPtr = xpc_dictionary_get_string(args, "attachment_guid") {
signal = .attachmentUploaded(uploadGuid: String(cString: ugPtr), attachmentGuid: String(cString: agPtr))
}
} else if name == "UpdateStreamReconnected" {
signal = .updateStreamReconnected
} }
}()
if let signal { if let signal {
signalLock.lock() signalLock.lock()
let sinks = signalSinks.values let sinks = signalSinks.values
signalLock.unlock() signalLock.unlock()
for sink in sinks { sink(signal) } for sink in sinks { sink(signal) }
} }
case XPC_TYPE_ERROR: case XPC_TYPE_ERROR:
if let errStr = xpc_string_get_string_ptr(event) { if let errStr = xpc_string_get_string_ptr(event) {
print("XPC event error: \(String(cString: errStr))") print("XPC event error: \(String(cString: errStr))")
} }
default: default:
break break
} }
} }
} }

View File

@@ -78,6 +78,15 @@ extension Array: XPCConvertible where Element: XPCConvertible
extension xpc_object_t extension xpc_object_t
{ {
func getObject(_ key: String) -> xpc_object_t? {
var raw: xpc_object_t?
key.withCString { cKey in
raw = xpc_dictionary_get_value(self, cKey)
}
return raw
}
func get<T: XPCConvertible>(_ key: String) -> T? { func get<T: XPCConvertible>(_ key: String) -> T? {
var raw: xpc_object_t? var raw: xpc_object_t?
key.withCString { cKey in key.withCString { cKey in
@@ -88,7 +97,42 @@ extension xpc_object_t
return T.fromXPC(value) return T.fromXPC(value)
} }
subscript<T: XPCConvertible>(key: String) -> T? { subscript<T: XPCConvertible>(key: String) -> T? { return get(key) }
return get(key)
var isDictionary: Bool { xpc_get_type(self) == XPC_TYPE_DICTIONARY }
var isArray: Bool { xpc_get_type(self) == XPC_TYPE_ARRAY }
}
// MARK: - Dictionary wrapper
struct XPCDictionary
{
let raw: xpc_object_t
init?(_ value: xpc_object_t) {
guard xpc_get_type(value) == XPC_TYPE_DICTIONARY else { return nil }
self.raw = value
}
func object(_ key: String) -> xpc_object_t? {
var rawValue: xpc_object_t?
key.withCString { cKey in
rawValue = xpc_dictionary_get_value(raw, cKey)
}
return rawValue
}
func get<T: XPCConvertible>(_ key: String) -> T? {
guard let value = object(key) else { return nil }
return T.fromXPC(value)
}
subscript<T: XPCConvertible>(_ key: String) -> T? { return get(key) }
}
extension XPCDictionary
{
static func wrap(_ value: xpc_object_t) -> XPCDictionary? {
return XPCDictionary(value)
} }
} }