From 0570d7637ce32050bfca79039e87936849da3c06 Mon Sep 17 00:00:00 2001 From: Muukii Date: Wed, 21 Feb 2024 22:28:20 +0900 Subject: [PATCH] WIP --- Dev/Brightroom.xcodeproj/project.pbxproj | 7 + .../xcshareddata/swiftpm/Package.resolved | 9 + Dev/Sources/SwiftUIDemo/DemoCropView.swift | 354 +---------------- Package.resolved | 18 + Package.swift | 12 +- .../PhotosCrop/SwiftUIPhotosCropView.swift | 4 + .../Shared/Components/Crop/CropView.swift | 4 +- .../PhotosCropRotating.swift | 369 ++++++++++++++++++ 8 files changed, 418 insertions(+), 359 deletions(-) create mode 100644 Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift diff --git a/Dev/Brightroom.xcodeproj/project.pbxproj b/Dev/Brightroom.xcodeproj/project.pbxproj index 1ab16285..5599cfc5 100644 --- a/Dev/Brightroom.xcodeproj/project.pbxproj +++ b/Dev/Brightroom.xcodeproj/project.pbxproj @@ -73,6 +73,7 @@ 4B98CCC325EFF31400E4F61F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B98CCC225EFF31400E4F61F /* Preview Assets.xcassets */; }; 4B98CCE725EFF4EF00E4F61F /* Mocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B98CCE625EFF4EF00E4F61F /* Mocks.swift */; }; 4B98CF5325F0122000E4F61F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B600B29216B7C9E001E1456 /* Assets.xcassets */; }; + 4BA2B1B42B86282D00E6DE64 /* BrightroomUIPhotosCrop in Frameworks */ = {isa = PBXBuildFile; productRef = 4BA2B1B32B86282D00E6DE64 /* BrightroomUIPhotosCrop */; }; 4BA41C82260CE817005E6FA7 /* orientation_up_mirrored.HEIC in Resources */ = {isa = PBXBuildFile; fileRef = 4B254FEB260BB32600F77E9A /* orientation_up_mirrored.HEIC */; }; 4BA41C83260CE817005E6FA7 /* orientation_right_mirrored.HEIC in Resources */ = {isa = PBXBuildFile; fileRef = 4B254FE7260BB32600F77E9A /* orientation_right_mirrored.HEIC */; }; 4BA41C84260CE817005E6FA7 /* orientation_left_mirrored.HEIC in Resources */ = {isa = PBXBuildFile; fileRef = 4B254FE6260BB32600F77E9A /* orientation_left_mirrored.HEIC */; }; @@ -1062,6 +1063,7 @@ 4B7513CB2B6BEE2100A4743E /* SwiftUISupport in Frameworks */, FC06C87F2A53AF4500215B89 /* BrightroomEngine in Frameworks */, 4B7513C82B6BEDFD00A4743E /* SwiftUIHosting in Frameworks */, + 4BA2B1B42B86282D00E6DE64 /* BrightroomUIPhotosCrop in Frameworks */, 4B5E72BC2B6B761800DE7A2A /* Reveal-SDK in Frameworks */, FC06C8812A53AF4500215B89 /* BrightroomUI in Frameworks */, ); @@ -1784,6 +1786,7 @@ 4B7513C72B6BEDFD00A4743E /* SwiftUIHosting */, 4B7513CA2B6BEE2100A4743E /* SwiftUISupport */, 4B46E71A2B762E20003179C2 /* MondrianLayout */, + 4BA2B1B32B86282D00E6DE64 /* BrightroomUIPhotosCrop */, ); productName = SwiftUIDemo; productReference = 4B98CCB925EFF31300E4F61F /* SwiftUIDemo.app */; @@ -3006,6 +3009,10 @@ package = 4B7513C92B6BEE2100A4743E /* XCRemoteSwiftPackageReference "swiftui-support" */; productName = SwiftUISupport; }; + 4BA2B1B32B86282D00E6DE64 /* BrightroomUIPhotosCrop */ = { + isa = XCSwiftPackageProductDependency; + productName = BrightroomUIPhotosCrop; + }; FC06C87E2A53AF4500215B89 /* BrightroomEngine */ = { isa = XCSwiftPackageProductDependency; productName = BrightroomEngine; diff --git a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 04e14419..49b2755e 100644 --- a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -36,6 +36,15 @@ "version" : "0.10.0" } }, + { + "identity" : "precisionlevelslider", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/PrecisionLevelSlider", + "state" : { + "revision" : "cd02d02e8add9886586d12450caba952fcdde910", + "version" : "2.0.0" + } + }, { "identity" : "rxswift", "kind" : "remoteSourceControl", diff --git a/Dev/Sources/SwiftUIDemo/DemoCropView.swift b/Dev/Sources/SwiftUIDemo/DemoCropView.swift index 831a8c3f..7c50e891 100644 --- a/Dev/Sources/SwiftUIDemo/DemoCropView.swift +++ b/Dev/Sources/SwiftUIDemo/DemoCropView.swift @@ -8,21 +8,15 @@ import BrightroomEngine import BrightroomUI +import BrightroomUIPhotosCrop import SwiftUI import UIKit struct DemoCropView: View { @StateObject var editingStack: EditingStack - - @State var rotation: EditingCrop.Rotation? - @State var adjustmentAngle: EditingCrop.AdjustmentAngle? - @State var croppingAspectRatio: PixelAspectRatio? - @State var resultImage: ResultImage? - @State var canReset: Bool = false - @State var isFocusingAspectRatio: Bool = false init( editingStack: @escaping () -> EditingStack @@ -32,128 +26,7 @@ struct DemoCropView: View { var body: some View { VStack { - ZStack { - Color.black - .ignoresSafeArea() - - VStack { - - HStack { - Button( - action: { - - if self.rotation == nil { - self.rotation = .angle_0 - self.rotation = self.rotation!.next() - } else { - self.rotation = self.rotation!.next() - } - - }, - label: { - Image(systemName: "rotate.left") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 22) - .foregroundStyle(.secondary) - } - ) - - Spacer() - - if editingStack.state.loadedState?.hasUncommitedChanges ?? false { - Button { - rotation = nil - adjustmentAngle = nil - croppingAspectRatio = nil - - // switch croppingAspectRatio { - // case .fixed(let ratio): - // cropView.setCroppingAspectRatio(ratio) - // case .selectable: - // cropView.setCroppingAspectRatio(nil) - // } - // cropView.resetCrop() - - } label: { - Text("RESET") - .font(.subheadline) - } - .tint(.yellow) - } - - Spacer() - - Button( - action: { - isFocusingAspectRatio.toggle() - }, - label: { - Image(systemName: isFocusingAspectRatio ? "aspectratio.fill" : "aspectratio") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 22) - .foregroundStyle(isFocusingAspectRatio ? .primary : .secondary) - } - ) - } - .tint(.white) - .padding() - .zIndex(1) - - SwiftUICropView( - editingStack: editingStack - ) - .rotation(rotation) - .adjustmentAngle(adjustmentAngle) - .croppingAspectRatio(croppingAspectRatio) - .zIndex(0) - - if isFocusingAspectRatio { - aspectRatioView - } - - VStack { - - HStack { - Button("16:9") { - self.croppingAspectRatio = .init(width: 16, height: 9) - } - - Button("Freeform") { - self.croppingAspectRatio = nil - } - } - HStack { - Button("0") { - self.rotation = .angle_0 - } - Button("90") { - self.rotation = .angle_90 - } - Button("180") { - self.rotation = .angle_180 - } - Button("270") { - self.rotation = .angle_270 - } - Button("- 10") { - if self.adjustmentAngle == nil { - self.adjustmentAngle = .zero - } - self.adjustmentAngle! -= .degrees(10) - } - Button("+ 10") { - if self.adjustmentAngle == nil { - self.adjustmentAngle = .zero - } - self.adjustmentAngle! += .degrees(10) - } - } - } - .zIndex(1) - } - } + PhotosCropRotating(editingStack: { editingStack }) Button("Done") { let image = try! editingStack.makeRenderer().render().cgImage self.resultImage = .init(cgImage: image) @@ -167,229 +40,6 @@ struct DemoCropView: View { } } - private var aspectRatioView: some View { - VStack { - HStack(spacing: 18) { - - // vertical - Button { - - } label: { - ZStack { - RoundedRectangle(cornerRadius: 2) - .stroke(style: .init(lineWidth: 5)) - .fill(Color(white: 0.5, opacity: 1)) - - RoundedRectangle(cornerRadius: 2) - .fill(Color(white: 0.3, opacity: 1)) - - Image(systemName: "checkmark") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 12) - .foregroundStyle(Color.black) - } - .tint(.white) - .frame(width: 18, height: 28) - } - - // horizontal - Button { - - } label: { - ZStack { - RoundedRectangle(cornerRadius: 2) - .stroke(style: .init(lineWidth: 5)) - .fill(Color(white: 0.5, opacity: 1)) - - RoundedRectangle(cornerRadius: 2) - .fill(Color(white: 0.3, opacity: 1)) - - Image(systemName: "checkmark") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 12) - .foregroundStyle(Color.black) - } - .tint(.white) - .frame(width: 28, height: 18) - } - } - - ScrollView(.horizontal, showsIndicators: false) { - HStack { - - Group { - - AspectRationButton( - title: Text("ORIGINAL"), - isSelected: true - ) { - - } - - AspectRationButton( - title: Text("FREEFORM"), - isSelected: true - ) { - - } - - AspectRationButton( - title: Text("SQUARE"), - isSelected: true - ) { - - } - - ForEach(Self.horizontalRectangleApectRatios) { ratio in - AspectRationButton( - title: Text("\(Int(ratio.width)):\(Int(ratio.height))"), - isSelected: false - ) { - - } - } - } - .tint(.white) - - } - - } - } - } - - private static let horizontalRectangleApectRatios: [PixelAspectRatio] = [ - .init(width: 16, height: 9), - .init(width: 10, height: 8), - .init(width: 7, height: 5), - .init(width: 4, height: 3), - .init(width: 5, height: 3), - .init(width: 3, height: 2), - ] -} - -struct AspectRationButton: View { - - let title: Text - let isSelected: Bool - let onTap: @MainActor () -> Void - - var body: some View { - Button( - action: { - onTap() - }, - label: { - title - .font(.caption) - .foregroundStyle(.primary) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background( - Capsule() - .foregroundStyle(.tertiary) - .opacity(isSelected ? 1 : 0) - ) - .foregroundStyle(.tint) - } - ) - } -} - -struct AspectRationButtonStyle: PrimitiveButtonStyle { - - let isSeleted: Bool - - func makeBody(configuration: Configuration) -> some View { - configuration - .label - .foregroundStyle(.primary) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background( - Capsule() - .foregroundStyle(.tertiary) - .opacity(isSeleted ? 1 : 0) - ) - .foregroundStyle(.tint) - - } - -} - -struct Slider: View { - - enum SliderPreferenceKey: PreferenceKey { - - static var defaultValue: CGRect = .zero - - static func reduce(value: inout CGRect, nextValue: () -> CGRect) { - // nextValue() - } - - typealias Value = CGRect - - } - - @State var value: Int = 0 - - var body: some View { - - VStack { - Circle() - .frame(width: 2, height: 2) - GeometryReader(content: { geometry in - ScrollViewReader { proxy in - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 4) { - ForEach(0..<25) { index in - RoundedRectangle(cornerRadius: 2) - .fill(Color(white: 0.5, opacity: 1)) - .frame(width: 2, height: 20) - } - RoundedRectangle(cornerRadius: 2) - .frame(width: 2, height: 20) - .id(0) - ForEach(0..<25) { index in - RoundedRectangle(cornerRadius: 2) - .fill(Color(white: 0.5, opacity: 1)) - .frame(width: 2, height: 20) - } - } - .background( - GeometryReader { geometry in - Color.clear.preference( - key: SliderPreferenceKey.self, - value: geometry.frame(in: .named("ScrollView")) - ) - } - ) - .padding(.horizontal, geometry.size.width / 2) - .onPreferenceChange( - SliderPreferenceKey.self, - perform: { value in - print(value) - } - ) - - } - .coordinateSpace(name: "ScrollView") - .onAppear(perform: { - proxy.scrollTo(0, anchor: .center) - }) - - } - // .background(Color.red) - }) - } - - } - -} - -#Preview("Slider") { - Slider() } #Preview { diff --git a/Package.resolved b/Package.resolved index 6bf1d600..809be54d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,14 @@ { "pins" : [ + { + "identity" : "precisionlevelslider", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/PrecisionLevelSlider", + "state" : { + "revision" : "cd02d02e8add9886586d12450caba952fcdde910", + "version" : "2.0.0" + } + }, { "identity" : "rxswift", "kind" : "remoteSourceControl", @@ -45,6 +54,15 @@ "version" : "509.0.1" } }, + { + "identity" : "swiftui-hosting", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/swiftui-Hosting", + "state" : { + "revision" : "7e8eaca72eae910d6d3b6272c263c6c3a10b755c", + "version" : "1.2.0" + } + }, { "identity" : "transitionpatch", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 484c2874..f5a9ee12 100644 --- a/Package.swift +++ b/Package.swift @@ -1,10 +1,10 @@ -// swift-tools-version:5.7 +// swift-tools-version:5.9 import PackageDescription let package = Package( name: "Brightroom", platforms: [ - .iOS(.v13) + .iOS(.v15) ], products: [ .library(name: "BrightroomEngine", targets: ["BrightroomUI"]), @@ -13,7 +13,8 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/VergeGroup/Verge.git", from: "12.0.0-beta.2"), - .package(url: "https://github.com/FluidGroup/TransitionPatch.git", from: "1.0.3") + .package(url: "https://github.com/FluidGroup/TransitionPatch.git", from: "1.0.3"), + .package(url: "https://github.com/FluidGroup/PrecisionLevelSlider", from: "2.0.0"), ], targets: [ .target( @@ -26,8 +27,7 @@ let package = Package( ), .target( name: "BrightroomUIPhotosCrop", - dependencies: ["BrightroomUI"] + dependencies: ["BrightroomUI", "PrecisionLevelSlider"] ) - ], - swiftLanguageVersions: [.v5] + ] ) diff --git a/Sources/BrightroomUI/Built-in UI/PhotosCrop/SwiftUIPhotosCropView.swift b/Sources/BrightroomUI/Built-in UI/PhotosCrop/SwiftUIPhotosCropView.swift index 1296a4e8..41b65fc2 100644 --- a/Sources/BrightroomUI/Built-in UI/PhotosCrop/SwiftUIPhotosCropView.swift +++ b/Sources/BrightroomUI/Built-in UI/PhotosCrop/SwiftUIPhotosCropView.swift @@ -58,3 +58,7 @@ public struct SwiftUIPhotosCropView: UIViewControllerRepresentable { public func updateUIViewController(_ uiViewController: PhotosCropViewController, context: Context) {} } + +#Preview { + Text("h") +} diff --git a/Sources/BrightroomUI/Shared/Components/Crop/CropView.swift b/Sources/BrightroomUI/Shared/Components/Crop/CropView.swift index 8f5adf85..26b8c536 100644 --- a/Sources/BrightroomUI/Shared/Components/Crop/CropView.swift +++ b/Sources/BrightroomUI/Shared/Components/Crop/CropView.swift @@ -904,7 +904,9 @@ extension CropView { private func record() { store.commit { state in - let crop = state.proposedCrop! + guard let crop = state.proposedCrop else { + return + } // remove rotation while converting rect let current = scrollView.transform diff --git a/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift b/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift new file mode 100644 index 00000000..c6caec51 --- /dev/null +++ b/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift @@ -0,0 +1,369 @@ +// +// DemoCropView.swift +// SwiftUIDemo +// +// Created by Muukii on 2021/03/05. +// Copyright © 2021 muukii. All rights reserved. +// + +import BrightroomEngine +import BrightroomUI +import PrecisionLevelSlider +import SwiftUI +import UIKit + +public struct PhotosCropRotating: View { + + @StateObject var editingStack: EditingStack + + @State var rotation: EditingCrop.Rotation? + @State var adjustmentAngle: EditingCrop.AdjustmentAngle? + @State var croppingAspectRatio: PixelAspectRatio? + + @State var canReset: Bool = false + @State var isFocusingAspectRatio: Bool = false + + public init( + editingStack: @escaping () -> EditingStack + ) { + self._editingStack = .init(wrappedValue: editingStack()) + } + + public var body: some View { + VStack { + ZStack { + Color.black + .ignoresSafeArea() + + VStack { + + HStack { + Button( + action: { + + if self.rotation == nil { + self.rotation = .angle_0 + self.rotation = self.rotation!.next() + } else { + self.rotation = self.rotation!.next() + } + + }, + label: { + Image(systemName: "rotate.left") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 22) + .foregroundStyle(.secondary) + } + ) + + Spacer() + + if editingStack.state.loadedState?.hasUncommitedChanges ?? false { + Button { + rotation = nil + adjustmentAngle = nil + croppingAspectRatio = nil + + // switch croppingAspectRatio { + // case .fixed(let ratio): + // cropView.setCroppingAspectRatio(ratio) + // case .selectable: + // cropView.setCroppingAspectRatio(nil) + // } + // cropView.resetCrop() + + } label: { + Text("RESET") + .font(.subheadline) + } + .tint(.yellow) + } + + Spacer() + + Button( + action: { + isFocusingAspectRatio.toggle() + }, + label: { + Image(systemName: isFocusingAspectRatio ? "aspectratio.fill" : "aspectratio") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 22) + .foregroundStyle(isFocusingAspectRatio ? .primary : .secondary) + } + ) + } + .tint(.white) + .padding() + .zIndex(1) + + SwiftUICropView( + editingStack: editingStack + ) + .rotation(rotation) + .adjustmentAngle(adjustmentAngle) + .croppingAspectRatio(croppingAspectRatio) + .zIndex(0) + + Group { + if isFocusingAspectRatio { + aspectRatioView + } else { + rotationAdjustmentView + } + } + .zIndex(1) + } + } + } + .onAppear { + editingStack.start() + } + + } + + private var rotationAdjustmentView: some View { + SwiftUIPrecisionLevelSlider( + value: .init( + get: { (adjustmentAngle?.degrees ?? 0) }, + set: { value in + adjustmentAngle = .init(degrees: value) + } + ), + haptics: .init(trigger: { value in + if value.truncatingRemainder(dividingBy: 5) == 0 { + return .impact(style: .light, intensity: 0.4) + } else { + return nil + } + }), + range: .init( + range: -45...45, + transform: { source in + source.rounded(.toNearestOrEven) + } + ), + centerLevel: { value in + HStack { + Spacer() + VStack { + Spacer(minLength: 12) + Rectangle() + .frame(width: 1) + Spacer(minLength: 12) + } + Spacer() + } + .foregroundStyle(.tint) + }, + track: { value in + VStack { + HStack { + Spacer() + Circle() + .frame(width: 6, height: 6) + .opacity(value == 0 ? 0 : 1) + .animation(.spring, value: value == 0) + Spacer() + } + HStack(spacing: 0) { + ForEach(0..<4) { i in + ShortBar() + .foregroundStyle(.primary) + Group { + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + ShortBar() + Spacer(minLength: 0) + } + .foregroundStyle(.secondary) + } + ShortBar() + .foregroundStyle(.primary) + } + } + .foregroundStyle(.tint) + } + ) + .tint(.white) + .frame(height: 50) + } + + private var aspectRatioView: some View { + VStack(spacing: 20) { + HStack(spacing: 18) { + + // vertical + Button { + + } label: { + ZStack { + RoundedRectangle(cornerRadius: 2) + .stroke(style: .init(lineWidth: 5)) + .fill(Color(white: 0.5, opacity: 1)) + + RoundedRectangle(cornerRadius: 2) + .fill(Color(white: 0.3, opacity: 1)) + + Image(systemName: "checkmark") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 12) + .foregroundStyle(Color.black) + } + .tint(.white) + .frame(width: 18, height: 28) + } + + // horizontal + Button { + + } label: { + ZStack { + RoundedRectangle(cornerRadius: 2) + .stroke(style: .init(lineWidth: 5)) + .fill(Color(white: 0.5, opacity: 1)) + + RoundedRectangle(cornerRadius: 2) + .fill(Color(white: 0.3, opacity: 1)) + + Image(systemName: "checkmark") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 12) + .foregroundStyle(Color.black) + } + .tint(.white) + .frame(width: 28, height: 18) + } + } + + ScrollView(.horizontal, showsIndicators: false) { + HStack { + + Group { + + AspectRationButton( + title: Text("ORIGINAL"), + isSelected: croppingAspectRatio?.asCGSize() + == editingStack.state.loadedState?.imageSize + ) { + guard let imageSize = editingStack.state.loadedState?.imageSize else { + return + } + croppingAspectRatio = .init(imageSize) + } + + AspectRationButton( + title: Text("FREEFORM"), + isSelected: croppingAspectRatio == nil + ) { + croppingAspectRatio = nil + } + + AspectRationButton( + title: Text("SQUARE"), + isSelected: croppingAspectRatio == .square + ) { + croppingAspectRatio = .square + } + + ForEach(Self.horizontalRectangleApectRatios) { ratio in + AspectRationButton( + title: Text("\(Int(ratio.width)):\(Int(ratio.height))"), + isSelected: croppingAspectRatio == ratio + ) { + croppingAspectRatio = ratio + } + } + } + .tint(.white) + + } + .padding(.horizontal, 20) + } + } + } + + private static let horizontalRectangleApectRatios: [PixelAspectRatio] = [ + .init(width: 16, height: 9), + .init(width: 10, height: 8), + .init(width: 7, height: 5), + .init(width: 4, height: 3), + .init(width: 5, height: 3), + .init(width: 3, height: 2), + ] +} + +struct AspectRationButton: View { + + let title: Text + let isSelected: Bool + let onTap: @MainActor () -> Void + + var body: some View { + Button( + action: { + onTap() + }, + label: { + title + .font(.caption) + .foregroundStyle(.primary) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background( + Capsule() + .foregroundStyle(.tertiary) + .opacity(isSelected ? 1 : 0) + ) + .foregroundStyle(.tint) + } + ) + } +} + +struct AspectRationButtonStyle: PrimitiveButtonStyle { + + let isSeleted: Bool + + func makeBody(configuration: Configuration) -> some View { + configuration + .label + .foregroundStyle(.primary) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background( + Capsule() + .foregroundStyle(.tertiary) + .opacity(isSeleted ? 1 : 0) + ) + .foregroundStyle(.tint) + + } + +} +struct ShortBar: View { + var body: some View { + RoundedRectangle(cornerRadius: 8) + .frame(width: 1, height: 10) + } +}