From 7f3062a2528262b22bada9d253c58ad0ce7fd8ab Mon Sep 17 00:00:00 2001 From: amodrono Date: Sun, 26 Dec 2021 01:00:10 +0100 Subject: [PATCH 1/3] chore(navigation_bar)!: changed the way navigation bar elements were created. BREAKING CHANGE: now navigation bar elements are passed as arguments to the style, so `.navigationBarElement()` is no longer used. --- Sources/StylableScrollView/BackButton.swift | 25 +-- .../StylableScrollView/Extensions/Color.swift | 8 + .../Extensions/Modifiers.swift | 66 +++++--- .../Configuration.swift | 0 .../Environment.swift | 0 .../Namespaces/NavigationBarProxy.swift | 57 +++++++ .../Preferences.swift | 9 +- .../StylableScrollView/ScrollViewStyle.swift | 2 +- .../StylableScrollView.swift | 13 +- .../Styles/AnyScrollViewStyle.swift | 4 +- .../Styles/StretchableScrollViewStyle.swift | 142 ++++++++---------- 11 files changed, 213 insertions(+), 113 deletions(-) rename Sources/StylableScrollView/{Configuration => Namespaces}/Configuration.swift (100%) rename Sources/StylableScrollView/{Configuration => Namespaces}/Environment.swift (100%) create mode 100644 Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift rename Sources/StylableScrollView/{Configuration => Namespaces}/Preferences.swift (98%) diff --git a/Sources/StylableScrollView/BackButton.swift b/Sources/StylableScrollView/BackButton.swift index a8cb340..776b3d4 100644 --- a/Sources/StylableScrollView/BackButton.swift +++ b/Sources/StylableScrollView/BackButton.swift @@ -14,20 +14,25 @@ public struct BackButton: View { @Environment(\.presentationMode) public var presentationMode: Binding - + @State private var hasBeenShownAtLeastOnce: Bool = false public var body: some View { (presentationMode.wrappedValue.isPresented || hasBeenShownAtLeastOnce) ? - Button(action: { self.presentationMode.wrappedValue.dismiss() }) { - Image(systemName: "chevron.left") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 20, alignment: .leading) - .foregroundColor(color) - .padding(.horizontal, 16) - .font(Font.body.bold()) - } + Button( + action: { + self.presentationMode.wrappedValue.dismiss() + }, + label: { + Image(systemName: "chevron.left") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 20, alignment: .leading) + .foregroundColor(color) + .padding(.horizontal, 16) + .font(Font.body.bold()) + } + ) .onAppear { self.hasBeenShownAtLeastOnce = true } diff --git a/Sources/StylableScrollView/Extensions/Color.swift b/Sources/StylableScrollView/Extensions/Color.swift index 7febd31..99418c9 100644 --- a/Sources/StylableScrollView/Extensions/Color.swift +++ b/Sources/StylableScrollView/Extensions/Color.swift @@ -28,6 +28,14 @@ public extension Color { return scheme == .light ? Color(red: 0.95, green: 0.95, blue: 0.97) : Color(red: 0.11, green: 0.11, blue: 0.12) } + /// `Color.systemGray6` multi-platform equivalent. + /// + /// - Parameters: + /// - scheme: The current color scheme. + static func label(for scheme: ColorScheme) -> Color { + return scheme == .light ? Color.black : Color.white + } + /// A multi-platform solution for obtaining the window's background color. static var backgroundColor: Color { diff --git a/Sources/StylableScrollView/Extensions/Modifiers.swift b/Sources/StylableScrollView/Extensions/Modifiers.swift index 56f8109..448f076 100644 --- a/Sources/StylableScrollView/Extensions/Modifiers.swift +++ b/Sources/StylableScrollView/Extensions/Modifiers.swift @@ -18,7 +18,7 @@ import Foundation import SwiftUI -// MARK: - SCROLLVIEW STYLE +// MARK: - SCROLLVIEW STYLE @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public extension View { @@ -53,9 +53,10 @@ public extension View { /// ) /// } /// - /// ![A stretchable scroll view with a big text talking about French footballer Kylian Mbappé. On top, a stretchable header can be seen.](StretchableHeader-kmbappe.png) + /// ![A stretchable scroll view with a big text talking about French footballer + /// Kylian Mbappé. On top, a stretchable header can be seen.](StretchableHeader-kmbappe.png) /// - @inlinable @ViewBuilder func scrollViewStyle(_ style: S) -> some View where S : ScrollViewStyle { + @inlinable @ViewBuilder func scrollViewStyle(_ style: S) -> some View where S: ScrollViewStyle { self.environment(\.scrollViewStyle, AnyScrollViewStyle(style)) @@ -63,7 +64,7 @@ public extension View { } -// MARK: - STRETCHABLE HEADER +// MARK: - STRETCHABLE HEADER @available(iOS 15.0, macOS 12, *) @available(tvOS, unavailable) @available(watchOS, unavailable) @@ -85,18 +86,21 @@ public extension ScrollView { /// - title: The title that appears on top of the header. /// - navBar: The contents of the navigationBar that appears when scrolling. /// - @ViewBuilder @inlinable func stretchableHeader( + @ViewBuilder @inlinable func stretchableHeader( header: Image, title: () -> Title, - navBar: () -> NavBar - ) -> some View where Title: View, NavBar: View { + navBar: () -> NavBar, + trailingElements: @escaping (NavigationBarProxy) -> TrailingElements, + leadingElements: @escaping (NavigationBarProxy) -> LeadingElements + ) -> some View where Title: View, NavBar: View, TrailingElements: View, LeadingElements: View { StylableScrollView( .vertical, showIndicators: false, content: { self - }) + } + ) .scrollViewStyle( StretchableScrollViewStyle( header: { @@ -105,7 +109,13 @@ public extension ScrollView { .aspectRatio(contentMode: .fill) }, title: title, - navBarContent: navBar + navBarContent: navBar, + trailingElements: { + trailingElements($0) + }, + leadingElements: { + leadingElements($0) + } ) ) @@ -126,24 +136,35 @@ public extension ScrollView { /// - header: The view that will be used for the sticky header. /// - title: The title that appears on top of the header. /// - navBar: The contents of the navigationBar that appears when scrolling. + /// - trailingElements: The navigation bar elements that will appear on the trailing side. + /// - leadingElements: The navigation bar elements that will appear on the leading side. /// - @ViewBuilder @inlinable func stretchableHeader( + @ViewBuilder @inlinable func stretchableHeader( header: () -> Header, title: () -> Title, - navBar: () -> NavBar - ) -> some View where Header: View, Title: View, NavBar: View { + navBar: () -> NavBar, + trailingElements: @escaping (NavigationBarProxy) -> TrailingElements, + leadingElements: @escaping (NavigationBarProxy) -> LeadingElements + ) -> some View where Header: View, Title: View, NavBar: View, TrailingElements: View, LeadingElements: View { StylableScrollView( .vertical, showIndicators: false, content: { self - }) + } + ) .scrollViewStyle( StretchableScrollViewStyle( header: header, title: title, - navBarContent: navBar + navBarContent: navBar, + trailingElements: { + trailingElements($0) + }, + leadingElements: { + leadingElements($0) + } ) ) @@ -151,7 +172,7 @@ public extension ScrollView { } -// MARK: - SIZE MODIFIERS +// MARK: - SIZE MODIFIERS @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public extension View { @@ -175,7 +196,7 @@ public extension View { } -// MARK: - NAVIGATION BAR ELEMENTS +// MARK: - NAVIGATION BAR ELEMENTS extension View { /// Creates a fake navigation bar item for ``StretchableScrollViewStyle``'s fake navigation bar using @@ -184,7 +205,8 @@ extension View { /// - Parameters: /// - axis: The horizontal edge the element will appear at. /// - content: The element view - /// - affectedByColorChanges: Whether the element is affected by the changes in color when shown in a navigation Bar. Defaults to `true`. + /// - affectedByColorChanges: Whether the element is affected by + /// the changes in color when shown in a navigation Bar. Defaults to `true`. /// /// Use this modifier to set a specific navigation bar element for /// ``StretchableScrollViewStyle`` instances within a view: @@ -202,8 +224,17 @@ extension View { @available(iOS 15.0, macOS 12.0, *) @available(tvOS, unavailable) @available(watchOS, unavailable) + @available(*, deprecated, message: "Please pass your elements as arguments to the ScrollViewStyle.") @ViewBuilder public func navigationBarElement(axis: HorizontalEdge, _ content: () -> Content) -> some View { + /* + * This function passes the navigation bar elements as preference items to the scroll view style, + * but they do not update, even if a state variable is changed. + * + * For this reason, this function is deprecated and should be deleted before the stable release, + * unless we find a way to make it work as desired. + */ + #warning("TODO: We should remove this function before the stable release (X.y.z | X > 0).") self.preference( key: Preferences.NavigationBar.Elements.Key.self, value: [ @@ -215,4 +246,5 @@ extension View { ) } + } diff --git a/Sources/StylableScrollView/Configuration/Configuration.swift b/Sources/StylableScrollView/Namespaces/Configuration.swift similarity index 100% rename from Sources/StylableScrollView/Configuration/Configuration.swift rename to Sources/StylableScrollView/Namespaces/Configuration.swift diff --git a/Sources/StylableScrollView/Configuration/Environment.swift b/Sources/StylableScrollView/Namespaces/Environment.swift similarity index 100% rename from Sources/StylableScrollView/Configuration/Environment.swift rename to Sources/StylableScrollView/Namespaces/Environment.swift diff --git a/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift b/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift new file mode 100644 index 0000000..31b235e --- /dev/null +++ b/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift @@ -0,0 +1,57 @@ +/* +* THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS +* NON-VIOLENT PUBLIC LICENSE v4 ("LICENSE"). THE WORK IS PROTECTED BY +* COPYRIGHT AND ALL OTHER APPLICABLE LAWS. ANY USE OF THE WORK OTHER THAN +* AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY +* EXERCISING ANY RIGHTS TO THE WORK PROVIDED IN THIS LICENSE, YOU AGREE +* TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE +* MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +* CONTAINED HERE IN AS CONSIDERATION FOR ACCEPTING THE TERMS AND +* CONDITIONS OF THIS LICENSE AND FOR AGREEING TO BE BOUND BY THE TERMS +* AND CONDITIONS OF THIS LICENSE. +* +* StylableScrollView.swift +* +* Created by Alex Modroño Vara on 26/12/21. +* +*/ +import Foundation +import SwiftUI + +// MARK: - NAVIGATION BAR +// +/// A proxy for access to several aspects of a Navigation Bar Element, +/// such as whether the navigation bar has changed display mode, the +/// preferred color for navigation bar elements, and more. +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) +public struct NavigationBarProxy { + + public enum Mode { + case large + case inline + } + + public var mode: Mode + + public var elementsColor: Color + +} + +///// A proxy for access to the size and coordinate space (for anchor resolution) +///// of the container view. +// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) +// public struct GeometryProxy { +// +// /// The size of the container view. +// public var size: CGSize { get } +// +// /// Resolves the value of `anchor` to the container view. +// public subscript(anchor: Anchor) -> T { get } +// +// /// The safe area inset of the container view. +// public var safeAreaInsets: EdgeInsets { get } +// +// /// Returns the container view's bounds rectangle, converted to a defined +// /// coordinate space. +// public func frame(in coordinateSpace: CoordinateSpace) -> CGRect +// } diff --git a/Sources/StylableScrollView/Configuration/Preferences.swift b/Sources/StylableScrollView/Namespaces/Preferences.swift similarity index 98% rename from Sources/StylableScrollView/Configuration/Preferences.swift rename to Sources/StylableScrollView/Namespaces/Preferences.swift index 906cafe..0be8469 100644 --- a/Sources/StylableScrollView/Configuration/Preferences.swift +++ b/Sources/StylableScrollView/Namespaces/Preferences.swift @@ -18,6 +18,9 @@ import Foundation import SwiftUI +// MARK: – SWIFTLINT +// swiftlint:disable nesting + @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct Preferences { @@ -26,11 +29,11 @@ public struct Preferences { /// Allows us to read the minY of the header from ancestor views. public struct Key: PreferenceKey { - + public typealias Value = Data public static var defaultValue: Data = Data.init(minY: 0) - + public static func reduce(value: inout Data, nextValue: () -> Data) { value = nextValue() } @@ -74,7 +77,7 @@ public struct Preferences { public typealias Value = [Data] public static var defaultValue: [Data] = [] - + public static func reduce(value: inout [Data], nextValue: () -> [Data]) { value.append(contentsOf: nextValue()) } diff --git a/Sources/StylableScrollView/ScrollViewStyle.swift b/Sources/StylableScrollView/ScrollViewStyle.swift index df8b0b4..9558316 100644 --- a/Sources/StylableScrollView/ScrollViewStyle.swift +++ b/Sources/StylableScrollView/ScrollViewStyle.swift @@ -29,7 +29,7 @@ import SwiftUI public protocol ScrollViewStyle { /// A view that represents the body of a ScrollView. - associatedtype Body : View + associatedtype Body: View /// Creates a view that represents the body of a ScrollView. /// diff --git a/Sources/StylableScrollView/StylableScrollView.swift b/Sources/StylableScrollView/StylableScrollView.swift index 4a9fbc9..d9b4fe0 100644 --- a/Sources/StylableScrollView/StylableScrollView.swift +++ b/Sources/StylableScrollView/StylableScrollView.swift @@ -70,14 +70,15 @@ import SwiftUI /// ) /// } /// -/// ![A stretchable scroll view with a big text talking about French footballer Kylian Mbappé. On top, a stretchable header can be seen.](StretchableHeader-kmbappe.png) +/// ![A stretchable scroll view with a big text talking about +/// French footballer Kylian Mbappé. On top, a stretchable header can be seen.](StretchableHeader-kmbappe.png) /// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct StylableScrollView: View { /// The style that is being used. @Environment(\.scrollViewStyle) private var style - + /// The configuration for the ScrollView private var configuration: ScrollViewStyleConfiguration @@ -93,7 +94,7 @@ public struct StylableScrollView: View { } -public extension StylableScrollView where Content : View { +public extension StylableScrollView where Content: View { /// Creates an instance of an ``StylableScrollView`` that is scrollable in a specific /// axis, and can show indicators while scrolling, using the body that you define. @@ -104,7 +105,11 @@ public extension StylableScrollView where Content : View { /// component of the content offset, in a way that's suitable for the platform. /// - content: The scroll view's content. /// - init(_ axes: Axis.Set = .vertical, showIndicators: Bool = true, content: () -> Content) { + init( + _ axes: Axis.Set = .vertical, + showIndicators: Bool = true, + content: () -> Content + ) { self.init( ScrollViewStyleConfiguration( diff --git a/Sources/StylableScrollView/Styles/AnyScrollViewStyle.swift b/Sources/StylableScrollView/Styles/AnyScrollViewStyle.swift index 5a4fdf5..b6961f4 100644 --- a/Sources/StylableScrollView/Styles/AnyScrollViewStyle.swift +++ b/Sources/StylableScrollView/Styles/AnyScrollViewStyle.swift @@ -21,11 +21,11 @@ import SwiftUI /// A type-erased ``ScrollViewStyle``. public struct AnyScrollViewStyle: ScrollViewStyle { private let styleMakeBody: (ScrollViewStyle.Configuration) -> AnyView - + public init(_ style: S) { self.styleMakeBody = style.makeTypeErasedBody } - + public func makeBody(configuration: ScrollViewStyle.Configuration) -> AnyView { self.styleMakeBody(configuration) } diff --git a/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift b/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift index e14c20f..defa95d 100644 --- a/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift +++ b/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift @@ -23,41 +23,86 @@ import SwiftUI @available(iOS 15.0, macOS 12.0, *) @available(tvOS, unavailable) @available(watchOS, unavailable) -public struct StretchableScrollViewStyle: ScrollViewStyle where Header: View, Title: View, Content: View { +// swiftlint:disable:next line_length +public struct StretchableScrollViewStyle: ScrollViewStyle where Header: View, Title: View, Content: View, TE: View, LE: View { private let header: Header private let title: Title private let navBarContent: Content + private let trailingElements: (NavigationBarProxy) -> TE + private let leadingElements: (NavigationBarProxy) -> LE public let showBackButton: Bool private var headerHeight: CGFloat - public init(size headerHeight: CGFloat = 200, header: () -> Header, title: () -> Title, navBarContent: () -> Content, _ showBackButton: Bool = true) { + public init( + size headerHeight: CGFloat = 200, + header: () -> Header, + title: () -> Title, + navBarContent: () -> Content, + _ showBackButton: Bool = true, + trailingElements: @escaping (NavigationBarProxy) -> TE, + leadingElements: @escaping (NavigationBarProxy) -> LE + ) { self.headerHeight = headerHeight self.header = header() self.title = title() self.navBarContent = navBarContent() self.showBackButton = showBackButton + self.trailingElements = trailingElements + self.leadingElements = leadingElements } - private struct view: View { + private class Manager: ObservableObject { - typealias navBarPreferenceKey = Preferences.NavigationBar.Elements.Key - typealias navBarPreferenceData = Preferences.NavigationBar.Elements.Data + @Environment(\.colorScheme) var colorScheme + + @Published var minY: CGFloat = 0 { + didSet { + self.materialOpacity = Double(-minY > 80 ? -(minY + 80) / 30 : 0) + } + } + @Published var navigationBarProxy: NavigationBarProxy = NavigationBarProxy( + mode: .large, + elementsColor: Color.white + ) + + /// The opacity of the material view that is used as the background of the fake navigation bar. + @Published var materialOpacity: CGFloat = 0 { + didSet { + self.navigationBarProxy.mode = materialOpacity < 0.3 ? .large : .inline + + if self.colorScheme == .light { + + self.navigationBarProxy.elementsColor = self.navigationBarProxy.mode == .large ? + Color.backgroundColor : Color.backgroundColorInverted(for: self.colorScheme) + + } + + } + } + + } + + private struct BodyView: View { + + @ObservedObject var manager: Manager = Manager() - @State var minY: CGFloat = 0 @State var leadingNavBarElements: [AnyView] = [] @State var trailingNavBarElements: [AnyView] = [] + let trailingElements: (NavigationBarProxy) -> TE + let leadingElements: (NavigationBarProxy) -> LE + @Environment(\.colorScheme) var colorScheme @Environment(\.layoutDirection) var layoutDirection: LayoutDirection var configuration: ScrollViewStyleConfiguration - + let header: Header let title: Title let navBarContent: Content @@ -75,22 +120,7 @@ public struct StretchableScrollViewStyle: ScrollViewStyl configuration.content } .onPreferenceChange(Preferences.Header.Key.self) { preference in - self.minY = preference.minY - } - .onPreferenceChange(navBarPreferenceKey.self) { preferences in - - for p in preferences { - - if p.axis == .leading { - self.leadingNavBarElements.append(p.element) - } - - if p.axis == .trailing { - self.trailingNavBarElements.append(p.element) - } - - } - + self.manager.minY = preference.minY } } ) @@ -99,21 +129,20 @@ public struct StretchableScrollViewStyle: ScrollViewStyl if self.showBackButton { BackButton( - color: navBarElementColor( - for: materialOpacity( - for: self.minY - ), - self.colorScheme - ) + color: self.manager.navigationBarProxy.elementsColor ) .shadow(radius: 10) } - getNavBarElements(for: self.layoutDirection == .leftToRight ? .leading : .trailing) + self.leadingElements( + self.manager.navigationBarProxy + ) Spacer() - getNavBarElements(for: self.layoutDirection == .leftToRight ? .trailing : .leading) + self.trailingElements( + self.manager.navigationBarProxy + ) } .padding(.top, 5) @@ -122,46 +151,6 @@ public struct StretchableScrollViewStyle: ScrollViewStyl ) } - @ViewBuilder private func getNavBarElements(for horizontalEdge: HorizontalEdge) -> some View { - - HStack { - if horizontalEdge == .leading { - if self.leadingNavBarElements.count > 0 { - ForEach( - 0 ..< self.leadingNavBarElements.count - ) { index in - self.leadingNavBarElements[index] - } - } - } else { - if self.trailingNavBarElements.count > 0 { - ForEach( - 0 ..< self.trailingNavBarElements.count - ) { index in - self.trailingNavBarElements[index] - } - } - } - } - .foregroundColor( - navBarElementColor( - for: materialOpacity( - for: self.minY - ), - self.colorScheme - ) - ) - - } - - private func navBarElementColor(for materialOpacity: Double, _ scheme: ColorScheme) -> Color { - if scheme == .light { - return materialOpacity < 0.3 ? Color.backgroundColor : Color.backgroundColorInverted(for: self.colorScheme) - } else { - return Color.white - } - } - public var headerView: some View { GeometryReader(content: { proxy -> AnyView in @@ -189,8 +178,7 @@ public struct StretchableScrollViewStyle: ScrollViewStyl .background(.ultraThickMaterial) .overlay( Divider() - .foregroundColor(.gray) - , alignment: .bottom + .foregroundColor(.gray), alignment: .bottom ) } .opacity(materialOpacity(for: minY)) @@ -212,7 +200,7 @@ public struct StretchableScrollViewStyle: ScrollViewStyl .offset(y: minY > 0 ? -minY : 0) .zIndex(0.8) .opacity(materialOpacity(for: minY) > 0.3 ? 0 : 1) - .animation(.easeIn(duration: 0.2)), + .animation(.easeIn(duration: 0.2), value: materialOpacity(for: minY)), alignment: .bottomLeading ) .preference( @@ -247,7 +235,7 @@ public struct StretchableScrollViewStyle: ScrollViewStyl private func getHeightForHeader(for minY: CGFloat, _ isOptional: Bool = true) -> CGFloat? { return minY > 0 ? headerHeight + minY : isOptional ? nil : headerHeight } - + } /// Creates a view that represents a body that is scrollable in the direction of the given @@ -264,7 +252,9 @@ public struct StretchableScrollViewStyle: ScrollViewStyl NSLog("Configuration.axes was passed as %d, but .vertical will be used instead.", configuration.axes.rawValue) } - return StretchableScrollViewStyle.view( + return StretchableScrollViewStyle.BodyView( + trailingElements: self.trailingElements, + leadingElements: self.leadingElements, configuration: configuration, header: self.header, title: self.title, From f36a2b3a081fe75f6d8bb642ff98baa238956b29 Mon Sep 17 00:00:00 2001 From: amodrono Date: Sun, 26 Dec 2021 13:21:32 +0100 Subject: [PATCH 2/3] fix(navigation_bar): change order of trailing and leading elements. --- .../Extensions/Modifiers.swift | 26 +++++++++---------- .../Namespaces/NavigationBarProxy.swift | 19 -------------- .../Styles/StretchableScrollViewStyle.swift | 8 +++--- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/Sources/StylableScrollView/Extensions/Modifiers.swift b/Sources/StylableScrollView/Extensions/Modifiers.swift index 448f076..e73c5cf 100644 --- a/Sources/StylableScrollView/Extensions/Modifiers.swift +++ b/Sources/StylableScrollView/Extensions/Modifiers.swift @@ -85,14 +85,16 @@ public extension ScrollView { /// - header: The header image that will be used for the sticky header. /// - title: The title that appears on top of the header. /// - navBar: The contents of the navigationBar that appears when scrolling. + /// - leadingElements: The navigation bar elements that will appear on the leading side. + /// - trailingElements: The navigation bar elements that will appear on the trailing side. /// @ViewBuilder @inlinable func stretchableHeader( header: Image, title: () -> Title, navBar: () -> NavBar, - trailingElements: @escaping (NavigationBarProxy) -> TrailingElements, - leadingElements: @escaping (NavigationBarProxy) -> LeadingElements - ) -> some View where Title: View, NavBar: View, TrailingElements: View, LeadingElements: View { + leadingElements: @escaping (NavigationBarProxy) -> LeadingElements, + trailingElements: @escaping (NavigationBarProxy) -> TrailingElements + ) -> some View where Title: View, NavBar: View, LeadingElements: View, TrailingElements: View { StylableScrollView( .vertical, @@ -110,11 +112,10 @@ public extension ScrollView { }, title: title, navBarContent: navBar, - trailingElements: { - trailingElements($0) - }, leadingElements: { leadingElements($0) + }, trailingElements: { + trailingElements($0) } ) ) @@ -136,16 +137,16 @@ public extension ScrollView { /// - header: The view that will be used for the sticky header. /// - title: The title that appears on top of the header. /// - navBar: The contents of the navigationBar that appears when scrolling. - /// - trailingElements: The navigation bar elements that will appear on the trailing side. /// - leadingElements: The navigation bar elements that will appear on the leading side. + /// - trailingElements: The navigation bar elements that will appear on the trailing side. /// @ViewBuilder @inlinable func stretchableHeader( header: () -> Header, title: () -> Title, navBar: () -> NavBar, - trailingElements: @escaping (NavigationBarProxy) -> TrailingElements, - leadingElements: @escaping (NavigationBarProxy) -> LeadingElements - ) -> some View where Header: View, Title: View, NavBar: View, TrailingElements: View, LeadingElements: View { + leadingElements: @escaping (NavigationBarProxy) -> LeadingElements, + trailingElements: @escaping (NavigationBarProxy) -> TrailingElements + ) -> some View where Header: View, Title: View, NavBar: View, LeadingElements: View, TrailingElements: View { StylableScrollView( .vertical, @@ -159,11 +160,10 @@ public extension ScrollView { header: header, title: title, navBarContent: navBar, - trailingElements: { - trailingElements($0) - }, leadingElements: { leadingElements($0) + }, trailingElements: { + trailingElements($0) } ) ) diff --git a/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift b/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift index 31b235e..7fdd7a9 100644 --- a/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift +++ b/Sources/StylableScrollView/Namespaces/NavigationBarProxy.swift @@ -36,22 +36,3 @@ public struct NavigationBarProxy { public var elementsColor: Color } - -///// A proxy for access to the size and coordinate space (for anchor resolution) -///// of the container view. -// @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) -// public struct GeometryProxy { -// -// /// The size of the container view. -// public var size: CGSize { get } -// -// /// Resolves the value of `anchor` to the container view. -// public subscript(anchor: Anchor) -> T { get } -// -// /// The safe area inset of the container view. -// public var safeAreaInsets: EdgeInsets { get } -// -// /// Returns the container view's bounds rectangle, converted to a defined -// /// coordinate space. -// public func frame(in coordinateSpace: CoordinateSpace) -> CGRect -// } diff --git a/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift b/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift index defa95d..4d102cd 100644 --- a/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift +++ b/Sources/StylableScrollView/Styles/StretchableScrollViewStyle.swift @@ -24,7 +24,7 @@ import SwiftUI @available(tvOS, unavailable) @available(watchOS, unavailable) // swiftlint:disable:next line_length -public struct StretchableScrollViewStyle: ScrollViewStyle where Header: View, Title: View, Content: View, TE: View, LE: View { +public struct StretchableScrollViewStyle: ScrollViewStyle where Header: View, Title: View, Content: View, LE: View, TE: View { private let header: Header private let title: Title @@ -42,8 +42,8 @@ public struct StretchableScrollViewStyle: Scroll title: () -> Title, navBarContent: () -> Content, _ showBackButton: Bool = true, - trailingElements: @escaping (NavigationBarProxy) -> TE, - leadingElements: @escaping (NavigationBarProxy) -> LE + leadingElements: @escaping (NavigationBarProxy) -> LE, + trailingElements: @escaping (NavigationBarProxy) -> TE ) { self.headerHeight = headerHeight @@ -51,8 +51,8 @@ public struct StretchableScrollViewStyle: Scroll self.title = title() self.navBarContent = navBarContent() self.showBackButton = showBackButton - self.trailingElements = trailingElements self.leadingElements = leadingElements + self.trailingElements = trailingElements } From 37a41262942bd04d2eb4cb62a0d16a7053d85a28 Mon Sep 17 00:00:00 2001 From: amodrono Date: Sun, 26 Dec 2021 13:43:15 +0100 Subject: [PATCH 3/3] chore(version): Added version number to `StylableScrollView` --- .../StylableScrollView/Extensions/Modifiers.swift | 8 ++++++-- .../StylableScrollView/Namespaces/Constants.swift | 14 ++++++++++++++ .../StylableScrollView/StylableScrollView.swift | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 Sources/StylableScrollView/Namespaces/Constants.swift diff --git a/Sources/StylableScrollView/Extensions/Modifiers.swift b/Sources/StylableScrollView/Extensions/Modifiers.swift index e73c5cf..0f48344 100644 --- a/Sources/StylableScrollView/Extensions/Modifiers.swift +++ b/Sources/StylableScrollView/Extensions/Modifiers.swift @@ -225,7 +225,11 @@ extension View { @available(tvOS, unavailable) @available(watchOS, unavailable) @available(*, deprecated, message: "Please pass your elements as arguments to the ScrollViewStyle.") - @ViewBuilder public func navigationBarElement(axis: HorizontalEdge, _ content: () -> Content) -> some View { + public func navigationBarElement(axis: HorizontalEdge, _ content: () -> Content) -> some View { + + guard Constants.MAJOR < 1 else { + fatalError(".navigationBarElement(axis:,_:) is obsolete and is not working anymore.") + } /* * This function passes the navigation bar elements as preference items to the scroll view style, @@ -235,7 +239,7 @@ extension View { * unless we find a way to make it work as desired. */ #warning("TODO: We should remove this function before the stable release (X.y.z | X > 0).") - self.preference( + return self.preference( key: Preferences.NavigationBar.Elements.Key.self, value: [ Preferences.NavigationBar.Elements.Data( diff --git a/Sources/StylableScrollView/Namespaces/Constants.swift b/Sources/StylableScrollView/Namespaces/Constants.swift new file mode 100644 index 0000000..40aa83f --- /dev/null +++ b/Sources/StylableScrollView/Namespaces/Constants.swift @@ -0,0 +1,14 @@ +// +// File.swift +// +// +// Created by Alex Modroño Vara on 26/12/21. +// + +import Foundation + +struct Constants { + static let MAJOR = 0 + static let MINOR = 1 + static let PATCH = 0 +} diff --git a/Sources/StylableScrollView/StylableScrollView.swift b/Sources/StylableScrollView/StylableScrollView.swift index d9b4fe0..7cc2184 100644 --- a/Sources/StylableScrollView/StylableScrollView.swift +++ b/Sources/StylableScrollView/StylableScrollView.swift @@ -76,6 +76,9 @@ import SwiftUI @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct StylableScrollView: View { + /// The actual version of StylableScrollView that is being used. + public let version: String = "\(Constants.MAJOR).\(Constants.MINOR).\(Constants.PATCH)" + /// The style that is being used. @Environment(\.scrollViewStyle) private var style