Compare commits

..

1 Commits

Author SHA1 Message Date
f72c509854 Remove CF bridges 2024-02-13 21:15:20 -08:00
15 changed files with 65 additions and 1673 deletions

View File

@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v1.0.1
- uses: actions/add-to-project@v0.0.3
with:
project-url: https://github.com/users/maxgoedjen/projects/1
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

View File

@ -5,8 +5,8 @@ on:
- cron: "0 8 * * *"
jobs:
build:
# runs-on: macOS-latest
runs-on: macos-14
# runs-on: macOS-latest-xlarge
runs-on: macos-13-xlarge
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.4.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.2.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@v4
uses: actions/upload-artifact@v3
with:
name: Secretive.zip
path: Secretive.zip

View File

@ -6,8 +6,8 @@ on:
- '*'
jobs:
test:
# runs-on: macOS-latest
runs-on: macos-14
# runs-on: macOS-latest-xlarge
runs-on: macos-13-xlarge
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.4.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.2.app
- name: Test
run: |
pushd Sources/Packages
@ -29,7 +29,7 @@ jobs:
popd
build:
# runs-on: macOS-latest
runs-on: macos-14
runs-on: macos-13
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.4.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.2.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@v4
uses: actions/upload-artifact@v1
with:
name: Secretive.zip
path: Secretive.zip
- name: Upload Archive to Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v1
with:
name: Xcode_Archive.zip
path: Archive.zip

View File

@ -3,13 +3,13 @@ name: Test
on: [push, pull_request]
jobs:
test:
# runs-on: macOS-latest
runs-on: macos-14
# runs-on: macOS-latest-xlarge
runs-on: macos-13-xlarge
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_15.4.app
run: sudo xcrun xcode-select -s /Applications/Xcode_15.2.app
- name: Test
run: |
pushd Sources/Packages

View File

