Skip to content

Commit

Permalink
1.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nathantannar4 committed May 2, 2024
1 parent b841fb6 commit c7fc37a
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 1 deletion.
1 change: 1 addition & 0 deletions Sources/Engine/Sources/ConditionalShape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ extension ConditionalShape: Shape {

// MARK: - Previews

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
struct ConditionalShape_Previews: PreviewProvider {
static var previews: some View {
Preview()
Expand Down
31 changes: 31 additions & 0 deletions Sources/Engine/Sources/HostingController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ open class HostingController<
}
}

#if os(iOS) || os(tvOS)
@available(iOS 16.0, tvOS 16.0, *)
public var allowUIKitAnimationsForNextUpdate: Bool {
get {
guard let view else { return false }
let result = try? swift_getFieldValue("allowUIKitAnimationsForNextUpdate", Bool.self, view)
return result ?? false
}
set {
guard let view else { return }
try? swift_setFieldValue("allowUIKitAnimationsForNextUpdate", newValue, view)
}
}

@available(iOS 16.0, tvOS 16.0, *)
public var automaticallyAllowUIKitAnimationsForNextUpdate: Bool {
get { shouldAutomaticallyAllowUIKitAnimationsForNextUpdate }
set { shouldAutomaticallyAllowUIKitAnimationsForNextUpdate = newValue }
}
private var shouldAutomaticallyAllowUIKitAnimationsForNextUpdate: Bool = true
#endif

public init(content: Content) {
super.init(rootView: content)
}
Expand All @@ -59,6 +81,15 @@ open class HostingController<
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

open override func viewWillLayoutSubviews() {
if #available(iOS 16.0, tvOS 16.0, *), shouldAutomaticallyAllowUIKitAnimationsForNextUpdate,
UIView.inheritedAnimationDuration > 0 || view.layer.animationKeys()?.isEmpty == false
{
allowUIKitAnimationsForNextUpdate = true
}
super.viewWillLayoutSubviews()
}
}

#endif // !os(watchOS)
1 change: 1 addition & 0 deletions Sources/Engine/Sources/ShapeAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public struct ShapeAdapter<S: Shape>: Shape {

// MARK: - Previews

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
struct ShapeAdapter_Previews: PreviewProvider {
static var previews: some View {
Preview()
Expand Down
17 changes: 17 additions & 0 deletions Sources/Engine/Sources/ViewInputConditionalContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ public struct ViewInputConditionalContent<
self.falseContent = otherwise()
}

@inlinable
public init(
_ : Condition,
@ViewBuilder then: () -> TrueContent,
@ViewBuilder otherwise: () -> FalseContent
) {
self.trueContent = then()
self.falseContent = otherwise()
}

public var body: Never {
bodyError()
}
Expand Down Expand Up @@ -67,6 +77,13 @@ extension ViewInputConditionalContent where FalseContent == EmptyView {
) {
self.init(Condition.self, then: then, otherwise: { EmptyView() })
}

public init(
_ : Condition,
@ViewBuilder then: () -> TrueContent
) {
self.init(Condition.self, then: then, otherwise: { EmptyView() })
}
}

// MARK: - Previews
Expand Down
17 changes: 17 additions & 0 deletions Sources/Engine/Sources/ViewInputConditionalModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ public struct ViewInputConditionalModifier<
self.falseModifier = otherwise()
}

@inlinable
public init(
_ : Condition,
@ViewModifierBuilder then: () -> TrueModifier,
@ViewModifierBuilder otherwise: () -> FalseModifier
) {
self.trueModifier = then()
self.falseModifier = otherwise()
}

public func body(content: Content) -> Never {
bodyError()
}
Expand Down Expand Up @@ -70,6 +80,13 @@ extension ViewInputConditionalModifier where FalseModifier == EmptyModifier {
) {
self.init(Condition.self, then: then, otherwise: { EmptyModifier() })
}

public init(
_ : Condition,
@ViewModifierBuilder then: () -> TrueModifier
) {
self.init(Condition.self, then: then, otherwise: { EmptyModifier() })
}
}

// MARK: - Previews
Expand Down
24 changes: 23 additions & 1 deletion Sources/Engine/Sources/ViewInputs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,30 @@ import os.log

@frozen
public struct ViewInputs {


public struct Options: OptionSet {
public var rawValue: UInt32

public init(rawValue: UInt32) { self.rawValue = rawValue }

public static func flag(_ index: Int) -> Options {
Options(rawValue: 1 << index)
}

public static let isAxisHorizontal = Options(rawValue: 1 << 3)
}

public var _graphInputs: _GraphInputs

public var options: Options {
do {
let rawValue = try swift_getFieldValue("options", UInt32.self, _graphInputs)
return Options(rawValue: rawValue)
} catch {
return Options(rawValue: 0)
}
}

init(inputs: _GraphInputs) {
self._graphInputs = inputs
}
Expand Down Expand Up @@ -66,6 +87,7 @@ public struct _ViewInputsLogModifier: ViewInputsModifier {
#if DEBUG
let log: String = {
var message = "\n=== ViewInputs ===\n"
dump(inputs.options, to: &message)
var ptr = inputs._graphInputs.customInputs.elements
while let p = ptr {
dump(p, to: &message)
Expand Down
131 changes: 131 additions & 0 deletions Sources/Engine/Sources/ViewStackAxisReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// Copyright (c) Nathan Tannar
//

import SwiftUI

/// A `View` that statically depends if its parent is a `VStack` or `HStack`.
///
/// > Tip: You to make views that behave like `Divider` and `Spacer`
///
@frozen
public struct ViewStackAxisReader<Content: View>: View {

@usableFromInline
var vertical: Content

@usableFromInline
var horizontal: Content

@inlinable
public init(
@ViewBuilder content: (Axis) -> Content
) {
self.vertical = content(.vertical)
self.horizontal = content(.horizontal)
}

public var body: some View {
ViewInputConditionalContent(IsAxisHorizontal.self) {
horizontal
} otherwise: {
vertical
}
}
}

private struct IsAxisHorizontal: ViewInputsCondition {
static func evaluate(_ inputs: ViewInputs) -> Bool {
inputs.options.contains(.isAxisHorizontal)
}
}

// MARK: - Previews

private struct CustomDivider: View {

var scale: CGFloat = 1

@Environment(\.pixelLength) var pixelLength

var body: some View {
ViewStackAxisReader { axis in
Capsule(style: .circular)
.frame(
width: axis == .horizontal ? scale * pixelLength : nil,
height: axis == .vertical ? scale * pixelLength : nil
)
}
}
}

@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
struct ViewStackAxisReader_Previews: PreviewProvider {
static var previews: some View {
VStack(spacing: 12) {
HStack {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}

CustomDivider(scale: 3)

CustomDivider()

Divider()
.overlay(Color.black)
}

VStack {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}

CustomDivider()

Divider()
}

LazyHStack {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}
}

LazyVStack {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}
}

ZStack {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}
}

if #available(iOS 16.0, macOS 13.0, *) {
Grid(verticalSpacing: 8) {
CustomDivider()

Divider()

ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}

GridRow {
ViewStackAxisReader { axis in
Text(axis == .horizontal ? "Horizontal" : "Vertical")
}

CustomDivider()

Divider()
}
}
}
}
.fixedSize()
}
}

0 comments on commit c7fc37a

Please sign in to comment.