From dd56827ba9918f213abc434b4adca54896a5cb92 Mon Sep 17 00:00:00 2001 From: Ilya Baudin Date: Tue, 12 Sep 2023 01:49:49 +0400 Subject: [PATCH] Added support for macOS platform Added conditional compilation for haptics engine code Checked functionality on macOS 13.0 Added support for macOS platform Added native support for macOS platform for example project Min macOS target: 13.0 Added conditional compilation for haptics engine code Added platform specific code using conditional compilation for example project Added in Package.swift macOS platform --- .../project.pbxproj | 12 +++++++ .../ContentView+Customization.swift | 10 ++++++ Example/SwipeActionsExample/ContentView.swift | 33 +++++++++++++++++-- .../SwipeActionsExampleApp.swift | 2 ++ Package.swift | 3 +- Sources/SwipeActions.swift | 13 ++++++-- 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Example/SwipeActionsExample.xcodeproj/project.pbxproj b/Example/SwipeActionsExample.xcodeproj/project.pbxproj index cbe9803..eb47b2d 100644 --- a/Example/SwipeActionsExample.xcodeproj/project.pbxproj +++ b/Example/SwipeActionsExample.xcodeproj/project.pbxproj @@ -226,6 +226,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -280,6 +281,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MACOSX_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -294,6 +296,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = WV6XDLHK3W; @@ -308,9 +311,13 @@ "$(inherited)", "@executable_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = app.getfind.SwipeActionsExample; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -322,6 +329,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = WV6XDLHK3W; @@ -336,9 +344,13 @@ "$(inherited)", "@executable_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = app.getfind.SwipeActionsExample; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Example/SwipeActionsExample/ContentView+Customization.swift b/Example/SwipeActionsExample/ContentView+Customization.swift index b687abb..ea96d4d 100644 --- a/Example/SwipeActionsExample/ContentView+Customization.swift +++ b/Example/SwipeActionsExample/ContentView+Customization.swift @@ -14,14 +14,18 @@ extension ContentView { if showingCustomizationClear { SwipeView { Container(title: "Notification", details: "Swipe for options") { +#if os(iOS) VisualEffectView(.systemThinMaterial) +#endif } } trailingActions: { _ in SwipeAction {} label: { highlight in Text("Options") } background: { highlight in +#if os(iOS) VisualEffectView(.systemThinMaterial) .brightness(highlight ? -0.1 : 0) +#endif } SwipeAction { @@ -38,8 +42,10 @@ extension ContentView { } label: { highlight in Text("Clear") } background: { highlight in +#if os(iOS) VisualEffectView(.systemThinMaterial) .brightness(highlight ? -0.1 : 0) +#endif } .allowSwipeToTrigger() } @@ -54,7 +60,9 @@ extension ContentView { #" backgroundColor: .blue"#, #") {}"# ) { +#if os(iOS) VisualEffectView(.systemThickMaterial) +#endif } } trailingActions: { _ in SwipeAction( @@ -75,7 +83,9 @@ extension ContentView { #") {}"#, #" .swipeActionChangeLabelVisibilityOnly(true)"# ) { +#if os(iOS) VisualEffectView(.systemChromeMaterial) +#endif } } trailingActions: { _ in SwipeAction( diff --git a/Example/SwipeActionsExample/ContentView.swift b/Example/SwipeActionsExample/ContentView.swift index 7e30acf..4f9935a 100644 --- a/Example/SwipeActionsExample/ContentView.swift +++ b/Example/SwipeActionsExample/ContentView.swift @@ -31,6 +31,15 @@ struct ContentView: View { @State var expandedSectionKinds = DemoSectionKind.allCases @State var showingDebug = false + + /// Calculatable `ToolbarItemPlacement` modifier for iOS and macOS platforms + private var toolbarGroupPlacement: ToolbarItemPlacement { + #if os(iOS) + return .navigationBarTrailing + #else + return .automatic + #endif + } var body: some View { VStack { @@ -139,7 +148,7 @@ struct ContentView: View { .font(.system(.body, design: .monospaced).weight(.semibold)) } .multilineTextAlignment(.center) - .accent(.primary) + .accentColor(.primary) .padding(.top, 20) .transition(.scale(scale: 0.8).combined(with: .opacity)) } @@ -163,7 +172,7 @@ struct ContentView: View { .padding(.bottom, 32) } .toolbar { - ToolbarItemGroup(placement: .navigationBarTrailing) { + ToolbarItemGroup(placement: toolbarGroupPlacement) { let shouldExpandAll: Bool = { if expandedSectionKinds.count == DemoSectionKind.allCases.count { return false @@ -190,7 +199,7 @@ struct ContentView: View { } } label: { Image(systemName: shouldExpandAll ? "arrow.up.backward.and.arrow.down.forward" : "arrow.down.forward.and.arrow.up.backward") - .noAnimation() + .animation(nil) } } } @@ -229,11 +238,17 @@ struct DemoSection: View { Image(systemName: "chevron.right") .rotationEffect(.degrees(expanded.wrappedValue ? 90 : 0)) } +#if os(iOS) .foregroundColor(.primary) +#else + .foregroundColor(.black) +#endif .font(.title3.weight(.bold)) .padding(.horizontal, 24) .padding(.vertical) +#if os(iOS) .background(VisualEffectView(.systemChromeMaterial)) +#endif .cornerRadius(32) .environment(\.colorScheme, .dark) } @@ -249,8 +264,10 @@ struct DemoSection: View { .font(.title3.weight(.medium)) .environment(\.colorScheme, .dark) } background: { highlight in +#if os(iOS) VisualEffectView(.systemChromeMaterial) .environment(\.colorScheme, .dark) +#endif } .allowSwipeToTrigger() } @@ -265,6 +282,7 @@ struct DemoSection: View { } /// Use UIKit blurs in SwiftUI. +#if os(iOS) struct VisualEffectView: UIViewRepresentable { /// The blur's style. public var style: UIBlurEffect.Style @@ -282,13 +300,22 @@ struct VisualEffectView: UIViewRepresentable { uiView.effect = UIBlurEffect(style: style) } } +#endif private struct BackgroundColorKey: EnvironmentKey { + #if os(iOS) static let defaultValue = Color(.systemBackground) + #else + static let defaultValue = Color(.windowBackgroundColor) + #endif } private struct SecondaryBackgroundColorKey: EnvironmentKey { + #if os(iOS) static let defaultValue = Color(.secondarySystemBackground) + #else + static let defaultValue = Color(.windowBackgroundColor) + #endif } extension EnvironmentValues { diff --git a/Example/SwipeActionsExample/SwipeActionsExampleApp.swift b/Example/SwipeActionsExample/SwipeActionsExampleApp.swift index 08782a6..f3b44ac 100644 --- a/Example/SwipeActionsExample/SwipeActionsExampleApp.swift +++ b/Example/SwipeActionsExample/SwipeActionsExampleApp.swift @@ -16,8 +16,10 @@ struct SwipeActionsExampleApp: App { var body: some Scene { WindowGroup { ContentView() +#if os(iOS) .environment(\.backgroundColor, Color(colorScheme == .light ? .systemBackground : .secondarySystemBackground)) .environment(\.secondaryBackgroundColor, Color(colorScheme == .light ? .secondarySystemBackground : .systemBackground)) +#endif } } } diff --git a/Package.swift b/Package.swift index 29e6773..6e65cd2 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,8 @@ import PackageDescription let package = Package( name: "SwipeActions", platforms: [ - .iOS(.v14) + .iOS(.v14), + .macOS(.v13) ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. diff --git a/Sources/SwipeActions.swift b/Sources/SwipeActions.swift index 60eb846..c9bd0b8 100644 --- a/Sources/SwipeActions.swift +++ b/Sources/SwipeActions.swift @@ -151,10 +151,13 @@ public struct SwipeOptions { /// Ensure that the user must drag a significant amount to trigger the edge action, even if the actions' total width is small. var minimumPointToTrigger = Double(200) - +#if os(iOS) /// Applies if `swipeToTriggerLeadingEdge/swipeToTriggerTrailingEdge` is true. + /// Available only for iOS platform var enableTriggerHaptics = true - +#else + var enableTriggerHaptics = false +#endif /// Applies if `swipeToTriggerLeadingEdge/swipeToTriggerTrailingEdge` is false, or when there's no actions on one side. var stretchRubberBandingPower = Double(0.7) @@ -458,7 +461,7 @@ public struct SwipeView: View where Labe } // MARK: - Trigger haptics - +#if os(iOS) .onChange(of: leadingState) { [leadingState] newValue in /// Make sure the change was from `triggering` to `nil`, or the other way around. let changed = @@ -481,6 +484,7 @@ public struct SwipeView: View where Labe generator.impactOccurred() } } +#endif // MARK: - Receive `SwipeViewGroup` events @@ -1198,12 +1202,15 @@ public extension SwipeView { return view } +#if os(iOS) /// Applies if `swipeToTriggerLeadingEdge/swipeToTriggerTrailingEdge` is true. + /// Available only for iOS platform func swipeEnableTriggerHaptics(_ value: Bool) -> SwipeView { var view = self view.options.enableTriggerHaptics = value return view } +#endif /// Applies if `swipeToTriggerLeadingEdge/swipeToTriggerTrailingEdge` is false, or when there's no actions on one side. func swipeStretchRubberBandingPower(_ value: Double) -> SwipeView {