diff --git a/FrameworkTests/TerminalCommandDraftControllerTests.swift b/FrameworkTests/TerminalCommandDraftControllerTests.swift
index f0f9a12f..d51002f7 100644
--- a/FrameworkTests/TerminalCommandDraftControllerTests.swift
+++ b/FrameworkTests/TerminalCommandDraftControllerTests.swift
@@ -13,7 +13,7 @@ struct TerminalCommandDraftControllerTests {
writes.append(data)
}
}
- await Task.yield()
+ while !controller.hasPendingRequest { await Task.yield() }
await #expect(throws: TerminalDraftError.self) {
try await controller.read(isAvailable: true) { _ in }
@@ -39,7 +39,7 @@ struct TerminalCommandDraftControllerTests {
let read = Task {
try await controller.read(isAvailable: true) { _ in }
}
- await Task.yield()
+ while !controller.hasPendingRequest { await Task.yield() }
controller.cancel(CancellationError())
diff --git a/Frameworks/Resources/Localizable.xcstrings b/Frameworks/Resources/Localizable.xcstrings
index 8f0ec840..de274853 100644
--- a/Frameworks/Resources/Localizable.xcstrings
+++ b/Frameworks/Resources/Localizable.xcstrings
@@ -7696,7 +7696,6 @@
}
},
"Discard Changes" : {
- "extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
@@ -7713,7 +7712,6 @@
}
},
"Discard Changes?" : {
- "extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
@@ -26998,4 +26996,4 @@
}
},
"version" : "1.2"
-}
\ No newline at end of file
+}
diff --git a/Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift b/Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift
index 7a6514f1..d7755eac 100644
--- a/Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift
+++ b/Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift
@@ -44,8 +44,6 @@ public protocol RemoteSessionHostStore: AnyObject, Sendable {
func upsert(_ host: Host)
}
-extension HostLibraryModel: RemoteSessionHostStore {}
-
extension RemoteSessionHostStore {
public func expectedHostKeys(
for host: Host, temporaryHostKeys: [Host.ID: SSHHostKeyIdentity]
diff --git a/Frameworks/TermindApplication/FeatureModels/HostLibraryModel.swift b/Frameworks/TermindApplication/FeatureModels/HostLibraryModel.swift
index 924b6aea..17416607 100644
--- a/Frameworks/TermindApplication/FeatureModels/HostLibraryModel.swift
+++ b/Frameworks/TermindApplication/FeatureModels/HostLibraryModel.swift
@@ -9,7 +9,7 @@ import struct TermindDomain.Host
/// Core host metadata is backed by SwiftData in the app and projected into value
/// types for the views. Previews can still construct an in-memory store directly.
@Observable
-public final class HostLibraryModel {
+public final class HostLibraryModel: RemoteSessionHostStore {
public private(set) var hosts: [Host] = []
public private(set) var groups: [HostGroup] = []
public private(set) var keys: [SSHKeyRef] = []
diff --git a/Frameworks/TermindRemoteInfrastructure/SSH/SSHSessionActor.swift b/Frameworks/TermindRemoteInfrastructure/SSH/SSHSessionActor.swift
index f3a47cc3..23c66dfd 100644
--- a/Frameworks/TermindRemoteInfrastructure/SSH/SSHSessionActor.swift
+++ b/Frameworks/TermindRemoteInfrastructure/SSH/SSHSessionActor.swift
@@ -53,19 +53,18 @@ public nonisolated struct RemoteShellIntegrationBootstrap: Sendable {
// The POSIX helper reads os-release as inert assignment text instead of
// sourcing it. Its output precedes the shell marker, so a missing `sh`
// still leaves the original shell-only bootstrap path usable.
- startCommand = Data(
- (" command sh -c 'f=; did=; dlike=; dver=; "
- + "[ -r /etc/os-release ] && f=/etc/os-release; "
- + "[ -z \"$f\" ] && [ -r /usr/lib/os-release ] && f=/usr/lib/os-release; "
- + "if [ -n \"$f\" ]; then while IFS= read -r line; do case \"$line\" in "
- + "ID=*) did=${line#ID=} ;; ID_LIKE=*) dlike=${line#ID_LIKE=} ;; "
- + "VERSION_ID=*) dver=${line#VERSION_ID=} ;; esac; "
- + "done < \"$f\"; fi; kn=$(uname -s 2>/dev/null); "
- + "kr=$(uname -r 2>/dev/null); ka=$(uname -m 2>/dev/null); "
- + "printf \"\\n__TRMD_%s_SYSTEM__%s|%s|%s|%s|%s|%s__\\n\" "
- + "\"$1\" \"$did\" \"$dlike\" \"$dver\" \"$kn\" \"$kr\" \"$ka\"' sh '\(token)'; "
- + "printf '\\n__TRMD_%s_SHELL__%s__\\n' '\(token)' \"$SHELL\"\n").utf8
- )
+ var probeCommand = " command sh -c 'f=; did=; dlike=; dver=; "
+ probeCommand += "[ -r /etc/os-release ] && f=/etc/os-release; "
+ probeCommand += "[ -z \"$f\" ] && [ -r /usr/lib/os-release ] && f=/usr/lib/os-release; "
+ probeCommand += "if [ -n \"$f\" ]; then while IFS= read -r line; do case \"$line\" in "
+ probeCommand += "ID=*) did=${line#ID=} ;; ID_LIKE=*) dlike=${line#ID_LIKE=} ;; "
+ probeCommand += "VERSION_ID=*) dver=${line#VERSION_ID=} ;; esac; "
+ probeCommand += "done < \"$f\"; fi; kn=$(uname -s 2>/dev/null); "
+ probeCommand += "kr=$(uname -r 2>/dev/null); ka=$(uname -m 2>/dev/null); "
+ probeCommand += "printf \"\\n__TRMD_%s_SYSTEM__%s|%s|%s|%s|%s|%s__\\n\" "
+ probeCommand += "\"$1\" \"$did\" \"$dlike\" \"$dver\" \"$kn\" \"$kr\" \"$ka\"' sh '\(token)'; "
+ probeCommand += "printf '\\n__TRMD_%s_SHELL__%s__\\n' '\(token)' \"$SHELL\"\n"
+ startCommand = Data(probeCommand.utf8)
deadline = now + Self.responseTimeout
}
diff --git a/TFI/Features/Workspaces/MobileWorkspace.swift b/TFI/Features/Workspaces/MobileWorkspace.swift
index b978d5c4..2b6076b2 100644
--- a/TFI/Features/Workspaces/MobileWorkspace.swift
+++ b/TFI/Features/Workspaces/MobileWorkspace.swift
@@ -552,8 +552,8 @@ final class MobileWorkspace: Identifiable {
self?.generation == $0
}
connection.clearHostKeyPrompt()
- attempt = Task { [weak self] in
- guard let self else { return }
+ attempt = Task { [weak self, weak hosts] in
+ guard let self, let hosts else { return }
defer { if generation == token { busy = false } }
guard generation == token, !Task.isCancelled else { return }
do {
diff --git a/TFI/Info.plist b/TFI/Info.plist
index 36ea3147..ea6b0134 100644
--- a/TFI/Info.plist
+++ b/TFI/Info.plist
@@ -13,10 +13,6 @@
- NSFaceIDUsageDescription
- Authenticate to use your SSH keys.
- NSSupportsLiveActivities
-
TermindCloudKitEnvironment
$(ICLOUD_CONTAINER_ENVIRONMENT)
TermindKeychainAccessGroup
@@ -36,12 +32,6 @@
remote-notification
- NSMicrophoneUsageDescription
- Termind uses the microphone to transcribe speech into your chat draft.
- NSSpeechRecognitionUsageDescription
- Termind uses Apple Speech Recognition to turn your recording into text. Depending on system settings and language support, Apple may process the audio online.
- NSCameraUsageDescription
- Termind uses the camera to attach photos to your chat.
UTExportedTypeDeclarations
diff --git a/TFI/UI/Components/MobileNativeList.swift b/TFI/UI/Components/MobileNativeList.swift
index 4e2345be..37bb5090 100644
--- a/TFI/UI/Components/MobileNativeList.swift
+++ b/TFI/UI/Components/MobileNativeList.swift
@@ -214,8 +214,6 @@ where Item: Identifiable & Hashable & SendableMetatype, RowContent: View {
}
}
- @_optimize(none) deinit {}
-
func update(
listView: ListView- , items newItems: [Item], renderer: @escaping Renderer,
onSelect: ((Item) -> Void)?,
diff --git a/TFM/App/RootView.swift b/TFM/App/RootView.swift
index f50e1f1a..a170bf40 100644
--- a/TFM/App/RootView.swift
+++ b/TFM/App/RootView.swift
@@ -160,7 +160,8 @@ struct RootView: View {
window.refreshSessionContext()
window.reconcileSidebarMode()
}
- .onAppear {
+ .onAppear { [weak app] in
+ guard let app else { return }
window.proAccess = app.proAccess
window.connectionCoordinator = app.connections
window.hostStore = app.hostLibrary
diff --git a/TFM/Features/SFTP/SFTPSessionModel.swift b/TFM/Features/SFTP/SFTPSessionModel.swift
index 31712794..1387a377 100644
--- a/TFM/Features/SFTP/SFTPSessionModel.swift
+++ b/TFM/Features/SFTP/SFTPSessionModel.swift
@@ -347,8 +347,8 @@ final class SFTPSessionModel: Identifiable {
hint =
reconnecting
? String(localized: "Reconnecting") : String(localized: "Connecting")
- connectionTask = Task { [weak self] in
- guard let self else { return }
+ connectionTask = Task { [weak self, weak store] in
+ guard let self, let store else { return }
do {
let configuration: SSHConnectionConfiguration
if let suppliedAuthentication {
diff --git a/TFM/Features/Terminal/SSHSessionModel.swift b/TFM/Features/Terminal/SSHSessionModel.swift
index 7c9ec9da..c2da9fa2 100644
--- a/TFM/Features/Terminal/SSHSessionModel.swift
+++ b/TFM/Features/Terminal/SSHSessionModel.swift
@@ -573,8 +573,8 @@ final class SSHSessionModel: Identifiable {
connection.clearHostKeyPrompt()
connectionTask?.cancel()
status = reconnecting ? .reconnecting : .connecting
- connectionTask = Task { [weak self] in
- guard let self else { return }
+ connectionTask = Task { [weak self, weak store] in
+ guard let self, let store else { return }
do {
try await openSSH(
host: host, username: username, credentials: credentials,
diff --git a/TFM/UI/Components/HostingListRow.swift b/TFM/UI/Components/HostingListRow.swift
index debab220..78dfc5bb 100644
--- a/TFM/UI/Components/HostingListRow.swift
+++ b/TFM/UI/Components/HostingListRow.swift
@@ -42,9 +42,6 @@ where
private var colorScheme = ColorScheme.light
private var items: [Item] = []
- // Swift 6.3.3's optimizer can crash while synthesizing generic deinit.
- @_optimize(none) deinit {}
-
@discardableResult
func update(
_ listView: ListView
- , items newItems: [Item], renderer: @escaping Renderer,
diff --git a/TFM/UI/Components/ManagedChooser.swift b/TFM/UI/Components/ManagedChooser.swift
index dd955f0e..9f65c14b 100644
--- a/TFM/UI/Components/ManagedChooser.swift
+++ b/TFM/UI/Components/ManagedChooser.swift
@@ -17,11 +17,6 @@ final class ManagedChooserState {
self.selected = selected
}
- // Swift 6.3.3's EarlyPerfInliner crashes while synthesizing this generic
- // class's optimized destructor. Keeping just the destructor unoptimized
- // preserves normal release optimization for the chooser and the app.
- @_optimize(none) deinit {}
-
func activate(_ id: ID) {
cursor = id
switch mode {
diff --git a/TFMTests/StoreKitTrialTests.swift b/TFMTests/StoreKitTrialTests.swift
index b797236f..9568b3a3 100644
--- a/TFMTests/StoreKitTrialTests.swift
+++ b/TFMTests/StoreKitTrialTests.swift
@@ -50,8 +50,8 @@ struct StoreKitTrialTests {
@Test
func lifetimePurchaseTakesPrecedenceOverAnnualSubscription() async throws {
let fixture = try Fixture()
- try await fixture.session.buyProduct(identifier: ProAccessController.annualProductID)
- try await fixture.session.buyProduct(identifier: ProAccessController.lifetimeProductID)
+ try await fixture.purchase(ProAccessController.annualProductID)
+ try await fixture.purchase(ProAccessController.lifetimeProductID)
let access = fixture.controller()
await access.refresh()
@@ -63,7 +63,7 @@ struct StoreKitTrialTests {
@Test
func cancellationAndNetworkFailuresDoNotRemoveAnnualAccess() async throws {
let fixture = try Fixture()
- try await fixture.session.buyProduct(identifier: ProAccessController.annualProductID)
+ try await fixture.purchase(ProAccessController.annualProductID)
let access = fixture.controller()
await access.refresh()
let active = access.status
@@ -110,12 +110,14 @@ struct StoreKitTrialTests {
@Test
func unverifiedAnnualTransactionNeverGrantsAccess() async throws {
let fixture = try Fixture()
- try await fixture.session.buyProduct(identifier: ProAccessController.annualProductID)
try await fixture.session.setSimulatedError(.verification(.invalidSignature), forAPI: .verification)
let access = fixture.controller()
await access.refresh()
+ await access.reloadProducts()
+ await access.purchaseAnnual()
- #expect(access.status == .verificationFailed)
+ #expect(access.error == .purchaseVerificationFailed)
+ await access.refresh()
#expect(!access.hasProAccess)
}
@@ -192,6 +194,30 @@ struct StoreKitTrialTests {
ProAccessController(now: now, observeStore: false)
}
+ func purchase(_ identifier: Product.ID) async throws {
+ let updates = Task {
+ for await _ in Transaction.updates {
+ guard !Task.isCancelled else { return }
+ }
+ }
+ defer { updates.cancel() }
+ await Task.yield()
+ let products = try await Product.products(for: [identifier])
+ let product = try #require(products.first { $0.id == identifier })
+ let result = try await product.purchase()
+ guard case .success(let verification) = result else {
+ Issue.record("StoreKit did not complete the \(identifier) purchase: \(result)")
+ return
+ }
+ let transaction = try verification.payloadValue
+ await transaction.finish()
+ for _ in 0..<100 {
+ if await Transaction.latest(for: identifier) != nil { return }
+ try await Task.sleep(for: .milliseconds(50))
+ }
+ Issue.record("StoreKit did not publish the \(identifier) transaction")
+ }
+
static func modifiedConfiguration(_ name: String) throws -> URL {
var root = try #require(
JSONSerialization.jsonObject(with: Data(contentsOf: configurationURL)) as? [String: Any])
diff --git a/Termind.xcodeproj/project.pbxproj b/Termind.xcodeproj/project.pbxproj
index 3e39880d..f348636d 100644
--- a/Termind.xcodeproj/project.pbxproj
+++ b/Termind.xcodeproj/project.pbxproj
@@ -8,7 +8,7 @@
/* Begin PBXBuildFile section */
0202B16D630CC57432748F0C /* TermindDomain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A62058825D6607920F1E2A1 /* TermindDomain.framework */; };
- 03892FFD3F1E351BD2C296E4 /* TermindWidgets.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 32414DBD2157FBAD4D00056D /* TermindWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ 03892FFD3F1E351BD2C296E4 /* TermindWidgets.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 32414DBD2157FBAD4D00056D /* TermindWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
082994E88792AF7D1F99B147 /* TermindPersistence.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 244632CCDB1CA43F45C0EB54 /* TermindPersistence.framework */; };
0861B3AA103F736DEE93983B /* TermindInfrastructure.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67B48098792E58C2955768F2 /* TermindInfrastructure.framework */; };
08620C447AFE3884EA26ADCC /* TermindPresentation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F2CD72AE76428E896F81B64 /* TermindPresentation.framework */; };
@@ -382,15 +382,15 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
- B7FBAAD7AF587EA9ADB523C5 /* Embed App Extensions */ = {
+ B7FBAAD7AF587EA9ADB523C5 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
- 03892FFD3F1E351BD2C296E4 /* TermindWidgets.appex in Embed App Extensions */,
+ 03892FFD3F1E351BD2C296E4 /* TermindWidgets.appex in Embed Foundation Extensions */,
);
- name = "Embed App Extensions";
+ name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
TRMD00000000000000000085 /* Embed MCP Bridge */ = {
@@ -760,7 +760,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 20CE6E8A93D697985F372EA6 /* Build configuration list for PBXNativeTarget "TFI" */;
buildPhases = (
- B7FBAAD7AF587EA9ADB523C5 /* Embed App Extensions */,
+ B7FBAAD7AF587EA9ADB523C5 /* Embed Foundation Extensions */,
AC89B83FA8E4154383D9AC81 /* Sources */,
7B09CFC5B32584951BD4C8F9 /* Frameworks */,
8F0C5245592A0E2AFB85E50F /* Resources */,
@@ -1135,7 +1135,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 2660;
- LastUpgradeCheck = 2660;
+ LastUpgradeCheck = 2700;
TargetAttributes = {
1EAB6B47E04D61C8CFC54762 = {
SystemCapabilities = {
@@ -1615,13 +1615,15 @@
00A459BF9EBF49731B530B7A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindremoteinfrastructure;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1638,7 +1640,6 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -1661,13 +1662,15 @@
26CFA808AF64A9ACDD4DF923 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindpersistence;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1682,13 +1685,15 @@
2E96D702E8EE688FB9B4DC71 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindinfrastructure;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1703,13 +1708,15 @@
30D03D452305AD59ECD3C460 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindapplication;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1729,13 +1736,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = TFI/TFI.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ CURRENT_PROJECT_VERSION = 9;
GENERATE_INFOPLIST_FILE = YES;
ICLOUD_CONTAINER_ENVIRONMENT = Development;
INFOPLIST_FILE = TFI/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Termind;
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
+ INFOPLIST_KEY_NSCameraUsageDescription = "Termind uses the camera to attach photos to your chat.";
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "Authenticate to use your SSH keys.";
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "Termind uses the microphone to transcribe speech into your chat draft.";
+ INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "Termind uses Apple Speech Recognition to turn your recording into text. Depending on system settings and language support, Apple may process the audio online.";
+ INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
@@ -1746,7 +1757,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.7.7;
+ MARKETING_VERSION = 1.8.0;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_MODULE_NAME = TermindIOS;
PRODUCT_NAME = Termind;
@@ -1761,7 +1772,6 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -1783,13 +1793,15 @@
51206A2D54AE88E0247CD9C6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindpresentation;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1805,7 +1817,6 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -1827,13 +1838,15 @@
61A9E8DD25722DF762DBC92A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindremoteinfrastructure;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1851,7 +1864,6 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 6;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TFIWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Termind Workspaces";
@@ -1876,13 +1888,15 @@
925DF91139ED491057366958 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindpersistence;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1897,13 +1911,15 @@
9A9993A9405331488B140C6A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.terminddomain;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1918,13 +1934,15 @@
A1DAF8C420A41777983ECE89 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindpresentation;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1939,13 +1957,15 @@
BD9E47297AE0FA3235A4633E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.terminddomain;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1960,13 +1980,15 @@
C4ED38FD24B69F063AC1FCC7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindapplication;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -1986,13 +2008,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = TFI/TFI.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ CURRENT_PROJECT_VERSION = 9;
GENERATE_INFOPLIST_FILE = YES;
ICLOUD_CONTAINER_ENVIRONMENT = Production;
INFOPLIST_FILE = TFI/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Termind;
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
+ INFOPLIST_KEY_NSCameraUsageDescription = "Termind uses the camera to attach photos to your chat.";
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "Authenticate to use your SSH keys.";
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "Termind uses the microphone to transcribe speech into your chat draft.";
+ INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "Termind uses Apple Speech Recognition to turn your recording into text. Depending on system settings and language support, Apple may process the audio online.";
+ INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
@@ -2003,7 +2029,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.7.7;
+ MARKETING_VERSION = 1.8.0;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_MODULE_NAME = TermindIOS;
PRODUCT_NAME = Termind;
@@ -2020,7 +2046,6 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 6;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TFIWidgets/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Termind Workspaces";
@@ -2045,13 +2070,15 @@
E072A089DE54B923933916DA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ ENABLE_MODULE_VERIFIER = YES;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACH_O_TYPE = staticlib;
MACOSX_DEPLOYMENT_TARGET = 15.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind.termindinfrastructure;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2068,7 +2095,6 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -2093,12 +2119,33 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 6;
+ DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = F6SUNDBBN9;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -2108,11 +2155,18 @@
"DEBUG=1",
"$(inherited)",
);
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.6.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
@@ -2129,20 +2183,48 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 6;
+ DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = F6SUNDBBN9;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.6.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
@@ -2164,9 +2246,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 13;
+ CURRENT_PROJECT_VERSION = 14;
+ DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
- DEVELOPMENT_TEAM = F6SUNDBBN9;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
@@ -2181,7 +2263,7 @@
);
LM_SKIP_METADATA_EXTRACTION = YES;
MACOSX_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.7.6;
+ MARKETING_VERSION = 1.8.0;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_MODULE_NAME = Termind;
PRODUCT_NAME = Termind;
@@ -2201,9 +2283,9 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 13;
+ CURRENT_PROJECT_VERSION = 14;
+ DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
- DEVELOPMENT_TEAM = F6SUNDBBN9;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
@@ -2222,7 +2304,7 @@
);
LM_SKIP_METADATA_EXTRACTION = YES;
MACOSX_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 1.7.6;
+ MARKETING_VERSION = 1.8.0;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_MODULE_NAME = Termind;
PRODUCT_NAME = Termind;
@@ -2238,7 +2320,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 15.0;
@@ -2258,7 +2340,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 15.0;
@@ -2280,7 +2362,7 @@
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -2304,7 +2386,7 @@
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
- DEVELOPMENT_TEAM = F6SUNDBBN9;
+ DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
diff --git a/Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme b/Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme
index f963120f..6d4a546b 100644
--- a/Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme
+++ b/Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme
@@ -1,39 +1,98 @@
-
-
-
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
\ No newline at end of file
+
diff --git a/Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme b/Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme
index 1cd91681..1fe2ce85 100644
--- a/Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme
+++ b/Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme
@@ -1,6 +1,6 @@