Compare commits

...
Author SHA1 Message Date
Max Goedjen 076c6dad26 Turn on enhanced security 2025-06-14 16:43:13 -07:00
Max Goedjen 697fdfafe4 Toolbar tweaks 2025-06-14 16:42:12 -07:00
Max Goedjen d68c5a162c Fix shadowed type 2025-06-14 15:24:59 -07:00
Max Goedjen 6ca09f901f Add packages as explicit dependency. 2025-06-14 15:24:10 -07:00
Max Goedjen ad56019901 Update CI + Concurrency Warnings (#564)
* Update test.yml

* Update nightly.yml

* Update release.yml

* Tweak concurrency settings

* Remove bad annotations
2024-08-26 15:11:28 -07:00
Josep Mengual 5929137f20 Add Catalan localization (#558) 2024-08-26 21:21:45 +00:00
Max Goedjen 35a7c99cba Turn down concurrency warnings until Swift 6 branch is merged. (#562) 2024-08-26 20:59:20 +00:00
Jason Garber a543de0737 GitHub Actions updates (#554)
* Bump actions/add-to-project to v1.0.1

This _might_ address the failed workflow runs dating back to at least
the last six months:

https://github.com/maxgoedjen/secretive/actions/workflows/add-to-project.yml

* Bump actions/upload-artifact to v4

This should get rid of the deprecation notices displayed as annotations
beneath each Nightly job run. See:

https://github.com/maxgoedjen/secretive/actions/runs/9461831554

* Bump actions/upload-artifact to v4

Similar to cf25db6, this should silence some deprecation notices.
2024-06-25 21:08:38 +00:00
Yoshimasa Niwa fc21018eb4 Add Japanese translations (#546) 2024-04-28 22:33:51 +00:00
mog422 52cc08424e Add Korean localization (#537) 2024-03-01 22:58:08 +00:00
Max Goedjen d13f4ee7ba Revert "Use Apple Silicon runners (#519)" (#533)
This reverts commit 409efa5f9f.
2024-02-26 00:24:48 +00:00
Max Goedjen 6f4226f97a Standardize newline handling (#522)
* Standardize newline handling

* Fix some unterminated bolds in other languages

* Set language back
2024-01-25 02:14:34 +00:00
Aarni Koskela 3315a4bfbc Add Finnish localization (#521) 2024-01-23 00:58:36 +00:00
Riccardo PesciarelliandMax Goedjen 85a7a64bc9 Updated Italian localization strings (#520)
* 🇮🇹 Initial proposal for Italian localization

* 🇮🇹 Updated Italian localization

---------

Co-authored-by: Max Goedjen <max.goedjen@gmail.com>
2024-01-18 17:35:36 +00:00
Max Goedjen 409efa5f9f Use Apple Silicon runners (#519)
* Test running on XL (does this work for OSS projects?)

* Move over test/release
2024-01-17 19:28:29 +00:00
Max Goedjen bb63ae8469 Set min width/height for setup. (#518) 2024-01-17 04:08:48 +00:00
Max Goedjen 30c1d36974 Mark newlines as verbatim (#517)
* Merge

* Add missing key
2024-01-17 03:49:14 +00:00
Max Goedjen de8d18f9e9 Switch to Xcode 15.2 (#516) 2024-01-16 21:39:07 +00:00
Riccardo PesciarelliandMax Goedjen 1ae0996e2c 🇮🇹 Initial proposal for Italian localization (#512)
Co-authored-by: Max Goedjen <max.goedjen@gmail.com>
2024-01-16 21:35:28 +00:00
Moritz SternemannandMax Goedjen 3d50a99430 Add German Localization 🇩🇪 (#514)
* Add German localization

* Small adjustments

* Add German localization in project file

---------

Co-authored-by: Max Goedjen <max.goedjen@gmail.com>
2024-01-16 21:15:07 +00:00
Marcio Saeger 45fc356f0f Add PT-BR to the i18n (#515) 2024-01-16 21:12:46 +00:00
Mahé 212678b94e Fix missing French translations (#510) 2024-01-13 14:32:08 -08:00
RyuSandAlex Q 2e1f4881a9 Translate_Addlang_ZH_Han (#508)
Co-authored-by: Alex Q <ln41xgpy@addymail.com>
2024-01-13 06:25:20 +00:00
Max Goedjen c2b80e3c7c Localization fixes (#507)
* Consolidate localization files into one file that both targets reference

* Update readme

* Secret Agent/Agent consolidation

* NSLS -> String(localized:)

* Auth contexts
2024-01-12 12:50:52 -08:00
Mahé 15d2afd2cb Add French localization (#506) 2024-01-12 12:14:02 -08:00
Ale Muñoz 2a4da36c4e Fix escaped text on Agent is running popover (#505) 2024-01-11 23:09:04 +00:00
20 changed files with 4740 additions and 221 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.0.3
- uses: actions/add-to-project@v1.0.1
with:
project-url: https://github.com/users/maxgoedjen/projects/1
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
+3 -3
View File
@@ -6,7 +6,7 @@ on:
jobs:
build:
# runs-on: macOS-latest
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -20,7 +20,7 @@ jobs:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_15.1.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.4.app
- name: Update Build Number
env:
RUN_ID: ${{ github.run_id }}
@@ -48,7 +48,7 @@ jobs:
shasum -a 256 Secretive.zip
shasum -a 256 Archive.zip
- name: Upload App to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Secretive.zip
path: Secretive.zip
+6 -6
View File
@@ -7,7 +7,7 @@ on:
jobs:
test:
# runs-on: macOS-latest
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -21,7 +21,7 @@ jobs:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_15.1.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.4.app
- name: Test
run: |
pushd Sources/Packages
@@ -29,7 +29,7 @@ jobs:
popd
build:
# runs-on: macOS-latest
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -43,7 +43,7 @@ jobs:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_15.1.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.4.app
- name: Update Build Number
env:
TAG_NAME: ${{ github.ref }}
@@ -107,12 +107,12 @@ jobs:
asset_name: Secretive.zip
asset_content_type: application/zip
- name: Upload App to Artifacts
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: Secretive.zip
path: Secretive.zip
- name: Upload Archive to Artifacts
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: Xcode_Archive.zip
path: Archive.zip
+2 -2
View File
@@ -4,12 +4,12 @@ on: [push, pull_request]
jobs:
test:
# runs-on: macOS-latest
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_15.1.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.4.app
- name: Test
run: |
pushd Sources/Packages
+1 -9
View File
@@ -16,7 +16,7 @@ Clone Secretive using [these instructions from GitHub](https://docs.github.com/e
Open [Sources/Secretive.xcodeproj](Sources/Secretive.xcodeproj) in Xcode.
### Localize the Main App
### Translate
Navigate to [Secretive/Localizable](Sources/Secretive/Localizable.xcstrings).
@@ -28,14 +28,6 @@ If your language already has an in-progress localization, select it from the lis
Start translating! You'll see a list of english phrases, and a space to add a translation of your language.
### Localize SecretAgent
Navigate to [Secretive/Localizable](Sources/SecretAgent/Localizable.xcstrings).
<img src="/.github/readme/localize_sidebar_agent.png" alt="Screenshot of Xcode navigating to the Localizable file" width="300">
Repeat the same steps from the process of localizing the main app.
### Create a Pull Request
Push your changes and open a pull request.
+5 -5
View File
@@ -34,27 +34,27 @@ let package = Package(
.target(
name: "SecretKit",
dependencies: [],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
),
.testTarget(
name: "SecretKitTests",
dependencies: ["SecretKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SecureEnclaveSecretKit",
dependencies: ["SecretKit"],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SmartCardSecretKit",
dependencies: ["SecretKit"],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SecretAgentKit",
dependencies: ["SecretKit", "SecretAgentKitHeaders"],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
),
.systemLibrary(
name: "SecretAgentKitHeaders"
@@ -35,7 +35,7 @@ extension Agent {
/// - writer: A ``FileHandleWriter`` to write the response to.
/// - Return value:
/// - Boolean if data could be read
@discardableResult @Sendable public func handle(reader: FileHandleReader, writer: FileHandleWriter) async -> Bool {
@discardableResult public func handle(reader: FileHandleReader, writer: FileHandleWriter) async -> Bool {
logger.debug("Agent handling new data")
let data = Data(reader.availableData)
guard data.count > 4 else { return false}
@@ -17,7 +17,7 @@ extension SecureEnclave {
TKTokenWatcher().tokenIDs.contains("com.apple.setoken")
}
public let id = UUID()
public let name = NSLocalizedString("Secure Enclave", comment: "Secure Enclave")
public let name = String(localized: "secure_enclave")
@Published public private(set) var secrets: [Secret] = []
private var persistedAuthenticationContexts: [Secret: PersistentAuthenticationContext] = [:]
@@ -107,10 +107,10 @@ extension SecureEnclave {
context = existing.context
} else {
let newContext = LAContext()
newContext.localizedCancelTitle = "Deny"
newContext.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
context = newContext
}
context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\""
context.localizedReason = String(localized: "auth_context_request_signature_description_\(provenance.origin.displayName)_\(secret.name)")
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
@@ -140,8 +140,8 @@ extension SecureEnclave {
public func verify(signature: Data, for data: Data, with secret: Secret) throws -> Bool {
let context = LAContext()
context.localizedReason = "verify a signature using secret \"\(secret.name)\""
context.localizedCancelTitle = "Deny"
context.localizedReason = String(localized: "auth_context_request_verify_description_\(secret.name)")
context.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
@@ -181,16 +181,16 @@ extension SecureEnclave {
public func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) throws {
let newContext = LAContext()
newContext.touchIDAuthenticationAllowableReuseDuration = duration
newContext.localizedCancelTitle = "Deny"
newContext.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .spellOut
formatter.allowedUnits = [.hour, .minute, .day]
if let durationString = formatter.string(from: duration) {
newContext.localizedReason = "unlock secret \"\(secret.name)\" for \(durationString)"
newContext.localizedReason = String(localized: "auth_context_persist_for_duration_\(secret.name)_\(durationString)")
} else {
newContext.localizedReason = "unlock secret \"\(secret.name)\""
newContext.localizedReason = String(localized: "auth_context_persist_for_duration_unknown_\(secret.name)")
}
newContext.evaluatePolicy(LAPolicy.deviceOwnerAuthentication, localizedReason: newContext.localizedReason) { [weak self] success, _ in
guard success else { return }
@@ -211,7 +211,7 @@ extension SecureEnclave.Store {
/// Reloads all secrets from the store.
/// - Parameter notifyAgent: A boolean indicating whether a distributed notification should be posted, notifying other processes (ie, the SecretAgent) to reload their stores as well.
@Sendable private func reloadSecretsInternal(notifyAgent: Bool = true) {
private func reloadSecretsInternal(notifyAgent: Bool = true) {
let before = secrets
secrets.removeAll()
loadSecrets()
@@ -260,7 +260,7 @@ extension SecureEnclave.Store {
nil)!
let wrapped: [SecureEnclave.Secret] = publicTyped.map {
let name = $0[kSecAttrLabel] as? String ?? "Unnamed"
let name = $0[kSecAttrLabel] as? String ?? String(localized: "unnamed_secret")
let id = $0[kSecAttrApplicationLabel] as! Data
let publicKeyRef = $0[kSecValueRef] as! SecKey
let publicKeyAttributes = SecKeyCopyAttributes(publicKeyRef) as! [CFString: Any]
@@ -12,7 +12,7 @@ extension SmartCard {
@Published public var isAvailable: Bool = false
public let id = UUID()
public private(set) var name = NSLocalizedString("Smart Card", comment: "Smart Card")
public private(set) var name = String(localized: "smart_card")
@Published public private(set) var secrets: [Secret] = []
private let watcher = TKTokenWatcher()
private var tokenID: String?
@@ -50,8 +50,8 @@ extension SmartCard {
public func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) throws -> Data {
guard let tokenID = tokenID else { fatalError() }
let context = LAContext()
context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\""
context.localizedCancelTitle = "Deny"
context.localizedReason = String(localized: "auth_context_request_signature_description_\(provenance.origin.displayName)_\(secret.name)")
context.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
@@ -117,7 +117,7 @@ extension SmartCard {
extension SmartCard.Store {
@Sendable private func reloadSecretsInternal() {
private func reloadSecretsInternal() {
self.isAvailable = self.tokenID != nil
let before = self.secrets
self.secrets.removeAll()
@@ -138,7 +138,7 @@ extension SmartCard.Store {
private func loadSecrets() {
guard let tokenID = tokenID else { return }
let fallbackName = NSLocalizedString("Smart Card", comment: "Smart Card")
let fallbackName = String(localized: "smart_card")
if let driverName = watcher.tokenInfo(forTokenID: tokenID)?.driverName {
name = driverName
} else {
@@ -156,7 +156,7 @@ extension SmartCard.Store {
SecItemCopyMatching(attributes, &untyped)
guard let typed = untyped as? [[CFString: Any]] else { return }
let wrapped = typed.map {
let name = $0[kSecAttrLabel] as? String ?? "Unnamed"
let name = $0[kSecAttrLabel] as? String ?? String(localized: "unnamed_secret")
let tokenID = $0[kSecAttrApplicationLabel] as! Data
let algorithm = Algorithm(secAttr: $0[kSecAttrKeyType] as! NSNumber)
let keySize = $0[kSecAttrKeySizeInBits] as! Int
@@ -183,8 +183,8 @@ extension SmartCard.Store {
/// - Warning: Encryption functions are deliberately only exposed on a library level, and are not exposed in Secretive itself to prevent users from data loss. Any pull requests which expose this functionality in the app will not be merged.
public func encrypt(data: Data, with secret: SecretType) throws -> Data {
let context = LAContext()
context.localizedReason = "encrypt data using secret \"\(secret.name)\""
context.localizedCancelTitle = "Deny"
context.localizedReason = String(localized: "auth_context_request_encrypt_description_\(secret.name)")
context.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
let attributes = KeychainDictionary([
kSecAttrKeyType: secret.algorithm.secAttrKeyType,
kSecAttrKeySizeInBits: secret.keySize,
@@ -212,8 +212,8 @@ extension SmartCard.Store {
public func decrypt(data: Data, with secret: SecretType) throws -> Data {
guard let tokenID = tokenID else { fatalError() }
let context = LAContext()
context.localizedReason = "decrypt data using secret \"\(secret.name)\""
context.localizedCancelTitle = "Deny"
context.localizedReason = String(localized: "auth_context_request_decrypt_description_\(secret.name)")
context.localizedCancelTitle = String(localized: "auth_context_request_deny_button")
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
-114
View File
@@ -1,114 +0,0 @@
{
"sourceLanguage" : "en",
"strings" : {
"persist_authentication_accept_button" : {
"comment" : "When the user authorizes an action using a secret that requires unlock, they're shown a notification offering to leave the secret unlocked for a set period of time. This is the title for the notification.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Leave Unlocked"
}
}
}
},
"persist_authentication_decline_button" : {
"comment" : "When the user authorizes an action using a secret that requires unlock, they're shown a notification offering to leave the secret unlocked for a set period of time. This is the decline button for the notification.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Do Not Unlock"
}
}
}
},
"signed_notification_description_%@" : {
"comment" : "When the user performs an action using a secret, they're shown a notification describing what happened. This is the description, showing which secret was used. The placeholder is the name of the secret.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Using secret %1$@"
}
}
}
},
"signed_notification_title_%@" : {
"comment" : "When the user performs an action using a secret, they're shown a notification describing what happened. This is the title, showing which app requested the action. The placeholder is the name of the app.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Signed Request from %1$@"
}
}
}
},
"update_notification_ignore_button" : {
"comment" : "When an update is available, a notification is shown. This is the button to decline an update.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ignore"
}
}
}
},
"update_notification_update_button" : {
"comment" : "When an update is available, a notification is shown. This is the button to download an update.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Update"
}
}
}
},
"update_notification_update_critical_title_%@" : {
"comment" : "When an update is available, a notification is shown. This is the title for a very high priority update with security fixes. The placeholder is for the application version, eg \"Critical Security Update - 2.0\"",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Critical Security Update - %1$@"
}
}
}
},
"update_notification_update_description" : {
"comment" : "When an update is available, a notification is shown. This is the description to download an update.",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Click to Update"
}
}
}
},
"update_notification_update_normal_title_%@" : {
"comment" : "When an update is available, a notification is shown. This is the title for a normal priority update. The placeholder is for the application version, eg \"Update Available - 2.0\"",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Update Available - %1$@"
}
}
}
}
},
"version" : "1.0"
}
@@ -4,6 +4,16 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.hardened-process</key>
<true/>
<key>com.apple.security.hardened-process.dyld-ro</key>
<true/>
<key>com.apple.security.hardened-process.enhanced-security-version</key>
<integer>1</integer>
<key>com.apple.security.hardened-process.hardened-heap</key>
<true/>
<key>com.apple.security.hardened-process.platform-restrictions</key>
<integer>2</integer>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.smartcard</key>
+49 -20
View File
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {
/* Begin PBXBuildFile section */
@@ -19,7 +19,6 @@
5003EF632780081B00DF2006 /* SecureEnclaveSecretKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF622780081B00DF2006 /* SecureEnclaveSecretKit */; };
5003EF652780081B00DF2006 /* SmartCardSecretKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5003EF642780081B00DF2006 /* SmartCardSecretKit */; };
500B93C32B478D8400E157DE /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 500B93C22B478D8400E157DE /* Localizable.xcstrings */; };
500B93C72B479E2E00E157DE /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 500B93C62B479E2E00E157DE /* Localizable.xcstrings */; };
501421622781262300BBAA70 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 501421612781262300BBAA70 /* Brief */; };
501421652781268000BBAA70 /* SecretAgent.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 50A3B78A24026B7500D209EA /* SecretAgent.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
50153E20250AFCB200525160 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E1F250AFCB200525160 /* UpdateView.swift */; };
@@ -53,6 +52,7 @@
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B8550C24138C4F009958AC /* DeleteSecretView.swift */; };
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */; };
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A42407A76D00AF2719 /* SecretDetailView.swift */; };
50E9CF422B51D596004AB36D /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 500B93C22B478D8400E157DE /* Localizable.xcstrings */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -111,7 +111,6 @@
50033AC227813F1700253856 /* BundleIDs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleIDs.swift; sourceTree = "<group>"; };
5003EF39278005C800DF2006 /* Packages */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Packages; sourceTree = "<group>"; };
500B93C22B478D8400E157DE /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
500B93C62B479E2E00E157DE /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
50153E1F250AFCB200525160 /* UpdateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateView.swift; sourceTree = "<group>"; };
50153E21250DECA300525160 /* SecretListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretListItemView.swift; sourceTree = "<group>"; };
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
@@ -316,7 +315,6 @@
50A3B79824026B7600D209EA /* Info.plist */,
508BF29425B4F140009EFB7E /* InternetAccessPolicy.plist */,
50A3B79924026B7600D209EA /* SecretAgent.entitlements */,
500B93C62B479E2E00E157DE /* Localizable.xcstrings */,
50A3B79224026B7600D209EA /* Preview Content */,
);
path = SecretAgent;
@@ -431,8 +429,18 @@
knownRegions = (
en,
Base,
it,
fr,
de,
"pt-BR",
fi,
ko,
ca,
);
mainGroup = 50617D7623FCE48D0099B055;
packageReferences = (
5068431C2DFE2DE000920856 /* XCLocalSwiftPackageReference "Packages" */,
);
productRefGroup = 50617D8023FCE48E0099B055 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -469,7 +477,7 @@
buildActionMask = 2147483647;
files = (
50A3B79724026B7600D209EA /* Main.storyboard in Resources */,
500B93C72B479E2E00E157DE /* Localizable.xcstrings in Resources */,
50E9CF422B51D596004AB36D /* Localizable.xcstrings in Resources */,
50A3B79424026B7600D209EA /* Preview Assets.xcassets in Resources */,
50A3B79124026B7600D209EA /* Assets.xcassets in Resources */,
508BF2AA25B4F1CB009EFB7E /* InternetAccessPolicy.plist in Resources */,
@@ -589,6 +597,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -609,7 +619,7 @@
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks";
OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO;
@@ -655,7 +665,9 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
@@ -668,7 +680,7 @@
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks";
OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO;
@@ -690,19 +702,20 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Debug;
@@ -719,19 +732,20 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "Secretive - Host";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Release;
@@ -814,6 +828,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -834,7 +850,7 @@
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks";
OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO;
@@ -849,22 +865,24 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Secretive/Secretive.entitlements;
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = NO;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Test;
@@ -895,21 +913,23 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = SecretAgent/SecretAgent.entitlements;
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Test;
@@ -923,18 +943,19 @@
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Debug;
@@ -949,19 +970,20 @@
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "Secretive - Secret Agent";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
};
name = Release;
@@ -1011,6 +1033,13 @@
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
5068431C2DFE2DE000920856 /* XCLocalSwiftPackageReference "Packages" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Packages;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
5003EF3A278005E800DF2006 /* SecretKit */ = {
isa = XCSwiftPackageProductDependency;
File diff suppressed because it is too large Load Diff
+10
View File
@@ -6,6 +6,16 @@
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.hardened-process</key>
<true/>
<key>com.apple.security.hardened-process.dyld-ro</key>
<true/>
<key>com.apple.security.hardened-process.enhanced-security-version</key>
<integer>1</integer>
<key>com.apple.security.hardened-process.hardened-heap</key>
<true/>
<key>com.apple.security.hardened-process.platform-restrictions</key>
<integer>2</integer>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.smartcard</key>
+14 -7
View File
@@ -30,10 +30,12 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
}
.frame(minWidth: 640, minHeight: 320)
.toolbar {
toolbarItem(updateNoticeView, id: "update")
toolbarItem(runningOrRunSetupView, id: "setup")
toolbarItem(appPathNoticeView, id: "appPath")
toolbarItem(newItemView, id: "new")
if #available(macOS 26.0, *) {
toolbarItem(updateNoticeView, id: "update")
toolbarItem(runningOrRunSetupView, id: "setup")
toolbarItem(appPathNoticeView, id: "appPath")
toolbarItem(newItemView, id: "new")
}
}
.sheet(isPresented: $runningSetup) {
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
@@ -44,9 +46,14 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
extension ContentView {
func toolbarItem(_ view: some View, id: String) -> ToolbarItem<String, some View> {
ToolbarItem(id: id) { view }
@ToolbarContentBuilder
func toolbarItem(_ view: some View, id: String) -> some ToolbarContent {
if #available(macOS 26.0, *) {
ToolbarItem(id: id) { view }
.sharedBackgroundVisibility(.hidden)
} else {
ToolbarItem(id: id) { view }
}
}
var needsSetup: Bool {
@@ -93,14 +93,14 @@ struct ThumbnailPickerView<ValueType: Hashable>: View {
extension ThumbnailPickerView {
struct Item<ValueType: Hashable>: Identifiable {
struct Item<InnerValueType: Hashable>: Identifiable {
let id = UUID()
let value: ValueType
let value: InnerValueType
let name: LocalizedStringKey
let description: LocalizedStringKey
let thumbnail: AnyView
init<ViewType: View>(value: ValueType, name: LocalizedStringKey, description: LocalizedStringKey, thumbnail: ViewType) {
init<ViewType: View>(value: InnerValueType, name: LocalizedStringKey, description: LocalizedStringKey, thumbnail: ViewType) {
self.value = value
self.name = name
self.description = description
+1 -1
View File
@@ -26,7 +26,7 @@ struct SetupView: View {
}
}
}
.frame(idealWidth: 500, idealHeight: 500)
.frame(minWidth: 500, idealWidth: 500, minHeight: 500, idealHeight: 500)
}
@@ -17,21 +17,43 @@ struct ToolbarButtonStyle: ButtonStyle {
self.darkColor = darkColor
}
private var backingColor: Color {
if !hovering {
colorScheme == .light ? lightColor : darkColor
} else {
colorScheme == .light ? .black.opacity(0.1) : .white.opacity(0.05)
}
}
@Namespace var namespace
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
.background(colorScheme == .light ? lightColor : darkColor)
.foregroundColor(.white)
.clipShape(RoundedRectangle(cornerRadius: 5))
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(colorScheme == .light ? .black.opacity(0.15) : .white.opacity(0.15), lineWidth: 1)
.background(hovering ? (colorScheme == .light ? .black.opacity(0.1) : .white.opacity(0.05)) : Color.clear)
)
.onHover { hovering in
withAnimation {
self.hovering = hovering
if #available(macOS 26.0, *) {
configuration
.label
.foregroundColor(.white)
.padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
.glassEffect(.regular.tint(backingColor), in: .capsule, isEnabled: true)
.onHover { hovering in
withAnimation {
self.hovering = hovering
}
}
}
} else {
configuration
.label
.background(colorScheme == .light ? lightColor : darkColor)
.foregroundColor(.white)
.clipShape(RoundedRectangle(cornerRadius: 5))
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(colorScheme == .light ? .black.opacity(0.15) : .white.opacity(0.15), lineWidth: 1)
.background(hovering ? (colorScheme == .light ? .black.opacity(0.1) : .white.opacity(0.05)) : Color.clear)
)
.onHover { hovering in
withAnimation {
self.hovering = hovering
}
}
}
}
}
+5 -5
View File
@@ -42,16 +42,16 @@ struct UpdateDetailView<UpdaterType: Updater>: View {
if let prefix = split.first {
switch prefix {
case "#":
attributed = Text(unprefixed).font(.title) + Text("\n")
attributed = Text(unprefixed).font(.title) + Text(verbatim: "\n")
case "##":
attributed = Text(unprefixed).font(.title2) + Text("\n")
attributed = Text(unprefixed).font(.title2) + Text(verbatim: "\n")
case "###":
attributed = Text(unprefixed).font(.title3) + Text("\n")
attributed = Text(unprefixed).font(.title3) + Text(verbatim: "\n")
default:
attributed = Text(line) + Text("\n\n")
attributed = Text(line) + Text(verbatim: "\n\n")
}
} else {
attributed = Text(line) + Text("\n\n")
attributed = Text(line) + Text(verbatim: "\n\n")
}
text = text + attributed
}