@ -34,27 +34,27 @@ let package = Package(
.target(
name: "SecretKit",
dependencies: [],
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
),
.testTarget(
name: "SecretKitTests",
dependencies: ["SecretKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"],
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SecureEnclaveSecretKit",
dependencies: ["SecretKit"],
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SmartCardSecretKit",
dependencies: ["SecretKit"],
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
),
.target(
name: "SecretAgentKit",
dependencies: ["SecretKit", "SecretAgentKitHeaders"],
swiftSettings: [.unsafeFlags(["-warnings-as-errors"])]
swiftSettings: [.enableExperimentalFeature("StrictConcurrency"), .unsafeFlags(["-warnings-as-errors"])]
),
.systemLibrary(
name: "SecretAgentKitHeaders"

View File

@ -35,7 +35,7 @@ extension Agent {
/// - writer: A ``FileHandleWriter`` to write the response to.
/// - Return value:
/// - Boolean if data could be read
@discardableResult public func handle(reader: FileHandleReader, writer: FileHandleWriter) async -> Bool {
@discardableResult @Sendable 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}

View File

@ -75,7 +75,7 @@ extension SecureEnclave {
public func delete(secret: Secret) throws {
let deleteAttributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrApplicationLabel: secret.id as CFData
kSecAttrApplicationLabel: secret.id
])
let status = SecItemDelete(deleteAttributes)
if status != errSecSuccess {
@ -87,7 +87,7 @@ extension SecureEnclave {
public func update(secret: Secret, name: String) throws {
let updateQuery = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrApplicationLabel: secret.id as CFData
kSecAttrApplicationLabel: secret.id
])
let updatedAttributes = KeychainDictionary([
@ -114,7 +114,7 @@ extension SecureEnclave {
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrApplicationLabel: secret.id as CFData,
kSecAttrApplicationLabel: secret.id,
kSecAttrKeyType: Constants.keyType,
kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
kSecAttrApplicationTag: Constants.keyTag,
@ -145,7 +145,7 @@ extension SecureEnclave {
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrApplicationLabel: secret.id as CFData,
kSecAttrApplicationLabel: secret.id,
kSecAttrKeyType: Constants.keyType,
kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
kSecAttrApplicationTag: Constants.keyTag,
@ -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.
private func reloadSecretsInternal(notifyAgent: Bool = true) {
@Sendable private func reloadSecretsInternal(notifyAgent: Bool = true) {
let before = secrets
secrets.removeAll()
loadSecrets()
@ -304,8 +304,8 @@ extension SecureEnclave.Store {
extension SecureEnclave {
enum Constants {
static let keyTag = "com.maxgoedjen.secretive.secureenclave.key".data(using: .utf8)! as CFData
static let keyType = kSecAttrKeyTypeECSECPrimeRandom
static let keyTag = Data("com.maxgoedjen.secretive.secureenclave.key".utf8)
static let keyType = kSecAttrKeyTypeECSECPrimeRandom as String
static let unauthenticatedThreshold: TimeInterval = 0.05
}

View File

@ -55,7 +55,7 @@ extension SmartCard {
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrApplicationLabel: secret.id as CFData,
kSecAttrApplicationLabel: secret.id,
kSecAttrTokenID: tokenID,
kSecUseAuthenticationContext: context,
kSecReturnRef: true
@ -117,7 +117,7 @@ extension SmartCard {
extension SmartCard.Store {
private func reloadSecretsInternal() {
@Sendable private func reloadSecretsInternal() {
self.isAvailable = self.tokenID != nil
let before = self.secrets
self.secrets.removeAll()
@ -217,7 +217,7 @@ extension SmartCard.Store {
let attributes = KeychainDictionary([
kSecClass: kSecClassKey,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrApplicationLabel: secret.id as CFData,
kSecAttrApplicationLabel: secret.id,
kSecAttrTokenID: tokenID,
kSecUseAuthenticationContext: context,
kSecReturnRef: true

View File

@ -4,16 +4,6 @@
<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>

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 60;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -434,13 +434,8 @@
de,
"pt-BR",
fi,
ko,
ca,
);
mainGroup = 50617D7623FCE48D0099B055;
packageReferences = (
5068431C2DFE2DE000920856 /* XCLocalSwiftPackageReference "Packages" */,
);
productRefGroup = 50617D8023FCE48E0099B055 /* Products */;
projectDirPath = "";
projectRoot = "";
@ -597,8 +592,6 @@
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;
@ -626,6 +619,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
};
name = Debug;
};
@ -665,9 +659,7 @@
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;
@ -687,6 +679,7 @@
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_STRICT_CONCURRENCY = complete;
};
name = Release;
};
@ -702,16 +695,14 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -732,16 +723,14 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -828,8 +817,6 @@
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;
@ -857,6 +844,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
};
name = Test;
};
@ -865,21 +853,18 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.Host;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -913,20 +898,17 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -943,16 +925,14 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -970,16 +950,14 @@
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 = 13.0;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.Secretive.SecretAgent;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1033,13 +1011,6 @@
};
/* 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

View File

@ -6,16 +6,6 @@
<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>

View File

@ -30,12 +30,10 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
}
.frame(minWidth: 640, minHeight: 320)
.toolbar {
if #available(macOS 26.0, *) {
toolbarItem(updateNoticeView, id: "update")
toolbarItem(runningOrRunSetupView, id: "setup")
toolbarItem(appPathNoticeView, id: "appPath")
toolbarItem(newItemView, id: "new")
}
toolbarItem(updateNoticeView, id: "update")
toolbarItem(runningOrRunSetupView, id: "setup")
toolbarItem(appPathNoticeView, id: "appPath")
toolbarItem(newItemView, id: "new")
}
.sheet(isPresented: $runningSetup) {
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
@ -46,14 +44,9 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
extension ContentView {
@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 }
}
func toolbarItem(_ view: some View, id: String) -> ToolbarItem<String, some View> {
ToolbarItem(id: id) { view }
}
var needsSetup: Bool {

View File

@ -93,14 +93,14 @@ struct ThumbnailPickerView<ValueType: Hashable>: View {
extension ThumbnailPickerView {
struct Item<InnerValueType: Hashable>: Identifiable {
struct Item<ValueType: Hashable>: Identifiable {
let id = UUID()
let value: InnerValueType
let value: ValueType
let name: LocalizedStringKey
let description: LocalizedStringKey
let thumbnail: AnyView
init<ViewType: View>(value: InnerValueType, name: LocalizedStringKey, description: LocalizedStringKey, thumbnail: ViewType) {
init<ViewType: View>(value: ValueType, name: LocalizedStringKey, description: LocalizedStringKey, thumbnail: ViewType) {
self.value = value
self.name = name
self.description = description

View File

@ -16,44 +16,22 @@ struct ToolbarButtonStyle: ButtonStyle {
self.lightColor = lightColor
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 {
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
}
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
}
} 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
}
}
}
}
}
}