From 47b7c037327ad9f67a95a08054fb5377c6c488b3 Mon Sep 17 00:00:00 2001 From: Alexandr Romanov Date: Tue, 10 May 2022 20:25:15 +0300 Subject: [PATCH] Up minimal macOS and watchOS versions --- .../xcschemes/OversizeUI.xcscheme | 2 +- Example/Example.xcodeproj/project.pbxproj | 28 +- .../xcschemes/Example (iOS).xcscheme | 2 +- Example/Shared/ComponentsList.swift | 8 +- Example/Shared/DemoPages/AvatarDemo.swift | 2 +- Example/Shared/DemoPages/ButtonsDemo.swift | 2 +- Example/Shared/DemoPages/GridSelectDemo.swift | 2 +- Example/Shared/DemoPages/IconsDemo.swift | 11 +- Example/Shared/DemoPages/PageDemo.swift | 2 + .../DemoPages/SegmentedControlDemo.swift | 2 +- Example/Shared/DemoPages/SurfaceDemo.swift | 3 +- Example/Shared/DemoPages/TextFieldDemo.swift | 4 +- Package.swift | 4 +- .../Controls/ContentView/ContentView.swift | 13 +- .../Controls/IconPicker/IconPicker.swift | 192 +++--- .../LocationPicker/LocationPicker.swift | 126 ++-- .../Controls/LocationPicker/MapView.swift | 78 +-- .../NavigationBar/ModalNavigationBar.swift | 616 +++++++++--------- .../Controls/PageView/PageView.swift | 378 +++++------ .../Controls/Surface/MaterialSurface.swift | 218 ++++--- .../Extensions/View/View+Navigationable.swift | 4 +- .../Apperance/AppearanceSettingView.swift | 340 +++++----- .../Modules/PINCode/PINCodeView.swift | 10 +- 23 files changed, 1030 insertions(+), 1017 deletions(-) diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/OversizeUI.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/OversizeUI.xcscheme index 831d4fe..eab16bf 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/OversizeUI.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/OversizeUI.xcscheme @@ -1,6 +1,6 @@ some View { switch secondaryButton { @@ -196,10 +194,9 @@ extension ContentView { } .style(.gray) .disabled(true) - + case .none: EmptyView() } } } - diff --git a/Sources/OversizeUI/Controls/IconPicker/IconPicker.swift b/Sources/OversizeUI/Controls/IconPicker/IconPicker.swift index 3c825bd..04e8a66 100644 --- a/Sources/OversizeUI/Controls/IconPicker/IconPicker.swift +++ b/Sources/OversizeUI/Controls/IconPicker/IconPicker.swift @@ -5,118 +5,120 @@ import SwiftUI -public struct IconPicker: View { - @Environment(\.theme) private var theme: ThemeSettings - @Environment(\.horizontalSizeClass) var horizontalSizeClass +#if os(iOS) + public struct IconPicker: View { + @Environment(\.theme) private var theme: ThemeSettings + @Environment(\.horizontalSizeClass) var horizontalSizeClass - private let label: String - private let icons: [Image] - @Binding private var selection: Image? - @State private var showModal = false - @State private var isSelected = false + private let label: String + private let icons: [Image] + @Binding private var selection: Image? + @State private var showModal = false + @State private var isSelected = false - @State private var selectedIndex: Int? + @State private var selectedIndex: Int? - @State var offset = CGPoint(x: 0, y: 0) - - private var gridPadding: CGFloat { - guard let sizeClass = horizontalSizeClass else { return 40 } - switch sizeClass { - case .compact: - return 60 - default: - return 72 + @State var offset = CGPoint(x: 0, y: 0) + + private var gridPadding: CGFloat { + guard let sizeClass = horizontalSizeClass else { return 40 } + switch sizeClass { + case .compact: + return 60 + default: + return 72 + } } - } - public init(_ label: String, - _ icons: [Image], - selection: Binding) - { - self.label = label - self.icons = icons - _selection = selection - } + public init(_ label: String, + _ icons: [Image], + selection: Binding) + { + self.label = label + self.icons = icons + _selection = selection + } - public var body: some View { - Button { - self.showModal.toggle() - } label: { - HStack(spacing: .xxSmall) { - Text(label) - .fontStyle(.subtitle1, color: .onSurfaceHighEmphasis) + public var body: some View { + Button { + self.showModal.toggle() + } label: { + HStack(spacing: .xxSmall) { + Text(label) + .fontStyle(.subtitle1, color: .onSurfaceHighEmphasis) + } + Spacer() + if let image = selection { + image + } + Icon(.chevronDown, color: .onSurfaceHighEmphasis) } - Spacer() - if let image = selection { - image + .frame(minWidth: 0, maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: Radius.medium.rawValue, + style: .continuous) + .fill(Color.surfaceSecondary) + .overlay( + RoundedRectangle(cornerRadius: Radius.medium.rawValue, + style: .continuous) + .stroke(theme.borderTextFields + ? Color.border + : Color.surfaceSecondary, lineWidth: CGFloat(theme.borderSize)) + ) + ) + .sheet(isPresented: $showModal) { + modal } - Icon(.chevronDown, color: .onSurfaceHighEmphasis) } - .frame(minWidth: 0, maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: Radius.medium.rawValue, - style: .continuous) - .fill(Color.surfaceSecondary) - .overlay( - RoundedRectangle(cornerRadius: Radius.medium.rawValue, - style: .continuous) - .stroke(theme.borderTextFields - ? Color.border - : Color.surfaceSecondary, lineWidth: CGFloat(theme.borderSize)) - ) - ) - .sheet(isPresented: $showModal) { - modal - } - } - private var modal: some View { - PageView(label) { - ScrollView { - LazyVGrid(columns: [GridItem(.adaptive(minimum: gridPadding))]) { - ForEach(icons.indices, id: \.self) { index in - Button(action: { - selectedIndex = index + private var modal: some View { + PageView(label) { + ScrollView { + LazyVGrid(columns: [GridItem(.adaptive(minimum: gridPadding))]) { + ForEach(icons.indices, id: \.self) { index in + Button(action: { + selectedIndex = index - }, - label: { - if index == selectedIndex { - Group { + }, + label: { + if index == selectedIndex { + Group { + icons[index] + .resizable() + + .frame(width: 24, height: 24, alignment: .center) + } + .overlay( + RoundedRectangle(cornerRadius: Radius.medium.rawValue, style: .continuous) + .strokeBorder(Color.border, lineWidth: 1) + .frame(width: 48, height: 48, alignment: .center) + ) + + } else { icons[index] .resizable() - .frame(width: 24, height: 24, alignment: .center) } - .overlay( - RoundedRectangle(cornerRadius: Radius.medium.rawValue, style: .continuous) - .strokeBorder(Color.border, lineWidth: 1) - .frame(width: 48, height: 48, alignment: .center) - ) - - } else { - icons[index] - .resizable() - .frame(width: 24, height: 24, alignment: .center) - } - }) - .padding(.vertical, horizontalSizeClass == .compact ? 12 : 20) + }) + .padding(.vertical, horizontalSizeClass == .compact ? 12 : 20) + } } + .padding(.top, .medium) + .paddingContent(.horizontal) + .paddingContent(.bottom) } - .padding(.top, .medium) - .paddingContent(.horizontal) - .paddingContent(.bottom) } - } - .leadingBar { - BarButton(type: .close) - } - .trailingBar { - BarButton(type: .secondary("Save", action: { - selection = icons[selectedIndex ?? 0] - isSelected = true - showModal.toggle() - })) + .leadingBar { + BarButton(type: .close) + } + .trailingBar { + BarButton(type: .secondary("Save", action: { + selection = icons[selectedIndex ?? 0] + isSelected = true + showModal.toggle() + })) + } } } -} +#endif diff --git a/Sources/OversizeUI/Controls/LocationPicker/LocationPicker.swift b/Sources/OversizeUI/Controls/LocationPicker/LocationPicker.swift index df3cd5c..b032f1a 100644 --- a/Sources/OversizeUI/Controls/LocationPicker/LocationPicker.swift +++ b/Sources/OversizeUI/Controls/LocationPicker/LocationPicker.swift @@ -6,77 +6,79 @@ import MapKit import SwiftUI -public struct LocationPicker: View { - @Environment(\.theme) private var theme: ThemeSettings +#if os(iOS) + public struct LocationPicker: View { + @Environment(\.theme) private var theme: ThemeSettings - private let label: String - private let saveButtonText: String? - @Binding var coordinates: CLLocationCoordinate2D - @State var offset = CGPoint(x: 0, y: 0) - @State private var showModal = false - @State private var isSelected = false + private let label: String + private let saveButtonText: String? + @Binding var coordinates: CLLocationCoordinate2D + @State var offset = CGPoint(x: 0, y: 0) + @State private var showModal = false + @State private var isSelected = false - public init(label: String, coordinates: Binding, saveButtonText: String? = nil) { - self.label = label - self.saveButtonText = saveButtonText - _coordinates = coordinates - } + public init(label: String, coordinates: Binding, saveButtonText: String? = nil) { + self.label = label + self.saveButtonText = saveButtonText + _coordinates = coordinates + } - public var body: some View { - Button { - self.showModal.toggle() - } label: { - HStack(spacing: .xxSmall) { - Text(label) - .fontStyle(.subtitle1, color: .onSurfaceHighEmphasis) - } - Spacer() - Text(String(coordinates.latitude)) - Text(String(coordinates.longitude)) + public var body: some View { + Button { + self.showModal.toggle() + } label: { + HStack(spacing: .xxSmall) { + Text(label) + .fontStyle(.subtitle1, color: .onSurfaceHighEmphasis) + } + Spacer() + Text(String(coordinates.latitude)) + Text(String(coordinates.longitude)) - Icon(.chevronDown, color: .onSurfaceHighEmphasis) - } - .frame(minWidth: 0, maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: Radius.medium.rawValue, - style: .continuous) - .fill(Color.surfaceSecondary) - .overlay( - RoundedRectangle(cornerRadius: Radius.medium.rawValue, - style: .continuous) - .stroke(theme.borderTextFields - ? Color.border - : Color.surfaceSecondary, lineWidth: CGFloat(theme.borderSize)) - ) - ) + Icon(.chevronDown, color: .onSurfaceHighEmphasis) + } + .frame(minWidth: 0, maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: Radius.medium.rawValue, + style: .continuous) + .fill(Color.surfaceSecondary) + .overlay( + RoundedRectangle(cornerRadius: Radius.medium.rawValue, + style: .continuous) + .stroke(theme.borderTextFields + ? Color.border + : Color.surfaceSecondary, lineWidth: CGFloat(theme.borderSize)) + ) + ) - .sheet(isPresented: $showModal) { - modal + .sheet(isPresented: $showModal) { + modal + } } - } - public var modal: some View { - ZStack { - MapView(centerCoordinate: $coordinates) - .ignoresSafeArea() + public var modal: some View { + ZStack { + MapView(centerCoordinate: $coordinates) + .ignoresSafeArea() - VStack { - Spacer() + VStack { + Spacer() - MaterialSurface { - Text("\(coordinates.latitude), \(coordinates.longitude)") - } + MaterialSurface { + Text("\(coordinates.latitude), \(coordinates.longitude)") + } - }.padding() - } - .navigationBar(label, style: .fixed($offset)) { - BarButton(type: .close) - } trailingBar: { - BarButton(type: .secondary(saveButtonText ?? "Save", action: { - isSelected = true - showModal.toggle() - })) + }.padding() + } + .navigationBar(label, style: .fixed($offset)) { + BarButton(type: .close) + } trailingBar: { + BarButton(type: .secondary(saveButtonText ?? "Save", action: { + isSelected = true + showModal.toggle() + })) + } } } -} +#endif diff --git a/Sources/OversizeUI/Controls/LocationPicker/MapView.swift b/Sources/OversizeUI/Controls/LocationPicker/MapView.swift index ea3f712..c9b9db5 100644 --- a/Sources/OversizeUI/Controls/LocationPicker/MapView.swift +++ b/Sources/OversizeUI/Controls/LocationPicker/MapView.swift @@ -8,60 +8,62 @@ import Foundation import MapKit import SwiftUI -public struct MapView: UIViewRepresentable { - @Binding var centerCoordinate: CLLocationCoordinate2D +#if os(iOS) + public struct MapView: UIViewRepresentable { + @Binding var centerCoordinate: CLLocationCoordinate2D - let mapView = MKMapView() + let mapView = MKMapView() - public func makeUIView(context: Context) -> MKMapView { - mapView.delegate = context.coordinator + public func makeUIView(context: Context) -> MKMapView { + mapView.delegate = context.coordinator - // mapView.centerCoordinate = centerCoordinate - let center = CLLocationCoordinate2D(latitude: centerCoordinate.latitude, longitude: centerCoordinate.longitude) + // mapView.centerCoordinate = centerCoordinate + let center = CLLocationCoordinate2D(latitude: centerCoordinate.latitude, longitude: centerCoordinate.longitude) - let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1) - let region = MKCoordinateRegion(center: center, span: span) - mapView.setRegion(region, animated: true) + let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1) + let region = MKCoordinateRegion(center: center, span: span) + mapView.setRegion(region, animated: true) - return mapView - } + return mapView + } - public func updateUIView(_: MKMapView, context _: Context) {} + public func updateUIView(_: MKMapView, context _: Context) {} - public func makeCoordinator() -> Coordinator { - Coordinator(self) - } + public func makeCoordinator() -> Coordinator { + Coordinator(self) + } - public class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate { - var parent: MapView + public class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate { + var parent: MapView - var gRecognizer = UITapGestureRecognizer() + var gRecognizer = UITapGestureRecognizer() - init(_ parent: MapView) { - self.parent = parent - super.init() - gRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler)) - gRecognizer.delegate = self - self.parent.mapView.addGestureRecognizer(gRecognizer) - } + init(_ parent: MapView) { + self.parent = parent + super.init() + gRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler)) + gRecognizer.delegate = self + self.parent.mapView.addGestureRecognizer(gRecognizer) + } - @objc func tapHandler(_: UITapGestureRecognizer) { - let location = gRecognizer.location(in: parent.mapView) + @objc func tapHandler(_: UITapGestureRecognizer) { + let location = gRecognizer.location(in: parent.mapView) - let coordinate = parent.mapView.convert(location, toCoordinateFrom: parent.mapView) + let coordinate = parent.mapView.convert(location, toCoordinateFrom: parent.mapView) - withAnimation { - let clObject = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) - parent.centerCoordinate = clObject + withAnimation { + let clObject = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) + parent.centerCoordinate = clObject - let annotation = MKPointAnnotation() - annotation.coordinate = clObject + let annotation = MKPointAnnotation() + annotation.coordinate = clObject - withAnimation { - parent.mapView.removeAnnotations(parent.mapView.annotations) - parent.mapView.addAnnotation(annotation) + withAnimation { + parent.mapView.removeAnnotations(parent.mapView.annotations) + parent.mapView.addAnnotation(annotation) + } } } } } -} +#endif diff --git a/Sources/OversizeUI/Controls/NavigationBar/ModalNavigationBar.swift b/Sources/OversizeUI/Controls/NavigationBar/ModalNavigationBar.swift index 3a0cd90..ce444ff 100644 --- a/Sources/OversizeUI/Controls/NavigationBar/ModalNavigationBar.swift +++ b/Sources/OversizeUI/Controls/NavigationBar/ModalNavigationBar.swift @@ -5,358 +5,358 @@ import SwiftUI -#if os(iOS) - public struct ModalNavigationBar: View { - public let leadingBar: () -> LeadingBar? - public let trailingBar: () -> TrailingBar? - public let bottomBar: () -> BottomBar? - - @Environment(\.screenSize) var screenSize - - private var title: String - private var subtitle: String = "" - private var bigTitle: Bool - private let modalityPresent: Bool - private let alwaysSlideSmallTile: Bool - - @Binding public var offset: CGPoint - - private var maxHeight: CGFloat = 100 - - private let background: Color - - public init(title: String, - bigTitle: Bool = true, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - background: Color = Color.backgroundPrimary, - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder leadingBar: @escaping () -> LeadingBar, - @ViewBuilder trailingBar: @escaping () -> TrailingBar, - @ViewBuilder bottomBar: @escaping () -> BottomBar) - { - self.title = title - self.bigTitle = bigTitle - _offset = offset - self.leadingBar = leadingBar - self.trailingBar = trailingBar - self.bottomBar = bottomBar - self.background = background - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - } +@available(iOS 14.0, *) +public struct ModalNavigationBar: View { + public let leadingBar: () -> LeadingBar? + public let trailingBar: () -> TrailingBar? + public let bottomBar: () -> BottomBar? + + @Environment(\.screenSize) var screenSize + + private var title: String + private var subtitle: String = "" + private var bigTitle: Bool + private let modalityPresent: Bool + private let alwaysSlideSmallTile: Bool + + @Binding public var offset: CGPoint + + private var maxHeight: CGFloat = 100 + + private let background: Color + + public init(title: String, + bigTitle: Bool = true, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + background: Color = Color.backgroundPrimary, + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder leadingBar: @escaping () -> LeadingBar, + @ViewBuilder trailingBar: @escaping () -> TrailingBar, + @ViewBuilder bottomBar: @escaping () -> BottomBar) + { + self.title = title + self.bigTitle = bigTitle + _offset = offset + self.leadingBar = leadingBar + self.trailingBar = trailingBar + self.bottomBar = bottomBar + self.background = background + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + } - public var body: some View { - ZStack(alignment: .top) { - if bigTitle { - VStack(alignment: .leading) { - Spacer() + public var body: some View { + ZStack(alignment: .top) { + if bigTitle { + VStack(alignment: .leading) { + Spacer() - HStack { - Text(title) - .fontStyle(.largeTitle) - .opacity(largeTitleOpacity) - .padding(.bottom, 8) - // .rotation3DEffect(.degrees(Double(offset.y)), axis: (x: 1, y: 0, z: 0)) + HStack { + Text(title) + .fontStyle(.largeTitle) + .opacity(largeTitleOpacity) + .padding(.bottom, 8) + // .rotation3DEffect(.degrees(Double(offset.y)), axis: (x: 1, y: 0, z: 0)) - Spacer() - } + Spacer() + } - }.frame(maxHeight: headerHeight) + }.frame(maxHeight: headerHeight) - Rectangle() - .fill(Color.surfacePrimary) - .frame(maxWidth: .infinity, maxHeight: 60, alignment: .top) - .blur(radius: blurValue) - .offset(x: -20) - .opacity(smallBackgroundOpacity) - } + Rectangle() + .fill(Color.surfacePrimary) + .frame(maxWidth: .infinity, maxHeight: 60, alignment: .top) + .blur(radius: blurValue) + .offset(x: -20) + .opacity(smallBackgroundOpacity) + } - VStack(spacing: 20) { - ZStack { - HStack { - leadingBar() + VStack(spacing: 20) { + ZStack { + HStack { + leadingBar() - Spacer() - } + Spacer() + } - HStack { - Spacer() + HStack { + Spacer() - Text(title) - .fontStyle(.title3) - .multilineTextAlignment(.center) - .frame(minHeight: 40) - .opacity(smallTitleOpacity) - .offset(y: -smmallTitleOffset) + Text(title) + .fontStyle(.title3) + .multilineTextAlignment(.center) + .frame(minHeight: 40) + .opacity(smallTitleOpacity) + .offset(y: -smmallTitleOffset) - Spacer() - } + Spacer() + } - HStack { - Spacer() + HStack { + Spacer() - trailingBar() - } + trailingBar() } - - bottomBar() } - } - .padding(.top, modalityPresent ? screenSize.safeAreaTop + 20 : 20) - .padding(.horizontal, 20) - .padding(.bottom, bigTitle ? 0 : 20) - .background(Color.surfacePrimary.opacity(smallBackgroundOpacity)) - .clipped() - .shadow(color: Color.black.opacity(min(sadowOpacity, 0.08)), - radius: max(offset.y * 0, 1, 8), - x: 0, - y: 2) - .navigationBarHidden(true) - } - - private var smallTitleOpacity: Double { - if bigTitle { - return Double((offset.y * 0.1) - 8) - } else { - return 1 + + bottomBar() } } + .padding(.top, modalityPresent ? screenSize.safeAreaTop + 20 : 20) + .padding(.horizontal, 20) + .padding(.bottom, bigTitle ? 0 : 20) + .background(Color.surfacePrimary.opacity(smallBackgroundOpacity)) + .clipped() + .shadow(color: Color.black.opacity(min(sadowOpacity, 0.08)), + radius: max(offset.y * 0, 1, 8), + x: 0, + y: 2) + #if os(iOS) + .navigationBarHidden(true) + #endif + } - private var smallBackgroundOpacity: Double { - Double(offset.y * 0.1) + private var smallTitleOpacity: Double { + if bigTitle { + return Double((offset.y * 0.1) - 8) + } else { + return 1 } + } - private var sadowOpacity: Double { - Double(offset.y * 0.001) - } + private var smallBackgroundOpacity: Double { + Double(offset.y * 0.1) + } - private var largeTitleOpacity: Double { - if offset.y < 0 { - return 1 - } else if offset.y > maxHeight { - return 0 - } else { - return Double(1 / (offset.y * 0.01)) - } - } + private var sadowOpacity: Double { + Double(offset.y * 0.001) + } - private var smmallTitleOffset: CGFloat { - if bigTitle || alwaysSlideSmallTile { - if offset.y < 50 { - return -50 - } else if offset.y > 50 * 2 { - return 0 - } else { - return offset.y - (50 * 2) - } - } else { - return 1 - } + private var largeTitleOpacity: Double { + if offset.y < 0 { + return 1 + } else if offset.y > maxHeight { + return 0 + } else { + return Double(1 / (offset.y * 0.01)) } + } - private var blurValue: CGFloat { - if offset.y < 1 { + private var smmallTitleOffset: CGFloat { + if bigTitle || alwaysSlideSmallTile { + if offset.y < 50 { + return -50 + } else if offset.y > 50 * 2 { return 0 - } else if offset.y < 70 { - return offset.y * 0.01 } else { - return 0 + return offset.y - (50 * 2) } + } else { + return 1 } + } - private var headerHeight: CGFloat { - if offset.y > 0 { - return maxHeight - (offset.y / 2) - } else { - return maxHeight - } + private var blurValue: CGFloat { + if offset.y < 1 { + return 0 + } else if offset.y < 70 { + return offset.y * 0.01 + } else { + return 0 } + } - private var height: CGFloat { - if offset.y < 86 { - return 86 - } else if offset.y > maxHeight { - return maxHeight - } else { - return offset.y - } + private var headerHeight: CGFloat { + if offset.y > 0 { + return maxHeight - (offset.y / 2) + } else { + return maxHeight } } - public extension ModalNavigationBar - where - LeadingBar == EmptyView, - TrailingBar == EmptyView, - BottomBar == EmptyView - { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - _offset = offset - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - leadingBar = { nil } - trailingBar = { nil } - bottomBar = { nil } + private var height: CGFloat { + if offset.y < 86 { + return 86 + } else if offset.y > maxHeight { + return maxHeight + } else { + return offset.y } } - - public extension ModalNavigationBar - where - BottomBar == EmptyView +} + +public extension ModalNavigationBar + where + LeadingBar == EmptyView, + TrailingBar == EmptyView, + BottomBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder leadingBar: @escaping () -> LeadingBar, - @ViewBuilder trailingBar: @escaping () -> TrailingBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - _offset = offset - self.leadingBar = leadingBar - self.trailingBar = trailingBar - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - bottomBar = { nil } - } + self.title = title + self.bigTitle = bigTitle + self.background = background + _offset = offset + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + leadingBar = { nil } + trailingBar = { nil } + bottomBar = { nil } } - - public extension ModalNavigationBar - where - TrailingBar == EmptyView, - BottomBar == EmptyView +} + +public extension ModalNavigationBar + where + BottomBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder leadingBar: @escaping () -> LeadingBar, + @ViewBuilder trailingBar: @escaping () -> TrailingBar) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder leadingBar: @escaping () -> LeadingBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - _offset = offset - self.leadingBar = leadingBar - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - trailingBar = { nil } - bottomBar = { nil } - } + self.title = title + self.bigTitle = bigTitle + self.background = background + _offset = offset + self.leadingBar = leadingBar + self.trailingBar = trailingBar + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + bottomBar = { nil } } - - public extension ModalNavigationBar - where - LeadingBar == EmptyView, - BottomBar == EmptyView +} + +public extension ModalNavigationBar + where + TrailingBar == EmptyView, + BottomBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder leadingBar: @escaping () -> LeadingBar) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder trailingBar: @escaping () -> TrailingBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - _offset = offset - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - leadingBar = { nil } - self.trailingBar = trailingBar - bottomBar = { nil } - } + self.title = title + self.bigTitle = bigTitle + self.background = background + _offset = offset + self.leadingBar = leadingBar + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + trailingBar = { nil } + bottomBar = { nil } } - - public extension ModalNavigationBar - where - LeadingBar == EmptyView, - TrailingBar == EmptyView +} + +public extension ModalNavigationBar + where + LeadingBar == EmptyView, + BottomBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder trailingBar: @escaping () -> TrailingBar) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder bottomBar: @escaping () -> BottomBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - _offset = offset - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - leadingBar = { nil } - trailingBar = { nil } - self.bottomBar = bottomBar - } + self.title = title + self.bigTitle = bigTitle + self.background = background + _offset = offset + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + leadingBar = { nil } + self.trailingBar = trailingBar + bottomBar = { nil } } - - public extension ModalNavigationBar - where - LeadingBar == EmptyView +} + +public extension ModalNavigationBar + where + LeadingBar == EmptyView, + TrailingBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder bottomBar: @escaping () -> BottomBar) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder trailingBar: @escaping () -> TrailingBar, - @ViewBuilder bottomBar: @escaping () -> BottomBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - _offset = offset - leadingBar = { nil } - self.trailingBar = trailingBar - self.bottomBar = bottomBar - } + self.title = title + self.bigTitle = bigTitle + self.background = background + _offset = offset + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + leadingBar = { nil } + trailingBar = { nil } + self.bottomBar = bottomBar } - - public extension ModalNavigationBar - where - TrailingBar == EmptyView +} + +public extension ModalNavigationBar + where + LeadingBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder trailingBar: @escaping () -> TrailingBar, + @ViewBuilder bottomBar: @escaping () -> BottomBar) { - init(title: String, - bigTitle: Bool = true, - background: Color = Color.backgroundPrimary, - offset: Binding = .constant(CGPoint(x: 0, y: 0)), - modalityPresent: Bool = true, - alwaysSlideSmallTile: Bool = false, - @ViewBuilder leadingBar: @escaping () -> LeadingBar, - @ViewBuilder bottomBar: @escaping () -> BottomBar) - { - self.title = title - self.bigTitle = bigTitle - self.background = background - self.modalityPresent = modalityPresent - self.alwaysSlideSmallTile = alwaysSlideSmallTile - _offset = offset - self.leadingBar = leadingBar - trailingBar = { nil } - self.bottomBar = bottomBar - } + self.title = title + self.bigTitle = bigTitle + self.background = background + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + _offset = offset + leadingBar = { nil } + self.trailingBar = trailingBar + self.bottomBar = bottomBar } - -#endif +} + +public extension ModalNavigationBar + where + TrailingBar == EmptyView +{ + init(title: String, + bigTitle: Bool = true, + background: Color = Color.backgroundPrimary, + offset: Binding = .constant(CGPoint(x: 0, y: 0)), + modalityPresent: Bool = true, + alwaysSlideSmallTile: Bool = false, + @ViewBuilder leadingBar: @escaping () -> LeadingBar, + @ViewBuilder bottomBar: @escaping () -> BottomBar) + { + self.title = title + self.bigTitle = bigTitle + self.background = background + self.modalityPresent = modalityPresent + self.alwaysSlideSmallTile = alwaysSlideSmallTile + _offset = offset + self.leadingBar = leadingBar + trailingBar = { nil } + self.bottomBar = bottomBar + } +} diff --git a/Sources/OversizeUI/Controls/PageView/PageView.swift b/Sources/OversizeUI/Controls/PageView/PageView.swift index b0957b1..d47f17c 100644 --- a/Sources/OversizeUI/Controls/PageView/PageView.swift +++ b/Sources/OversizeUI/Controls/PageView/PageView.swift @@ -4,211 +4,219 @@ // import SwiftUI -public struct PageView: View where Label: View, LeadingBar: View, TrailingBar: View, TopToolbar: View { - @Environment(\.screenSize) var screenSize - - private let title: String? - private let label: Label - private var isModalable = false - private var isLargeTitle = false - private var isAlwaysSlideSmallTile = false - @State private var offset: CGPoint = .init(x: 0, y: 0) - - private var leadingBar: LeadingBar? - private var trailingBar: TrailingBar? - private var topToolbar: TopToolbar? - - private var backgroundColor: Color = .backgroundPrimary - - public init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - } - public var body: some View { - content - } +#if os(iOS) + public struct PageView: View where Label: View, LeadingBar: View, TrailingBar: View, TopToolbar: View { + @Environment(\.screenSize) var screenSize - private var content: some View { - VStack(spacing: .zero) { - if title != nil || leadingBar != nil || trailingBar != nil || topToolbar != nil { - ModalNavigationBar(title: title ?? "", - bigTitle: isLargeTitle, - offset: $offset, - modalityPresent: !isModalable, - alwaysSlideSmallTile: isAlwaysSlideSmallTile, - leadingBar: { leadingBar }, - trailingBar: { trailingBar }, - bottomBar: { topToolbar }) - .zIndex(999_999_999) - } - ScrollViewOffset(offset: $offset) { - label + private let title: String? + private let label: Label + private var isModalable = false + private var isLargeTitle = false + private var isAlwaysSlideSmallTile = false + @State private var offset: CGPoint = .init(x: 0, y: 0) + + private var leadingBar: LeadingBar? + private var trailingBar: TrailingBar? + private var topToolbar: TopToolbar? + + private var backgroundColor: Color = .backgroundPrimary + + public init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + } + + public var body: some View { + content + } + + private var content: some View { + VStack(spacing: .zero) { + if title != nil || leadingBar != nil || trailingBar != nil || topToolbar != nil { + ModalNavigationBar(title: title ?? "", + bigTitle: isLargeTitle, + offset: $offset, + modalityPresent: !isModalable, + alwaysSlideSmallTile: isAlwaysSlideSmallTile, + leadingBar: { leadingBar }, + trailingBar: { trailingBar }, + bottomBar: { topToolbar }) + .zIndex(999_999_999) + } + ScrollViewOffset(offset: $offset) { + label + } } + .ignoresSafeArea(edges: .top) + .background(backgroundColor.ignoresSafeArea()) } - .ignoresSafeArea(edges: .top) - .background(backgroundColor.ignoresSafeArea()) - } - public func modalable(_ isModalable: Bool = true) -> PageView { - var control = self - control.isModalable = isModalable - return control - } - - - public func slideSmallTile(_ isSlise: Bool = true) -> PageView { - var control = self - control.isAlwaysSlideSmallTile = isSlise - return control - } - - public func navigationBarHidden(_ isModalable: Bool = true) -> PageView { - var control = self - control.isModalable = isModalable - return control - } + public func modalable(_ isModalable: Bool = true) -> PageView { + var control = self + control.isModalable = isModalable + return control + } - public func largeTitle(_ isLargeTitle: Bool = true) -> PageView { - var control = self - control.isLargeTitle = isLargeTitle - return control - } + public func slideSmallTile(_ isSlise: Bool = true) -> PageView { + var control = self + control.isAlwaysSlideSmallTile = isSlise + return control + } - public func backgroundSecondary(_ backgroundColor: Color = .backgroundSecondary) -> PageView { - var control = self - control.backgroundColor = backgroundColor - return control - } + public func navigationBarHidden(_ isModalable: Bool = true) -> PageView { + var control = self + control.isModalable = isModalable + return control + } - public func leadingBar(@ViewBuilder leadingBar: @escaping () -> LeadingBar) -> PageView { - var control = self - control.leadingBar = leadingBar() - return control - } + public func largeTitle(_ isLargeTitle: Bool = true) -> PageView { + var control = self + control.isLargeTitle = isLargeTitle + return control + } - public func trailingBar(@ViewBuilder trailingBar: @escaping () -> TrailingBar) -> PageView { - var control = self - control.trailingBar = trailingBar() - return control - } + public func backgroundColor(_ backgroundColor: Color = .backgroundSecondary) -> PageView { + var control = self + control.backgroundColor = backgroundColor + return control + } - public func topToolbar(@ViewBuilder topToolbar: @escaping () -> TopToolbar) -> PageView { - var control = self - control.topToolbar = topToolbar() - return control - } + public func backgroundSecondary() -> PageView { + var control = self + control.backgroundColor = .backgroundSecondary + return control + } + + public func leadingBar(@ViewBuilder leadingBar: @escaping () -> LeadingBar) -> PageView { + var control = self + control.leadingBar = leadingBar() + return control + } + + public func trailingBar(@ViewBuilder trailingBar: @escaping () -> TrailingBar) -> PageView { + var control = self + control.trailingBar = trailingBar() + return control + } + + public func topToolbar(@ViewBuilder topToolbar: @escaping () -> TopToolbar) -> PageView { + var control = self + control.topToolbar = topToolbar() + return control + } - public func bottomToolbar(style: PageViewBottomType = .shadow, @ViewBuilder bottomToolbar: @escaping () -> BottomToolbar) -> some View { - VStack(spacing: .zero) { - self - .overlay( - Group { - if style == .gradient { - VStack { - Spacer() - LinearGradient(colors: [backgroundColor.opacity(0), Color.surfacePrimary.opacity(1)], - startPoint: .top, - endPoint: .bottom) - .frame(height: 60) } - - } else { - EmptyView() - - } - }) - HStack { - Spacer() - bottomToolbar() - Spacer() + public func bottomToolbar(style: PageViewBottomType = .shadow, @ViewBuilder bottomToolbar: @escaping () -> BottomToolbar) -> some View { + VStack(spacing: .zero) { + self + .overlay( + Group { + if style == .gradient { + VStack { + Spacer() + LinearGradient(colors: [backgroundColor.opacity(0), Color.surfacePrimary.opacity(1)], + startPoint: .top, + endPoint: .bottom) + .frame(height: 60) + } + + } else { + EmptyView() + } + }) + HStack { + Spacer() + bottomToolbar() + Spacer() + } + .paddingContent() + .background(Color.surfacePrimary.shadowElevaton(style == .shadow ? .z2 : .z0)) } - .paddingContent() - .background(Color.surfacePrimary.shadowElevaton(style == .shadow ? .z2 : .z0)) + + .ignoresSafeArea(edges: .bottom) } - - .ignoresSafeArea(edges: .bottom) } -} -extension PageView { - public enum PageViewBottomType { - case shadow, gradient + public extension PageView { + enum PageViewBottomType { + case shadow, gradient + } } -} - -public extension PageView where LeadingBar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - leadingBar = nil + + public extension PageView where LeadingBar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + leadingBar = nil + } } -} - -public extension PageView where TrailingBar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - trailingBar = nil + + public extension PageView where TrailingBar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + trailingBar = nil + } } -} - -public extension PageView where TrailingBar == EmptyView, LeadingBar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - leadingBar = nil - trailingBar = nil + + public extension PageView where TrailingBar == EmptyView, LeadingBar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + leadingBar = nil + trailingBar = nil + } } -} - -public extension PageView where TrailingBar == EmptyView, LeadingBar == EmptyView, TopToolbar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - leadingBar = nil - trailingBar = nil - topToolbar = nil + + public extension PageView where TrailingBar == EmptyView, LeadingBar == EmptyView, TopToolbar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + leadingBar = nil + trailingBar = nil + topToolbar = nil + } } -} - -public extension PageView where LeadingBar == EmptyView, TopToolbar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - leadingBar = nil - topToolbar = nil + + public extension PageView where LeadingBar == EmptyView, TopToolbar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + leadingBar = nil + topToolbar = nil + } } -} - -public extension PageView where TrailingBar == EmptyView, TopToolbar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - trailingBar = nil - topToolbar = nil + + public extension PageView where TrailingBar == EmptyView, TopToolbar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + trailingBar = nil + topToolbar = nil + } } -} - -public extension PageView where TopToolbar == EmptyView { - init(_ title: String? = nil, - @ViewBuilder label: () -> Label) - { - self.title = title - self.label = label() - topToolbar = nil + + public extension PageView where TopToolbar == EmptyView { + init(_ title: String? = nil, + @ViewBuilder label: () -> Label) + { + self.title = title + self.label = label() + topToolbar = nil + } } -} +#endif diff --git a/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift b/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift index b26763d..ab4cd67 100644 --- a/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift +++ b/Sources/OversizeUI/Controls/Surface/MaterialSurface.swift @@ -5,129 +5,131 @@ import SwiftUI -public enum SurfaceMaterialTyps { - /// A material that's somewhat translucent. - case regular - /// A material that's more opaque than translucent. - case thick - /// A material that's more translucent than opaque. - case thin - /// A mostly translucent material. - case ultraThin - /// A mostly opaque material. - case ultraThick -} +#if os(iOS) || os(tvOS) || os(macOS) + public enum SurfaceMaterialTyps { + /// A material that's somewhat translucent. + case regular + /// A material that's more opaque than translucent. + case thick + /// A material that's more translucent than opaque. + case thin + /// A mostly translucent material. + case ultraThin + /// A mostly opaque material. + case ultraThick + } -public struct MaterialSurface: View { - @Environment(\.elevation) private var elevation: Elevation - @Environment(\.theme) private var theme: ThemeSettings - @Environment(\.controlRadius) var controlRadius: Radius - @Environment(\.controlPadding) var controlPadding: Space + public struct MaterialSurface: View { + @Environment(\.elevation) private var elevation: Elevation + @Environment(\.theme) private var theme: ThemeSettings + @Environment(\.controlRadius) var controlRadius: Radius + @Environment(\.controlPadding) var controlPadding: Space - private let label: Label - private let action: (() -> Void)? - private var border: Color? - private var material: SurfaceMaterialTyps = .regular + private let label: Label + private let action: (() -> Void)? + private var border: Color? + private var material: SurfaceMaterialTyps = .regular - public init(action: (() -> Void)? = nil, - @ViewBuilder label: () -> Label) - { - self.label = label() - self.action = action - } + public init(action: (() -> Void)? = nil, + @ViewBuilder label: () -> Label) + { + self.label = label() + self.action = action + } - public var body: some View { - if action != nil { - actionableSurface - } else { - surface + public var body: some View { + if action != nil { + actionableSurface + } else { + surface + } } - } - private var actionableSurface: some View { - Button { - action?() - } label: { - surface + private var actionableSurface: some View { + Button { + action?() + } label: { + surface + } + .buttonStyle(SurfaceButtonStyle()) } - .buttonStyle(SurfaceButtonStyle()) - } - @ViewBuilder - private var surface: some View { - if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) { - label - .padding(.all, controlPadding.rawValue) - .background(backgroundMaterial, - in: RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .continuous)) - .overlay(overlayView) - .shadowElevaton(elevation) - } else { - label - .padding(.all, controlPadding.rawValue) - .background(legacyBackgroundView) - .overlay(overlayView) - .shadowElevaton(elevation) + @ViewBuilder + private var surface: some View { + if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) { + label + .padding(.all, controlPadding.rawValue) + .background(backgroundMaterial, + in: RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .continuous)) + .overlay(overlayView) + .shadowElevaton(elevation) + } else { + label + .padding(.all, controlPadding.rawValue) + .background(legacyBackgroundView) + .overlay(overlayView) + .shadowElevaton(elevation) + } } - } - @ViewBuilder - private var overlayView: some View { - RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .continuous) - .stroke( - border != nil ? border ?? Color.clear - : theme.borderSurface - ? Color.border - : Color.clear, lineWidth: CGFloat(theme.borderSize) - ) - } + @ViewBuilder + private var overlayView: some View { + RoundedRectangle(cornerRadius: controlRadius.rawValue, style: .continuous) + .stroke( + border != nil ? border ?? Color.clear + : theme.borderSurface + ? Color.border + : Color.clear, lineWidth: CGFloat(theme.borderSize) + ) + } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - private var backgroundMaterial: Material { - switch material { - case .regular: - return .regularMaterial - case .thick: - return .thickMaterial - case .thin: - return .thinMaterial - case .ultraThin: - return .ultraThinMaterial - case .ultraThick: - return .ultraThinMaterial + @available(iOS 15.0, macOS 12.0, tvOS 15.0, *) + private var backgroundMaterial: Material { + switch material { + case .regular: + return .regularMaterial + case .thick: + return .thickMaterial + case .thin: + return .thinMaterial + case .ultraThin: + return .ultraThinMaterial + case .ultraThick: + return .ultraThinMaterial + } } - } - private var legacyBackgroundViewColor: Color { - switch material { - case .ultraThin: - return .surfacePrimary.opacity(0.15) - case .thin: - return .surfacePrimary.opacity(0.35) - case .regular: - return .surfacePrimary.opacity(0.5) - case .thick: - return .surfacePrimary.opacity(0.75) - case .ultraThick: - return .surfacePrimary.opacity(0.95) + private var legacyBackgroundViewColor: Color { + switch material { + case .ultraThin: + return .surfacePrimary.opacity(0.15) + case .thin: + return .surfacePrimary.opacity(0.35) + case .regular: + return .surfacePrimary.opacity(0.5) + case .thick: + return .surfacePrimary.opacity(0.75) + case .ultraThick: + return .surfacePrimary.opacity(0.95) + } } - } - private var legacyBackgroundView: some View { - RoundedRectangle(cornerRadius: controlRadius.rawValue, - style: .circular) - .fill(legacyBackgroundViewColor) - } + private var legacyBackgroundView: some View { + RoundedRectangle(cornerRadius: controlRadius.rawValue, + style: .circular) + .fill(legacyBackgroundViewColor) + } - public func surfaceStyle(_ material: SurfaceMaterialTyps) -> MaterialSurface { - var control = self - control.material = material - return control - } + public func surfaceStyle(_ material: SurfaceMaterialTyps) -> MaterialSurface { + var control = self + control.material = material + return control + } - public func surfaceBorderColor(_ border: Color? = Color.border) -> MaterialSurface { - var control = self - control.border = border - return control + public func surfaceBorderColor(_ border: Color? = Color.border) -> MaterialSurface { + var control = self + control.border = border + return control + } } -} +#endif diff --git a/Sources/OversizeUI/Extensions/View/View+Navigationable.swift b/Sources/OversizeUI/Extensions/View/View+Navigationable.swift index 6c1d974..ae74fe3 100644 --- a/Sources/OversizeUI/Extensions/View/View+Navigationable.swift +++ b/Sources/OversizeUI/Extensions/View/View+Navigationable.swift @@ -9,7 +9,9 @@ public extension View { func navigationable(_ navigationBarHidden: Bool = true) -> some View { NavigationView { self - .navigationBarHidden(navigationBarHidden) + #if os(iOS) + .navigationBarHidden(navigationBarHidden) + #endif } } } diff --git a/Sources/OversizeUI/Modules/Apperance/AppearanceSettingView.swift b/Sources/OversizeUI/Modules/Apperance/AppearanceSettingView.swift index f226163..d5243a7 100644 --- a/Sources/OversizeUI/Modules/Apperance/AppearanceSettingView.swift +++ b/Sources/OversizeUI/Modules/Apperance/AppearanceSettingView.swift @@ -5,214 +5,216 @@ import SwiftUI -public struct AppearanceSettingView: View { - @Environment(\.verticalSizeClass) private var verticalSizeClass - @Environment(\.presentationMode) var presentationMode - @Environment(\.theme) private var theme: ThemeSettings - @Environment(\.isPortrait) var isPortrait +#if os(iOS) + public struct AppearanceSettingView: View { + @Environment(\.verticalSizeClass) private var verticalSizeClass + @Environment(\.presentationMode) var presentationMode + @Environment(\.theme) private var theme: ThemeSettings + @Environment(\.isPortrait) var isPortrait - public init() {} + public init() {} - #if os(iOS) - @StateObject var iconSettings = AppIconSettings() - #endif + #if os(iOS) + @StateObject var iconSettings = AppIconSettings() + #endif - // swiftlint:disable trailing_comma - private let columns = [ - GridItem(.adaptive(minimum: 78)), - ] + // swiftlint:disable trailing_comma + private let columns = [ + GridItem(.adaptive(minimum: 78)), + ] - @State var offset = CGPoint(x: 0, y: 0) + @State var offset = CGPoint(x: 0, y: 0) - enum Destenation { - case font - case border - case radius - } + enum Destenation { + case font + case border + case radius + } - @State var pageDestenation: Destenation? + @State var pageDestenation: Destenation? - public var body: some View { - #if os(iOS) - PageView("App") { - iOSSettings - } - .leadingBar { - if !isPortrait, verticalSizeClass == .regular { - EmptyView() - } else { - BarButton(type: .back) + public var body: some View { + #if os(iOS) + PageView("App") { + iOSSettings } - } - .backgroundSecondary() + .leadingBar { + if !isPortrait, verticalSizeClass == .regular { + EmptyView() + } else { + BarButton(type: .back) + } + } + .backgroundSecondary() - #else - macSettings - #endif - } + #else + macSettings + #endif + } - #if os(iOS) - private var iOSSettings: some View { - VStack(alignment: .center, spacing: 0) { - apperance + #if os(iOS) + private var iOSSettings: some View { + VStack(alignment: .center, spacing: 0) { + apperance - accentColor + accentColor - advanded + advanded - if iconSettings.iconNames.count > 1 { - appIcon + if iconSettings.iconNames.count > 1 { + appIcon + } } + .preferredColorScheme(theme.appearance.colorScheme) + .accentColor(theme.accentColor) } - .preferredColorScheme(theme.appearance.colorScheme) - .accentColor(theme.accentColor) - } - #endif - - private var macSettings: some View { - VStack(alignment: .center, spacing: 0) { - advanded - } - .frame(width: 400, height: 300) - // swiftlint:disable multiple_closures_with_trailing_closure superfluous_disable_command - - .navigationTitle("Appearance") - - .preferredColorScheme(theme.appearance.colorScheme) - } - - #if os(iOS) - private var apperance: some View { - SectionView { - HStack { - ForEach(Appearance.allCases, id: \.self) { appearance in + #endif - HStack { - Spacer() + private var macSettings: some View { + VStack(alignment: .center, spacing: 0) { + advanded + } + .frame(width: 400, height: 300) + // swiftlint:disable multiple_closures_with_trailing_closure superfluous_disable_command - VStack(spacing: .zero) { - Text(appearance.name) - .foregroundColor(.onSurfaceHighEmphasis) - .font(.subheadline) - .bold() + .navigationTitle("Appearance") - appearance.image - .padding(.vertical, .medium) + .preferredColorScheme(theme.appearance.colorScheme) + } - if appearance == theme.appearance { - Icon(.checkCircle, color: Color.accent) - } else { - Icon(.circle, color: .onSurfaceMediumEmphasis) + #if os(iOS) + private var apperance: some View { + SectionView { + HStack { + ForEach(Appearance.allCases, id: \.self) { appearance in + + HStack { + Spacer() + + VStack(spacing: .zero) { + Text(appearance.name) + .foregroundColor(.onSurfaceHighEmphasis) + .font(.subheadline) + .bold() + + appearance.image + .padding(.vertical, .medium) + + if appearance == theme.appearance { + Icon(.checkCircle, color: Color.accent) + } else { + Icon(.circle, color: .onSurfaceMediumEmphasis) + } } + Spacer() + } + .onTapGesture { + theme.appearance = appearance } - Spacer() - } - .onTapGesture { - theme.appearance = appearance } - } - }.padding(.vertical, .xSmall) + }.padding(.vertical, .xSmall) + } } - } - #endif + #endif - #if os(iOS) - private var accentColor: some View { - SectionView("Accent color") { - ColorSelector(selection: theme.$accentColor) + #if os(iOS) + private var accentColor: some View { + SectionView("Accent color") { + ColorSelector(selection: theme.$accentColor) + } } - } - #endif - - #if os(iOS) - private var appIcon: some View { - SectionView("App icon") { - LazyVGrid(columns: columns, spacing: 24) { - ForEach(0 ..< iconSettings.iconNames.count) { index in - HStack { - Image(uiImage: UIImage(named: iconSettings.iconNames[index] - ?? "DefaultAppIcon") ?? UIImage()) - .renderingMode(.original) - .resizable() - .scaledToFit() - .frame(width: 78, height: 78) - .cornerRadius(18) - .overlay( - RoundedRectangle(cornerRadius: 20) - .stroke(Color.accent, - lineWidth: index == iconSettings.currentIndex ? 3 : 0) - ) - .onTapGesture { - let defaultIconIndex = self.iconSettings.iconNames - .firstIndex(of: UIApplication.shared.alternateIconName) ?? 0 - if defaultIconIndex != index { - // swiftlint:disable line_length - UIApplication.shared.setAlternateIconName(self.iconSettings.iconNames[index]) { error in - if let error = error { - print(error.localizedDescription) - } else { - print("Success! You have changed the app icon.") + #endif + + #if os(iOS) + private var appIcon: some View { + SectionView("App icon") { + LazyVGrid(columns: columns, spacing: 24) { + ForEach(0 ..< iconSettings.iconNames.count) { index in + HStack { + Image(uiImage: UIImage(named: iconSettings.iconNames[index] + ?? "DefaultAppIcon") ?? UIImage()) + .renderingMode(.original) + .resizable() + .scaledToFit() + .frame(width: 78, height: 78) + .cornerRadius(18) + .overlay( + RoundedRectangle(cornerRadius: 20) + .stroke(Color.accent, + lineWidth: index == iconSettings.currentIndex ? 3 : 0) + ) + .onTapGesture { + let defaultIconIndex = self.iconSettings.iconNames + .firstIndex(of: UIApplication.shared.alternateIconName) ?? 0 + if defaultIconIndex != index { + // swiftlint:disable line_length + UIApplication.shared.setAlternateIconName(self.iconSettings.iconNames[index]) { error in + if let error = error { + print(error.localizedDescription) + } else { + print("Success! You have changed the app icon.") + } } } } - } + } + .padding(3) } - .padding(3) } + .padding() } - .padding() } - } - #endif - - private var advanded: some View { - SectionView("Advanced settings") { - ZStack { - NavigationLink(destination: FontSettingView(), - tag: .font, - selection: $pageDestenation) { EmptyView() } - - NavigationLink(destination: BorderSettingView(), - tag: .border, - selection: $pageDestenation) { EmptyView() } - - NavigationLink(destination: RadiusSettingView(), - tag: .radius, - selection: $pageDestenation) { EmptyView() } - - VStack(spacing: .zero) { - Row("Fonts", leadingType: .icon(.type), trallingType: .arrowIcon) { - pageDestenation = .font - } - .premium() + #endif - Row("Borders", leadingType: .icon(.layout), trallingType: .toggleWithArrowButton(isOn: theme.$borderApp, action: { - pageDestenation = .border - })) { - pageDestenation = .border - } - .premium() - .onChange(of: theme.borderApp) { value in - theme.borderSurface = value - theme.borderButtons = value - theme.borderControls = value - theme.borderTextFields = value - } + private var advanded: some View { + SectionView("Advanced settings") { + ZStack { + NavigationLink(destination: FontSettingView(), + tag: .font, + selection: $pageDestenation) { EmptyView() } + + NavigationLink(destination: BorderSettingView(), + tag: .border, + selection: $pageDestenation) { EmptyView() } + + NavigationLink(destination: RadiusSettingView(), + tag: .radius, + selection: $pageDestenation) { EmptyView() } - Row("Radius", leadingType: .icon(.circle), trallingType: .arrowIcon) { - pageDestenation = .radius + VStack(spacing: .zero) { + Row("Fonts", leadingType: .icon(.type), trallingType: .arrowIcon) { + pageDestenation = .font + } + .premium() + + Row("Borders", leadingType: .icon(.layout), trallingType: .toggleWithArrowButton(isOn: theme.$borderApp, action: { + pageDestenation = .border + })) { + pageDestenation = .border + } + .premium() + .onChange(of: theme.borderApp) { value in + theme.borderSurface = value + theme.borderButtons = value + theme.borderControls = value + theme.borderTextFields = value + } + + Row("Radius", leadingType: .icon(.circle), trallingType: .arrowIcon) { + pageDestenation = .radius + } + .premium() } - .premium() } } } } -} -struct SettingsThemeView_Previews: PreviewProvider { - static var previews: some View { - AppearanceSettingView() - .previewPhones() + struct SettingsThemeView_Previews: PreviewProvider { + static var previews: some View { + AppearanceSettingView() + .previewPhones() + } } -} +#endif diff --git a/Sources/OversizeUI/Modules/PINCode/PINCodeView.swift b/Sources/OversizeUI/Modules/PINCode/PINCodeView.swift index 7de462e..447b35f 100644 --- a/Sources/OversizeUI/Modules/PINCode/PINCodeView.swift +++ b/Sources/OversizeUI/Modules/PINCode/PINCodeView.swift @@ -89,10 +89,12 @@ public struct PINCodeView: View { Spacer() - biometricImage() - .onTapGesture { - biometricAction?() - } + #if os(iOS) + biometricImage() + .onTapGesture { + biometricAction?() + } + #endif Spacer() }