diff --git a/kordophone2.xcodeproj/project.pbxproj b/kordophone2.xcodeproj/project.pbxproj index 542da4d..3f6c97e 100644 --- a/kordophone2.xcodeproj/project.pbxproj +++ b/kordophone2.xcodeproj/project.pbxproj @@ -10,13 +10,70 @@ CD41F5D32E62431D00E0027B /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = CD41F5D22E62431D00E0027B /* KeychainAccess */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + CD41F5D92E6284FD00E0027B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Contents/Library/LaunchAgents; + dstSubfolderSpec = 1; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CD41F5DD2E6285E800E0027B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 6; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ CD41F5972E5B8E7300E0027B /* kordophone2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = kordophone2.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + CD41F5DA2E62850100E0027B /* Exceptions for "kordophone2" folder in "kordophone2" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Daemon/kordophoned, + Daemon/net.buzzert.kordophonecd.plist, + ); + target = CD41F5962E5B8E7300E0027B /* kordophone2 */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + CD41F5DC2E62853800E0027B /* Exceptions for "kordophone2" folder in "Copy Files" phase from "kordophone2" target */ = { + isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; + buildPhase = CD41F5D92E6284FD00E0027B /* CopyFiles */; + membershipExceptions = ( + Daemon/net.buzzert.kordophonecd.plist, + ); + }; + CD41F5E12E62860700E0027B /* Exceptions for "kordophone2" folder in "Copy Files" phase from "kordophone2" target */ = { + isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; + attributesByRelativePath = { + Daemon/kordophoned = (CodeSignOnCopy, ); + }; + buildPhase = CD41F5DD2E6285E800E0027B /* CopyFiles */; + membershipExceptions = ( + Daemon/kordophoned, + ); + }; +/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + /* Begin PBXFileSystemSynchronizedRootGroup section */ CD41F5992E5B8E7300E0027B /* kordophone2 */ = { isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + CD41F5DA2E62850100E0027B /* Exceptions for "kordophone2" folder in "kordophone2" target */, + CD41F5DC2E62853800E0027B /* Exceptions for "kordophone2" folder in "Copy Files" phase from "kordophone2" target */, + CD41F5E12E62860700E0027B /* Exceptions for "kordophone2" folder in "Copy Files" phase from "kordophone2" target */, + ); path = kordophone2; sourceTree = ""; }; @@ -60,6 +117,8 @@ CD41F5932E5B8E7300E0027B /* Sources */, CD41F5942E5B8E7300E0027B /* Frameworks */, CD41F5952E5B8E7300E0027B /* Resources */, + CD41F5D92E6284FD00E0027B /* CopyFiles */, + CD41F5DD2E6285E800E0027B /* CopyFiles */, ); buildRules = ( ); @@ -264,7 +323,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = DQQH5H6GBD; - ENABLE_HARDENED_RUNTIME = YES; + ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; @@ -291,7 +350,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = DQQH5H6GBD; - ENABLE_HARDENED_RUNTIME = YES; + ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; diff --git a/kordophone2/Daemon/kordophoned b/kordophone2/Daemon/kordophoned new file mode 100755 index 0000000..8d02d59 Binary files /dev/null and b/kordophone2/Daemon/kordophoned differ diff --git a/kordophone2/Daemon/net.buzzert.kordophonecd.plist b/kordophone2/Daemon/net.buzzert.kordophonecd.plist new file mode 100644 index 0000000..c112e26 --- /dev/null +++ b/kordophone2/Daemon/net.buzzert.kordophonecd.plist @@ -0,0 +1,26 @@ + + + + + Label + net.buzzert.kordophonecd + BundleProgram + Contents/MacOS/kordophoned + EnvironmentVariables + + RUST_LOG + info + + MachServices + + net.buzzert.kordophonecd + + + KeepAlive + + StandardOutPath + /tmp/kordophoned.out.log + StandardErrorPath + /tmp/kordophoned.err.log + + diff --git a/kordophone2/MessageEntryView.swift b/kordophone2/MessageEntryView.swift index 30192f5..549d9db 100644 --- a/kordophone2/MessageEntryView.swift +++ b/kordophone2/MessageEntryView.swift @@ -19,7 +19,7 @@ struct MessageEntryView: View .frame(height: 1.0) HStack { - TextField("", text: $viewModel.draftText, axis: .vertical) + TextField("iMessage", text: $viewModel.draftText, axis: .vertical) .focusEffectDisabled(true) .textFieldStyle(.plain) .lineLimit(nil) @@ -30,7 +30,7 @@ struct MessageEntryView: View .padding(8.0) .disabled(selectedConversation == nil) .background { - RoundedRectangle(cornerRadius: 6.0) + RoundedRectangle(cornerRadius: 8.0) .stroke(SeparatorShapeStyle()) .fill(.background) } diff --git a/kordophone2/Supporting Files/kordophone2.entitlements b/kordophone2/Supporting Files/kordophone2.entitlements index 8f230e7..da519ee 100644 --- a/kordophone2/Supporting Files/kordophone2.entitlements +++ b/kordophone2/Supporting Files/kordophone2.entitlements @@ -6,6 +6,8 @@ com.apple.security.files.user-selected.read-only + com.apple.security.network.client + com.apple.security.temporary-exception.mach-lookup.global-name net.buzzert.kordophonecd diff --git a/kordophone2/Transcript/TranscriptView.swift b/kordophone2/Transcript/TranscriptView.swift index 129e1ba..0fb6ff6 100644 --- a/kordophone2/Transcript/TranscriptView.swift +++ b/kordophone2/Transcript/TranscriptView.swift @@ -29,6 +29,7 @@ struct TranscriptView: View .padding() } .scaleEffect(CGSize(width: 1.0, height: -1.0)) + .id(model.displayedConversation) .task { await watchForMessageListChanges() } } @@ -103,7 +104,7 @@ struct TranscriptView: View func attachmentDownloaded(id: String) { // TODO: should be smarter here - setNeedsReload(animated: true) + setNeedsReload(animated: false) } private func observeDisplayedConversation() { diff --git a/kordophone2/XPC/XPCClient.swift b/kordophone2/XPC/XPCClient.swift index 0b66ffc..068b298 100644 --- a/kordophone2/XPC/XPCClient.swift +++ b/kordophone2/XPC/XPCClient.swift @@ -6,18 +6,35 @@ // import Foundation +import ServiceManagement import XPC private let serviceName = "net.buzzert.kordophonecd" + final class XPCClient { private let connection: xpc_connection_t private let signalLock = NSLock() private var signalSinks: [UUID: (Signal) -> Void] = [:] private var didSubscribeSignals: Bool = false + + static let appService: SMAppService = { + do { + let service = SMAppService.agent(plistName: "net.buzzert.kordophonecd.plist") + if service.status != .enabled { + try service.register() + } + + return service + } catch { + fatalError("Unable to register agent: \(error)") + } + }() init() { + _ = Self.appService + self.connection = xpc_connection_create_mach_service(serviceName, nil, 0) let handler: xpc_handler_t = { [weak self] event in