diff --git a/FueledUtils.podspec b/FueledUtils.podspec index 5eb1a523..eeb95045 100644 --- a/FueledUtils.podspec +++ b/FueledUtils.podspec @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.subspec 'Core' do |s| s.ios.deployment_target = '8.0' - s.osx.deployment_target = '10.9' + s.osx.deployment_target = '10.12' s.watchos.deployment_target = '2.0' s.tvos.deployment_target = '9.0' @@ -74,9 +74,9 @@ Pod::Spec.new do |s| s.subspec 'ReactiveCombineBridge' do |s| s.dependency 'FueledUtils/ReactiveSwift' - s.dependency 'FueledUtils/CombineOperators' + s.dependency 'FueledUtils/Combine' - s.ios.source_files = 'FueledUtils/ReactiveCombineBridge/**/*.swift' + s.source_files = 'FueledUtils/ReactiveCombineBridge/**/*.swift' end s.osx.exclude_files = ['FueledUtils/FueledUtils.h', 'FueledUtils/ButtonWithTitleAdjustment.swift', 'FueledUtils/DecoratingTextFieldDelegate.swift', 'FueledUtils/DimmingButton.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/HairlineView.swift', 'FueledUtils/KeyboardInsetHelper.swift', 'FueledUtils/LabelWithTitleAdjustment.swift', 'FueledUtils/ReactiveCocoaExtensions.swift', 'FueledUtils/ScrollViewPage.swift', 'FueledUtils/SetRootViewController.swift', 'FueledUtils/SignalingAlert.swift', 'FueledUtils/UIExtensions.swift', 'FueledUtils/GradientView.swift'] diff --git a/FueledUtils/Core/SwiftExtensions.swift b/FueledUtils/Core/SwiftExtensions.swift new file mode 100644 index 00000000..44d78bd8 --- /dev/null +++ b/FueledUtils/Core/SwiftExtensions.swift @@ -0,0 +1,24 @@ +// +// FoundationExtensions.swift +// Pods +// +// Created by Stéphane Copin on 8/31/20. +// + +extension FloatingPoint { + func rounded(decimalPlaces: Int, rule: FloatingPointRoundingRule = .toNearestOrAwayFromZero) -> Self { + var this = self + this.round(decimalPlaces: decimalPlaces, rule: rule) + return this + } + + mutating func round(decimalPlaces: Int, rule: FloatingPointRoundingRule = .toNearestOrAwayFromZero) { + var offset = Self(1) + for _ in (0.. { + public var publisher: Publishers.SignalProducerPublisher { Publishers.SignalProducerPublisher(self.producer) } } diff --git a/FueledUtils/ReactiveSwift/ReactiveCocoaExtensions.swift b/FueledUtils/ReactiveSwift/ReactiveCocoaExtensions.swift index a7de6a92..95cc0e44 100644 --- a/FueledUtils/ReactiveSwift/ReactiveCocoaExtensions.swift +++ b/FueledUtils/ReactiveSwift/ReactiveCocoaExtensions.swift @@ -15,12 +15,15 @@ import Foundation import ReactiveCocoa import ReactiveSwift +#if os(iOS) import UIKit +#endif /// /// Use with `SignalProtocol.observe(context:)` or `SignalProducerProtocol.observe(context:)` below to animate /// all changes made by observers of the signal returned from `observe(context:)`. /// +#if os(iOS) public func animatingContext( _ duration: TimeInterval, delay: TimeInterval = 0, @@ -64,6 +67,7 @@ public func transitionContext( completion: completion) } } +#endif extension Reactive where Base: NSLayoutConstraint { /// @@ -74,6 +78,7 @@ extension Reactive where Base: NSLayoutConstraint { } } +#if os(iOS) extension Reactive where Base: UIView { /// /// Update the `alpha` property of the view with an animation. @@ -121,7 +126,6 @@ extension Reactive where Base: UIViewController { } } -#if os(iOS) extension Reactive where Base: UINavigationItem { /// /// Show/hide the back button, optionally with an animation. diff --git a/FueledUtils/SwiftUI/BackgroundBlur.swift b/FueledUtils/SwiftUI/BackgroundBlur.swift index 39867330..88d0d378 100644 --- a/FueledUtils/SwiftUI/BackgroundBlur.swift +++ b/FueledUtils/SwiftUI/BackgroundBlur.swift @@ -15,6 +15,7 @@ import SwiftUI extension View { + #if os(iOS) public func backgroundBlur(style: UIBlurEffect.Style, color: Color? = nil) -> some View { ZStack { color @@ -23,4 +24,27 @@ extension View { .eraseToAnyView() } } + #else + public func backgroundBlur( + material: NSVisualEffectView.Material = .appearanceBased, + blendingMode: NSVisualEffectView.BlendingMode = .behindWindow, + state: NSVisualEffectView.State = .followsWindowActiveState, + maskImage: NSImage? = nil, + isEmphasized: Bool = false, + color: Color? = nil + ) -> some View { + ZStack { + color + BlurView( + material: material, + blendingMode: blendingMode, + state: state, + maskImage: maskImage, + isEmphasized: isEmphasized + ) + self + .eraseToAnyView() + } + } + #endif } diff --git a/FueledUtils/SwiftUI/BlurView.swift b/FueledUtils/SwiftUI/BlurView.swift index d2c3c3fc..69d0014d 100644 --- a/FueledUtils/SwiftUI/BlurView.swift +++ b/FueledUtils/SwiftUI/BlurView.swift @@ -13,10 +13,20 @@ // limitations under the License. import SwiftUI +#if os(iOS) +import UIKit +#else +import AppKit +#endif +#if os(iOS) public struct BlurView: UIViewRepresentable { public let style: UIBlurEffect.Style + public init(style: UIBlurEffect.Style) { + self.style = style + } + public func makeUIView(context: Context) -> UIVisualEffectView { UIVisualEffectView(effect: UIBlurEffect(style: self.style)) } @@ -25,3 +35,39 @@ public struct BlurView: UIViewRepresentable { visualEffectView.effect = UIBlurEffect(style: self.style) } } +#else +public struct BlurView: NSViewRepresentable { + public let material: NSVisualEffectView.Material + public let blendingMode: NSVisualEffectView.BlendingMode + public let state: NSVisualEffectView.State + public let maskImage: NSImage? + public let isEmphasized: Bool + + public init( + material: NSVisualEffectView.Material = .appearanceBased, + blendingMode: NSVisualEffectView.BlendingMode = .behindWindow, + state: NSVisualEffectView.State = .followsWindowActiveState, + maskImage: NSImage? = nil, + isEmphasized: Bool = false + ) { + self.material = material + self.blendingMode = blendingMode + self.state = state + self.maskImage = maskImage + self.isEmphasized = isEmphasized + } + + public func makeNSView(context: Context) -> NSVisualEffectView { + NSVisualEffectView() + } + + public func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context) { + visualEffectView.material = self.material + visualEffectView.blendingMode = self.blendingMode + visualEffectView.state = self.state + visualEffectView.maskImage = self.maskImage + visualEffectView.isEmphasized = self.isEmphasized + } +} + +#endif diff --git a/FueledUtils/SwiftUI/ForEachWithIndex.swift b/FueledUtils/SwiftUI/ForEachWithIndex.swift index 95b6f732..0e36901b 100644 --- a/FueledUtils/SwiftUI/ForEachWithIndex.swift +++ b/FueledUtils/SwiftUI/ForEachWithIndex.swift @@ -15,9 +15,9 @@ import SwiftUI public struct ForEachWithIndex: View { - var data: Data + public var data: Data + public var content: (_ index: Data.Index, _ element: Data.Element) -> Content var id: KeyPath - var content: (_ index: Data.Index, _ element: Data.Element) -> Content public init(_ data: Data, id: KeyPath, content: @escaping (_ index: Data.Index, _ element: Data.Element) -> Content) { self.data = data @@ -47,6 +47,9 @@ extension ForEachWithIndex where ID == Data.Element.ID, Content: View, Data.Elem } } +extension ForEachWithIndex: DynamicViewContent where Content: View { +} + private struct IndexInfo: Hashable { let index: Index let id: KeyPath diff --git a/Tests/Podfile.lock b/Tests/Podfile.lock index b4a499e5..9bfa0be7 100644 --- a/Tests/Podfile.lock +++ b/Tests/Podfile.lock @@ -5,7 +5,7 @@ PODS: - FueledUtils/Combine - FueledUtils/Core (3.0-alpha1) - FueledUtils/ReactiveCombineBridge (3.0-alpha1): - - FueledUtils/CombineOperators + - FueledUtils/Combine - FueledUtils/ReactiveSwift - FueledUtils/ReactiveCommon (3.0-alpha1): - FueledUtils/Core @@ -48,7 +48,7 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - FueledUtils: 440829476734457153856d2e60eb100fff7c001b + FueledUtils: ac740e5dae55bc10029aa3cbcd8b533298622d7a Nimble: 4ab1aeb9b45553c75b9687196b0fa0713170a332 Quick: 7fb19e13be07b5dfb3b90d4f9824c855a11af40e ReactiveCocoa: a123c42f449c552460a4ee217dd49c76a17c8204 @@ -56,4 +56,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: aeaba40223e95702eeaff4c66b27d8c72fcee5f5 -COCOAPODS: 1.9.1 +COCOAPODS: 1.9.3