From afe5d43d6f1641d390b291b65fcab5d0a4cc071d Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Sun, 18 Aug 2024 14:25:43 +0300 Subject: [PATCH] Swift format --- playground/ContentView.swift | 12 +- playground/Samples.swift | 206 +++++------ playground/SamplesList.swift | 98 +++--- playground/playgroundApp.swift | 2 - .../Buttons/ButtonBorderShapeSample.swift | 72 ++-- .../CompsitingGroupSample.swift | 38 +- .../samples/Gesture/RotateGestureSample.swift | 36 +- .../samples/GroupBox/GroupBoxSample.swift | 42 ++- .../samples/Images/AsyncImageSample.swift | 30 +- .../samples/Images/VariableValueSample.swift | 64 ++-- .../ContainerRelativeFrameSample.swift | 20 +- .../samples/Lists/DisclosureGroupSample.swift | 76 ++-- .../Lists/ListSectionSpacingSample.swift | 104 +++--- playground/samples/Map/MapStyleSample.swift | 24 +- playground/samples/MaskingSample.swift | 24 +- .../samples/Navigation/TabViewSample.swift | 40 +-- .../Navigation/TabViewStyleSample.swift | 40 +-- playground/samples/Slider/SliderSample.swift | 28 +- playground/samples/Tables/TableSample.swift | 108 +++--- .../Text/RelativeDateStyleSample.swift | 2 +- .../samples/Text/TextRendererSample.swift | 217 ++++++------ .../ThirdParty/JunoUISliderSample.swift | 331 +++++++++--------- .../samples/ViewGroupings/FormSample.swift | 70 ++-- playgroundTests/playgroundTests.swift | 6 +- playgroundTests/sliderTests.swift | 14 +- playgroundUITests/playgroundUITests.swift | 1 - .../playgroundUITestsLaunchTests.swift | 1 - 27 files changed, 846 insertions(+), 860 deletions(-) diff --git a/playground/ContentView.swift b/playground/ContentView.swift index d2c1d8f..65fbd90 100644 --- a/playground/ContentView.swift +++ b/playground/ContentView.swift @@ -7,14 +7,14 @@ import SwiftUI -struct ContentView: View { - var body: some View { - NavigationStack { - SamplesList(title: "Swift Playground", samples: samples) +struct ContentView: View { + var body: some View { + NavigationStack { + SamplesList(title: "Swift Playground", samples: samples) + } } - } } #Preview { - ContentView() + ContentView() } diff --git a/playground/Samples.swift b/playground/Samples.swift index 520f38c..3ee0f07 100644 --- a/playground/Samples.swift +++ b/playground/Samples.swift @@ -8,107 +8,107 @@ import SwiftUI public let samples: [String: AnyView] = [ - "Buttons": AnyView(SamplesList( - title: "Buttons", samples: - [ - // https://developer.apple.com/documentation/swiftui/button - "Button Border Shape": AnyView(ButtonBorderShapeSample()), - ] - )), - "Map": AnyView(SamplesList( - title: "Map", samples: - [ - // https://developer.apple.com/documentation/mapkit/map - "MapStyle": AnyView(MapStyleSample()), - ] - )), - "Gesture": AnyView(SamplesList( - title: "Gesture", samples: - [ - // https://developer.apple.com/documentation/swiftui/rotategesture - "Rotate Gesture": AnyView(RotateGestureSample()), - ] - )), - "Third party": AnyView(SamplesList( - title: "Third party", samples: - [ - // https://github.com/christianselig/JunoSlider - "JunoUI Slider": AnyView(JunoUISliderSample()), - ] - )), - "Layout Adjustments": AnyView(SamplesList( - title: "Layout Adjustments", samples: - [ - // https://developer.apple.com/documentation/swiftui/view/containerrelativeframe(_:alignment:) - "Container Relative Frame": AnyView(ContainerRelativeFrameSample()), - ] - )), - "Drawing and Graphics": AnyView(SamplesList( - title: "Drawing and Graphics", samples: - [ - // https://developer.apple.com/documentation/swiftui/view/compositinggroup() - "Compsiting Group": AnyView(CompsitingGroupSample()), - // https://developer.apple.com/documentation/swiftui/view/mask(alignment:_:) - "Masking": AnyView(MaskingSample()), - ] - )), - "Tables": AnyView(SamplesList( - title: "Tables", samples: - [ - // https://developer.apple.com/documentation/swiftui/table - "Table": AnyView(TableSample()), - ] - )), - "Text": AnyView(SamplesList( - title: "Text", samples: - [ - // https://developer.apple.com/documentation/swiftui/textrenderer - "Text Renderer": AnyView(TextRendererSample()), - // https://developer.apple.com/documentation/swiftui/text/datestyle - "Relative DateStyle": AnyView(RelativeDateStyleSample()), - ] - )), - "Navigation": AnyView(SamplesList( - title: "Navigation", samples: - [ - // https://developer.apple.com/documentation/swiftui/tabview - "Tab View": AnyView(TabViewSample()), - // https://developer.apple.com/documentation/swiftui/tabviewstyle - "Tab View Style": AnyView(TabViewStyleSample()), - ] - )), - "Images": AnyView(SamplesList( - title: "Images", samples: - [ - // https://developer.apple.com/documentation/swiftui/asyncimage - "Async Image": AnyView(AsyncImageSample()), - // https://developer.apple.com/documentation/swiftui/image/init(_:variablevalue:bundle:) - "Variable Value": AnyView(VariableValueSample()), - ] - )), - "View Groupings": AnyView(SamplesList( - title: "View Groupings", samples: - [ - // https://developer.apple.com/documentation/swiftui/form - "Form": AnyView(FormSample()), - // https://developer.apple.com/documentation/swiftui/groupbox - "GroupBox": AnyView(GroupBoxSample()), - ] - )), - "Lists": AnyView(SamplesList( - title: "Lists", samples: - [ - // https://developer.apple.com/documentation/swiftui/disclosuregroup - "Disclosure Group": AnyView(DisclosureGroupSample()), - // https://developer.apple.com/documentation/swiftui/listsectionspacing - "List Section Spacing": AnyView(ListSectionSpacingSample()), - ] - )), - "Slider": AnyView(SamplesList( - title: "Slider", samples: - [ - // https://developer.apple.com/documentation/swiftui/slider - "Slider": AnyView(SliderSample()), - ] - )), + "Buttons": AnyView(SamplesList( + title: "Buttons", samples: + [ + // https://developer.apple.com/documentation/swiftui/button + "Button Border Shape": AnyView(ButtonBorderShapeSample()), + ] + )), + "Map": AnyView(SamplesList( + title: "Map", samples: + [ + // https://developer.apple.com/documentation/mapkit/map + "MapStyle": AnyView(MapStyleSample()), + ] + )), + "Gesture": AnyView(SamplesList( + title: "Gesture", samples: + [ + // https://developer.apple.com/documentation/swiftui/rotategesture + "Rotate Gesture": AnyView(RotateGestureSample()), + ] + )), + "Third party": AnyView(SamplesList( + title: "Third party", samples: + [ + // https://github.com/christianselig/JunoSlider + "JunoUI Slider": AnyView(JunoUISliderSample()), + ] + )), + "Layout Adjustments": AnyView(SamplesList( + title: "Layout Adjustments", samples: + [ + // https://developer.apple.com/documentation/swiftui/view/containerrelativeframe(_:alignment:) + "Container Relative Frame": AnyView(ContainerRelativeFrameSample()), + ] + )), + "Drawing and Graphics": AnyView(SamplesList( + title: "Drawing and Graphics", samples: + [ + // https://developer.apple.com/documentation/swiftui/view/compositinggroup() + "Compsiting Group": AnyView(CompsitingGroupSample()), + // https://developer.apple.com/documentation/swiftui/view/mask(alignment:_:) + "Masking": AnyView(MaskingSample()), + ] + )), + "Tables": AnyView(SamplesList( + title: "Tables", samples: + [ + // https://developer.apple.com/documentation/swiftui/table + "Table": AnyView(TableSample()), + ] + )), + "Text": AnyView(SamplesList( + title: "Text", samples: + [ + // https://developer.apple.com/documentation/swiftui/textrenderer + "Text Renderer": AnyView(TextRendererSample()), + // https://developer.apple.com/documentation/swiftui/text/datestyle + "Relative DateStyle": AnyView(RelativeDateStyleSample()), + ] + )), + "Navigation": AnyView(SamplesList( + title: "Navigation", samples: + [ + // https://developer.apple.com/documentation/swiftui/tabview + "Tab View": AnyView(TabViewSample()), + // https://developer.apple.com/documentation/swiftui/tabviewstyle + "Tab View Style": AnyView(TabViewStyleSample()), + ] + )), + "Images": AnyView(SamplesList( + title: "Images", samples: + [ + // https://developer.apple.com/documentation/swiftui/asyncimage + "Async Image": AnyView(AsyncImageSample()), + // https://developer.apple.com/documentation/swiftui/image/init(_:variablevalue:bundle:) + "Variable Value": AnyView(VariableValueSample()), + ] + )), + "View Groupings": AnyView(SamplesList( + title: "View Groupings", samples: + [ + // https://developer.apple.com/documentation/swiftui/form + "Form": AnyView(FormSample()), + // https://developer.apple.com/documentation/swiftui/groupbox + "GroupBox": AnyView(GroupBoxSample()), + ] + )), + "Lists": AnyView(SamplesList( + title: "Lists", samples: + [ + // https://developer.apple.com/documentation/swiftui/disclosuregroup + "Disclosure Group": AnyView(DisclosureGroupSample()), + // https://developer.apple.com/documentation/swiftui/listsectionspacing + "List Section Spacing": AnyView(ListSectionSpacingSample()), + ] + )), + "Slider": AnyView(SamplesList( + title: "Slider", samples: + [ + // https://developer.apple.com/documentation/swiftui/slider + "Slider": AnyView(SliderSample()), + ] + )), ] diff --git a/playground/SamplesList.swift b/playground/SamplesList.swift index 93bf6dc..9e1477a 100644 --- a/playground/SamplesList.swift +++ b/playground/SamplesList.swift @@ -8,60 +8,60 @@ import SwiftUI struct SamplesList: View { - let title: String - let samples: [String: AnyView] - - init(title: String, samples: [String: AnyView]) { - self.title = title - self.samples = samples - } + let title: String + let samples: [String: AnyView] - let columns = [ - GridItem(.flexible(), spacing: 16), - GridItem(.flexible(), spacing: 16) - ] - - var body: some View { - ScrollView { - LazyVGrid(columns: columns, spacing: 16) { - ForEach( - Array(samples.keys.sorted()), - id: \.self - ) { sampleKey in - NavigationLink(destination: samples[sampleKey]) { - VStack { - Text(sampleKey) - .font(.headline) - .multilineTextAlignment(.center) - .foregroundColor(.primary) - .padding(.horizontal) - .padding(.vertical, 10) - .frame(height: 100) - .frame(maxWidth: .infinity) - .background(Color.blue.opacity(0.1)) - .cornerRadius(10) - .overlay( - RoundedRectangle(cornerRadius: 10) - .stroke(Color.blue, lineWidth: 1) - ) + init(title: String, samples: [String: AnyView]) { + self.title = title + self.samples = samples + } + + let columns = [ + GridItem(.flexible(), spacing: 16), + GridItem(.flexible(), spacing: 16), + ] + + var body: some View { + ScrollView { + LazyVGrid(columns: columns, spacing: 16) { + ForEach( + Array(samples.keys.sorted()), + id: \.self + ) { sampleKey in + NavigationLink(destination: samples[sampleKey]) { + VStack { + Text(sampleKey) + .font(.headline) + .multilineTextAlignment(.center) + .foregroundColor(.primary) + .padding(.horizontal) + .padding(.vertical, 10) + .frame(height: 100) + .frame(maxWidth: .infinity) + .background(Color.blue.opacity(0.1)) + .cornerRadius(10) + .overlay( + RoundedRectangle(cornerRadius: 10) + .stroke(Color.blue, lineWidth: 1) + ) + } + } + .buttonStyle(PlainButtonStyle()) + } } - } - .buttonStyle(PlainButtonStyle()) + .padding() } - } - .padding() + .navigationTitle(title) } - .navigationTitle(title) - } } #Preview { - NavigationView { - SamplesList(title: "Swift Playground", samples: [ - "Sample 1": AnyView(Text("This is Sample 1")), - "Sample 2": AnyView(Text("This is Sample 2")), - "Sample 3": AnyView(Text("This is Sample 3")), - "Sample 4": AnyView(Text("This is Sample 4")) - ]) - } + NavigationView { + SamplesList(title: "Swift Playground", samples: [ + "Sample 1": AnyView(Text("This is Sample 1")), + "Sample 2": AnyView(Text("This is Sample 2")), + "Sample 3": AnyView(Text("This is Sample 3")), + "Sample 4": AnyView(Text("This is Sample 4")), + ]) + } } diff --git a/playground/playgroundApp.swift b/playground/playgroundApp.swift index f8e5fd5..24215ee 100644 --- a/playground/playgroundApp.swift +++ b/playground/playgroundApp.swift @@ -9,11 +9,9 @@ import SwiftUI @main struct playgroundApp: App { - var body: some Scene { WindowGroup { ContentView() } } } - diff --git a/playground/samples/Buttons/ButtonBorderShapeSample.swift b/playground/samples/Buttons/ButtonBorderShapeSample.swift index f109dca..dc9f2ff 100644 --- a/playground/samples/Buttons/ButtonBorderShapeSample.swift +++ b/playground/samples/Buttons/ButtonBorderShapeSample.swift @@ -8,44 +8,44 @@ import SwiftUI struct ButtonBorderShapeSample: View { - var body: some View { - VStack { - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: { - Image(systemName: "macbook.gen2") - }) - .controlSize(.large) - .tint(.red) - .buttonStyle(.bordered) - .buttonBorderShape(.roundedRectangle) - - Button(action: {}, label: { - Image(systemName: "iphone.gen3") - }) - .controlSize(.large) - .tint(.purple) - .buttonStyle(.bordered) - .buttonBorderShape(.roundedRectangle(radius: 8)) - - Button(action: {}, label: { - Image(systemName: "applewatch") - }) - .controlSize(.large) - .tint(.green) - .buttonStyle(.bordered) - .buttonBorderShape(.circle) - - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: { - Image(systemName: "visionpro") - .padding(.all, 2) - }) - .controlSize(.large) - .tint(.blue) - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) + var body: some View { + VStack { + Button(action: /*@START_MENU_TOKEN@*/ {}/*@END_MENU_TOKEN@*/, label: { + Image(systemName: "macbook.gen2") + }) + .controlSize(.large) + .tint(.red) + .buttonStyle(.bordered) + .buttonBorderShape(.roundedRectangle) + + Button(action: {}, label: { + Image(systemName: "iphone.gen3") + }) + .controlSize(.large) + .tint(.purple) + .buttonStyle(.bordered) + .buttonBorderShape(.roundedRectangle(radius: 8)) + + Button(action: {}, label: { + Image(systemName: "applewatch") + }) + .controlSize(.large) + .tint(.green) + .buttonStyle(.bordered) + .buttonBorderShape(.circle) + + Button(action: /*@START_MENU_TOKEN@*/ {}/*@END_MENU_TOKEN@*/, label: { + Image(systemName: "visionpro") + .padding(.all, 2) + }) + .controlSize(.large) + .tint(.blue) + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + } } - } } #Preview { - ButtonBorderShapeSample() + ButtonBorderShapeSample() } diff --git a/playground/samples/DrawingandGraphics/CompsitingGroupSample.swift b/playground/samples/DrawingandGraphics/CompsitingGroupSample.swift index 3ab161d..af5c720 100644 --- a/playground/samples/DrawingandGraphics/CompsitingGroupSample.swift +++ b/playground/samples/DrawingandGraphics/CompsitingGroupSample.swift @@ -8,27 +8,27 @@ import SwiftUI struct CompsitingGroupSample: View { - var body: some View { - VStack { - RoundedRectangle(cornerRadius: 25) - .fill(.red) - .frame(width: 350, height: 124) - .offset(y: 50) - .zIndex(1) - RoundedRectangle(cornerRadius: 25) - .fill(.red) - .frame(width: 125, height: 250) + var body: some View { + VStack { + RoundedRectangle(cornerRadius: 25) + .fill(.red) + .frame(width: 350, height: 124) + .offset(y: 50) + .zIndex(1) + RoundedRectangle(cornerRadius: 25) + .fill(.red) + .frame(width: 125, height: 250) + } + .compositingGroup() + .shadow( + color: .black.opacity(0.4), + radius: 30, + y: 30 + ) + .padding() } - .compositingGroup() - .shadow( - color: .black.opacity(0.4), - radius: 30, - y: 30 - ) - .padding() - } } #Preview { - CompsitingGroupSample() + CompsitingGroupSample() } diff --git a/playground/samples/Gesture/RotateGestureSample.swift b/playground/samples/Gesture/RotateGestureSample.swift index d3a97ba..2eea4a4 100644 --- a/playground/samples/Gesture/RotateGestureSample.swift +++ b/playground/samples/Gesture/RotateGestureSample.swift @@ -1,5 +1,5 @@ // -// PixelatedImage.swift +// RotateGestureSample.swift // playground // // Created by Taha Tesser on 04.08.2024. @@ -8,24 +8,24 @@ import SwiftUI struct RotateGestureSample: View { - @State private var angle: Angle = .degrees(0.0) - - var rotation: some Gesture { - RotateGesture() - .onChanged { value in - self.angle = value.rotation - } - } - - var body: some View { - Image(systemName: "steeringwheel") - .font(.system(size: 300)) - .shadow(radius: 10) - .rotationEffect(angle) - .gesture(rotation) - } + @State private var angle: Angle = .degrees(0.0) + + var rotation: some Gesture { + RotateGesture() + .onChanged { value in + self.angle = value.rotation + } + } + + var body: some View { + Image(systemName: "steeringwheel") + .font(.system(size: 300)) + .shadow(radius: 10) + .rotationEffect(angle) + .gesture(rotation) + } } #Preview { - RotateGestureSample() + RotateGestureSample() } diff --git a/playground/samples/GroupBox/GroupBoxSample.swift b/playground/samples/GroupBox/GroupBoxSample.swift index f10948e..af78c4b 100644 --- a/playground/samples/GroupBox/GroupBoxSample.swift +++ b/playground/samples/GroupBox/GroupBoxSample.swift @@ -8,30 +8,28 @@ import SwiftUI struct GroupBoxSample: View { - var body: some View { - VStack { - - GroupBox("Title") { - Text( - "This is a GroupBox. Similar to a Card in Material Design and I love it!" - ) - } - .frame(width: 200) - - GroupBox { - Text( - "This is a GroupBox. Similar to a Card in Material Design and I love it!" - ) - - } label: { - Label("Title", systemImage: "airplane") - } - + var body: some View { + VStack { + GroupBox("Title") { + Text( + "This is a GroupBox. Similar to a Card in Material Design and I love it!" + ) + } + .frame(width: 200) + + GroupBox { + Text( + "This is a GroupBox. Similar to a Card in Material Design and I love it!" + ) + + } label: { + Label("Title", systemImage: "airplane") + } + } + .padding() } - .padding() - } } #Preview { - GroupBoxSample() + GroupBoxSample() } diff --git a/playground/samples/Images/AsyncImageSample.swift b/playground/samples/Images/AsyncImageSample.swift index 6757dec..a963f81 100644 --- a/playground/samples/Images/AsyncImageSample.swift +++ b/playground/samples/Images/AsyncImageSample.swift @@ -8,23 +8,23 @@ import SwiftUI struct AsyncImageSample: View { - let imageUrl = "https://github.com/TahaTesser/swift_playground/blob/main/playground/Preview%20Content/Preview%20Assets.xcassets/park.imageset/park.jpeg?raw=true" - - var body: some View { - AsyncImage(url: URL(string: imageUrl)) { image in - image - .resizable() - .scaledToFit() - } placeholder: { - ProgressView() - .progressViewStyle(CircularProgressViewStyle(tint: .green)) - .scaleEffect(2.0, anchor: .center) + let imageUrl = "https://github.com/TahaTesser/swift_playground/blob/main/playground/Preview%20Content/Preview%20Assets.xcassets/park.imageset/park.jpeg?raw=true" + + var body: some View { + AsyncImage(url: URL(string: imageUrl)) { image in + image + .resizable() + .scaledToFit() + } placeholder: { + ProgressView() + .progressViewStyle(CircularProgressViewStyle(tint: .green)) + .scaleEffect(2.0, anchor: .center) + } + .clipShape(.rect(cornerRadius: 4)) + .padding() } - .clipShape(.rect(cornerRadius: 4)) - .padding() - } } #Preview { - AsyncImageSample() + AsyncImageSample() } diff --git a/playground/samples/Images/VariableValueSample.swift b/playground/samples/Images/VariableValueSample.swift index 2019cdb..bc3d8da 100644 --- a/playground/samples/Images/VariableValueSample.swift +++ b/playground/samples/Images/VariableValueSample.swift @@ -8,40 +8,40 @@ import SwiftUI struct VariableValueSample: View { - @State private var value: Double = 0.5 - - var body: some View { - VStack { - HStack { - Image(systemName: "speaker.wave.3", variableValue: 0) - .resizable() - .aspectRatio(contentMode: .fit) - .padding() - Image(systemName: "speaker.wave.3", variableValue: 0.3) - .resizable() - .aspectRatio(contentMode: .fit) - .padding() - Image(systemName: "speaker.wave.3", variableValue: 0.6) - .resizable() - .aspectRatio(contentMode: .fit) - .padding() - Image(systemName: "speaker.wave.3", variableValue: 0.9) - .resizable() - .aspectRatio(contentMode: .fit) - .padding() - }.padding() - VStack { - Image(systemName: "speaker.wave.3", variableValue: value) - .resizable() - .frame(width: 72.0, height: 72.0) - .padding() - Slider(value: $value, in: 0...1) - .padding() - }.padding() + @State private var value: Double = 0.5 + + var body: some View { + VStack { + HStack { + Image(systemName: "speaker.wave.3", variableValue: 0) + .resizable() + .aspectRatio(contentMode: .fit) + .padding() + Image(systemName: "speaker.wave.3", variableValue: 0.3) + .resizable() + .aspectRatio(contentMode: .fit) + .padding() + Image(systemName: "speaker.wave.3", variableValue: 0.6) + .resizable() + .aspectRatio(contentMode: .fit) + .padding() + Image(systemName: "speaker.wave.3", variableValue: 0.9) + .resizable() + .aspectRatio(contentMode: .fit) + .padding() + }.padding() + VStack { + Image(systemName: "speaker.wave.3", variableValue: value) + .resizable() + .frame(width: 72.0, height: 72.0) + .padding() + Slider(value: $value, in: 0 ... 1) + .padding() + }.padding() + } } - } } #Preview { - VariableValueSample() + VariableValueSample() } diff --git a/playground/samples/LayoutAdjustments/ContainerRelativeFrameSample.swift b/playground/samples/LayoutAdjustments/ContainerRelativeFrameSample.swift index 831f2dc..d210216 100644 --- a/playground/samples/LayoutAdjustments/ContainerRelativeFrameSample.swift +++ b/playground/samples/LayoutAdjustments/ContainerRelativeFrameSample.swift @@ -8,19 +8,19 @@ import SwiftUI struct ContainerRelativeFrameSample: View { - var body: some View { - ZStack { - Color.purple - .containerRelativeFrame(.horizontal) { size, axis in - size / 2 + var body: some View { + ZStack { + Color.purple + .containerRelativeFrame(.horizontal) { size, _ in + size / 2 + } + Text("1/2 of the horizontal width") + .font(.footnote) + .foregroundStyle(.white) } - Text("1/2 of the horizontal width") - .font(.footnote) - .foregroundStyle(.white) } - } } #Preview { - ContainerRelativeFrameSample() + ContainerRelativeFrameSample() } diff --git a/playground/samples/Lists/DisclosureGroupSample.swift b/playground/samples/Lists/DisclosureGroupSample.swift index 1ac7010..6765d92 100644 --- a/playground/samples/Lists/DisclosureGroupSample.swift +++ b/playground/samples/Lists/DisclosureGroupSample.swift @@ -8,47 +8,47 @@ import SwiftUI struct DisclosureGroupSample: View { - struct Device { - let title: String - let imageName: String - } - - struct Weather { - let title: String - let imageName: String - } - - let devices: [Device] = [ - .init(title: "iPhone", imageName: "iphone"), - .init(title: "MacBook", imageName: "macbook"), - .init(title: "Mac mini", imageName: "macmini.fill"), - ] - - let weather: [Weather] = [ - .init(title: "Cloudy", imageName: "cloud.fill"), - .init(title: "Sunny", imageName: "sun.max.fill"), - .init(title: "Rainy", imageName: "cloud.rain"), - ] - - @State private var isDevicesExpanded: Bool = true - @State private var isWeatherExpanded: Bool = true - - var body: some View { - List { - DisclosureGroup("Devices", isExpanded: $isDevicesExpanded) { - ForEach(devices, id: \.title) { device in - Label(device.title, systemImage: device.imageName) - } - } - DisclosureGroup("Weather", isExpanded: $isWeatherExpanded) { - ForEach(weather, id: \.title) { item in - Label(item.title, systemImage: item.imageName) + struct Device { + let title: String + let imageName: String + } + + struct Weather { + let title: String + let imageName: String + } + + let devices: [Device] = [ + .init(title: "iPhone", imageName: "iphone"), + .init(title: "MacBook", imageName: "macbook"), + .init(title: "Mac mini", imageName: "macmini.fill"), + ] + + let weather: [Weather] = [ + .init(title: "Cloudy", imageName: "cloud.fill"), + .init(title: "Sunny", imageName: "sun.max.fill"), + .init(title: "Rainy", imageName: "cloud.rain"), + ] + + @State private var isDevicesExpanded: Bool = true + @State private var isWeatherExpanded: Bool = true + + var body: some View { + List { + DisclosureGroup("Devices", isExpanded: $isDevicesExpanded) { + ForEach(devices, id: \.title) { device in + Label(device.title, systemImage: device.imageName) + } + } + DisclosureGroup("Weather", isExpanded: $isWeatherExpanded) { + ForEach(weather, id: \.title) { item in + Label(item.title, systemImage: item.imageName) + } + } } - } } - } } #Preview { - DisclosureGroupSample() + DisclosureGroupSample() } diff --git a/playground/samples/Lists/ListSectionSpacingSample.swift b/playground/samples/Lists/ListSectionSpacingSample.swift index 8a55c51..889f6cb 100644 --- a/playground/samples/Lists/ListSectionSpacingSample.swift +++ b/playground/samples/Lists/ListSectionSpacingSample.swift @@ -8,60 +8,60 @@ import SwiftUI struct ListSectionSpacingSample: View { - var body: some View { - TabView { - Tab { - List { - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - }.listSectionSpacing(.default) - } label: { - Text("Default") - } - Tab { - List { - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - }.listSectionSpacing(.compact) - } label: { - Text("Compact") - } - Tab { - List { - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - Section { - Text("A List Item") - Text("A Second List Item") - Text("A Third List Item") - } - }.listSectionSpacing(70) - } label: { - Text("Custom") - } + var body: some View { + TabView { + Tab { + List { + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + }.listSectionSpacing(.default) + } label: { + Text("Default") + } + Tab { + List { + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + }.listSectionSpacing(.compact) + } label: { + Text("Compact") + } + Tab { + List { + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + Section { + Text("A List Item") + Text("A Second List Item") + Text("A Third List Item") + } + }.listSectionSpacing(70) + } label: { + Text("Custom") + } + } } - } } #Preview { - ListSectionSpacingSample() + ListSectionSpacingSample() } diff --git a/playground/samples/Map/MapStyleSample.swift b/playground/samples/Map/MapStyleSample.swift index ec125af..bc21703 100644 --- a/playground/samples/Map/MapStyleSample.swift +++ b/playground/samples/Map/MapStyleSample.swift @@ -1,26 +1,26 @@ // -// MapStyle.swift +// MapStyleSample.swift // playground // // Created by Taha Tesser on 04.08.2024. // -import SwiftUI import MapKit +import SwiftUI struct MapStyleSample: View { - let location = CLLocationCoordinate2D( - latitude: 41.8902, longitude: 12.4922 - ) - - var body: some View { - Map { - Marker("Colosseum", coordinate: location) + let location = CLLocationCoordinate2D( + latitude: 41.8902, longitude: 12.4922 + ) + + var body: some View { + Map { + Marker("Colosseum", coordinate: location) + } + .mapStyle(.standard(elevation: .realistic)) } - .mapStyle(.standard(elevation: .realistic)) - } } #Preview { - MapStyleSample() + MapStyleSample() } diff --git a/playground/samples/MaskingSample.swift b/playground/samples/MaskingSample.swift index ea3cc1d..82329e6 100644 --- a/playground/samples/MaskingSample.swift +++ b/playground/samples/MaskingSample.swift @@ -8,19 +8,19 @@ import SwiftUI struct MaskingSample: View { - var body: some View { - Image("park") - .resizable() - .scaledToFit() - .ignoresSafeArea() - .mask { - Image(systemName: "apple.logo") - .font(.system(size: 200)) - } - .shadow(radius: 10) - } + var body: some View { + Image("park") + .resizable() + .scaledToFit() + .ignoresSafeArea() + .mask { + Image(systemName: "apple.logo") + .font(.system(size: 200)) + } + .shadow(radius: 10) + } } #Preview { - MaskingSample() + MaskingSample() } diff --git a/playground/samples/Navigation/TabViewSample.swift b/playground/samples/Navigation/TabViewSample.swift index 7fd73a5..0d2dfb6 100644 --- a/playground/samples/Navigation/TabViewSample.swift +++ b/playground/samples/Navigation/TabViewSample.swift @@ -8,28 +8,28 @@ import SwiftUI struct TabViewSample: View { - var body: some View { - TabView { - Tab("Feed", systemImage: "rectangle.stack.fill") { - Text("Feed Page") - .font(.headline) - } - Tab("Search", systemImage: "magnifyingglass") { - Text("Search Page") - .font(.headline) - } - Tab("Notifications", systemImage: "bell.fill") { - Text("Notifications Page") - .font(.headline) - } - Tab("You", systemImage: "person.crop.circle") { - Text("You Page") - .font(.headline) - } + var body: some View { + TabView { + Tab("Feed", systemImage: "rectangle.stack.fill") { + Text("Feed Page") + .font(.headline) + } + Tab("Search", systemImage: "magnifyingglass") { + Text("Search Page") + .font(.headline) + } + Tab("Notifications", systemImage: "bell.fill") { + Text("Notifications Page") + .font(.headline) + } + Tab("You", systemImage: "person.crop.circle") { + Text("You Page") + .font(.headline) + } + } } - } } #Preview { - TabViewSample() + TabViewSample() } diff --git a/playground/samples/Navigation/TabViewStyleSample.swift b/playground/samples/Navigation/TabViewStyleSample.swift index d7139ac..1cf2d6d 100644 --- a/playground/samples/Navigation/TabViewStyleSample.swift +++ b/playground/samples/Navigation/TabViewStyleSample.swift @@ -9,26 +9,26 @@ import SwiftUI struct TabViewStyleSample: View { var body: some View { - TabView{ - Tab("Feed", systemImage: "rectangle.stack.fill") { - Text("Feed Page") - .font(.headline) - } - Tab("Search", systemImage: "magnifyingglass") { - Text("Search Page") - .font(.headline) - } - TabSection("Notifs & You") { - Tab("Notifications", systemImage: "bell.fill") { - Text("Notifications Page") - .font(.headline) - } - Tab("You", systemImage: "person.crop.circle") { - Text("You Page") - .font(.headline) - } - } - }.tabViewStyle(.sidebarAdaptable) + TabView { + Tab("Feed", systemImage: "rectangle.stack.fill") { + Text("Feed Page") + .font(.headline) + } + Tab("Search", systemImage: "magnifyingglass") { + Text("Search Page") + .font(.headline) + } + TabSection("Notifs & You") { + Tab("Notifications", systemImage: "bell.fill") { + Text("Notifications Page") + .font(.headline) + } + Tab("You", systemImage: "person.crop.circle") { + Text("You Page") + .font(.headline) + } + } + }.tabViewStyle(.sidebarAdaptable) } } diff --git a/playground/samples/Slider/SliderSample.swift b/playground/samples/Slider/SliderSample.swift index 6eac4be..c952dbd 100644 --- a/playground/samples/Slider/SliderSample.swift +++ b/playground/samples/Slider/SliderSample.swift @@ -8,21 +8,21 @@ import SwiftUI struct SliderSample: View { - @State var sliderValue = 50.0 - @State var isEditing = false - + @State var sliderValue = 50.0 + @State var isEditing = false + var body: some View { - VStack { - Slider( - value: $sliderValue, - in: 0...100, - onEditingChanged: { editing in - isEditing = editing - } - ) - Text("\(sliderValue)") - .foregroundStyle(isEditing ? .red : .blue) - }.padding() + VStack { + Slider( + value: $sliderValue, + in: 0 ... 100, + onEditingChanged: { editing in + isEditing = editing + } + ) + Text("\(sliderValue)") + .foregroundStyle(isEditing ? .red : .blue) + }.padding() } } diff --git a/playground/samples/Tables/TableSample.swift b/playground/samples/Tables/TableSample.swift index c775108..25c72e0 100644 --- a/playground/samples/Tables/TableSample.swift +++ b/playground/samples/Tables/TableSample.swift @@ -8,68 +8,66 @@ import SwiftUI struct Person: Identifiable { - let givenName: String - let familyName: String - let emailAddress: String - let id = UUID() - - var fullName: String { givenName + " " + familyName } + let givenName: String + let familyName: String + let emailAddress: String + let id = UUID() + + var fullName: String { givenName + " " + familyName } } struct TableSample: View { - @State private var people = [ - Person( - givenName: "Juan", - familyName: "Chavez", - emailAddress: "juanchavez@icloud.com" - ), - Person( - givenName: "Mei", - familyName: "Chen", - emailAddress: "meichen@icloud.com" - ), - Person( - givenName: "Tom", - familyName: "Clark", - emailAddress: "tomclark@icloud.com" - ), - Person( - givenName: "Gita", - familyName: "Kumar", - emailAddress: "gitakumar@icloud.com" - ) - ] - @State private var sortOrder = [KeyPathComparator(\Person.givenName)] + @State private var people = [ + Person( + givenName: "Juan", + familyName: "Chavez", + emailAddress: "juanchavez@icloud.com" + ), + Person( + givenName: "Mei", + familyName: "Chen", + emailAddress: "meichen@icloud.com" + ), + Person( + givenName: "Tom", + familyName: "Clark", + emailAddress: "tomclark@icloud.com" + ), + Person( + givenName: "Gita", + familyName: "Kumar", + emailAddress: "gitakumar@icloud.com" + ), + ] + @State private var sortOrder = [KeyPathComparator(\Person.givenName)] + + #if os(iOS) + @Environment(\.horizontalSizeClass) private var horizontalSizeClass + private var isCompact: Bool { horizontalSizeClass == .compact } + #else + private let isCompact = false + #endif - -#if os(iOS) - @Environment(\.horizontalSizeClass) private var horizontalSizeClass - private var isCompact: Bool { horizontalSizeClass == .compact } -#else - private let isCompact = false -#endif - - var body: some View { - Table(people, sortOrder: $sortOrder) { - TableColumn("Given Name", value: \.givenName) { person in - VStack(alignment: .leading) { - Text(isCompact ? person.fullName : person.givenName) - if isCompact { - Text(person.emailAddress) - .foregroundStyle(.secondary) - } + var body: some View { + Table(people, sortOrder: $sortOrder) { + TableColumn("Given Name", value: \.givenName) { person in + VStack(alignment: .leading) { + Text(isCompact ? person.fullName : person.givenName) + if isCompact { + Text(person.emailAddress) + .foregroundStyle(.secondary) + } + } + } + TableColumn("Family Name", value: \.familyName) + TableColumn("E-Mail Address", value: \.emailAddress) + } + .onChange(of: sortOrder) { _, sortOrder in + people.sort(using: sortOrder) } - } - TableColumn("Family Name", value: \.familyName) - TableColumn("E-Mail Address", value: \.emailAddress) - } - .onChange(of: sortOrder) { _, sortOrder in - people.sort(using: sortOrder) } - - } } #Preview { - TableSample() + TableSample() } diff --git a/playground/samples/Text/RelativeDateStyleSample.swift b/playground/samples/Text/RelativeDateStyleSample.swift index f2f55bd..efbf391 100644 --- a/playground/samples/Text/RelativeDateStyleSample.swift +++ b/playground/samples/Text/RelativeDateStyleSample.swift @@ -1,5 +1,5 @@ // -// DynamicDatesSample.swift +// RelativeDateStyleSample.swift // playground // // Created by Taha Tesser on 17.08.2024. diff --git a/playground/samples/Text/TextRendererSample.swift b/playground/samples/Text/TextRendererSample.swift index 0424790..2c6e1c0 100644 --- a/playground/samples/Text/TextRendererSample.swift +++ b/playground/samples/Text/TextRendererSample.swift @@ -8,138 +8,137 @@ import SwiftUI struct TextRendererSample: View { - @State private var amount = -10.0 - @State private var strength = 0.0 - - var body: some View { - VStack(spacing: 16.0) { - Text("Hello,\nWorld! ") - .font(.largeTitle) - .textRenderer(ZebraStripeRenderer()) - - Text("Hello, World!") - .font(.largeTitle) - .textRenderer(BoxedRenderer()) - - Text("Hello, World!") - .font(.largeTitle) - .textRenderer(WaveRenderer(strength: amount, frequency: 0.5 )) - .onAppear() { - withAnimation( - .easeInOut(duration: 1).repeatForever(autoreverses: true) - ) { - amount = 10 - } - } + @State private var amount = -10.0 + @State private var strength = 0.0 - Text("Hello, World!") - .font(.largeTitle) - .textRenderer(QuakeRenderer(moveAmount: strength)) - .onAppear() { - withAnimation( - .easeInOut(duration: 1).repeatForever(autoreverses: true) - ) { - strength = 10 - } - } + var body: some View { + VStack(spacing: 16.0) { + Text("Hello,\nWorld! ") + .font(.largeTitle) + .textRenderer(ZebraStripeRenderer()) + + Text("Hello, World!") + .font(.largeTitle) + .textRenderer(BoxedRenderer()) + + Text("Hello, World!") + .font(.largeTitle) + .textRenderer(WaveRenderer(strength: amount, frequency: 0.5)) + .onAppear { + withAnimation( + .easeInOut(duration: 1).repeatForever(autoreverses: true) + ) { + amount = 10 + } + } + Text("Hello, World!") + .font(.largeTitle) + .textRenderer(QuakeRenderer(moveAmount: strength)) + .onAppear { + withAnimation( + .easeInOut(duration: 1).repeatForever(autoreverses: true) + ) { + strength = 10 + } + } + } + .padding() } - .padding() - } } #Preview { - TextRendererSample() + TextRendererSample() } struct ZebraStripeRenderer: TextRenderer { - func draw(layout: Text.Layout, in context: inout GraphicsContext) { - for (index, line) in layout.enumerated() { - if index.isMultiple(of: 2) { - context.opacity = 1 - } else { - context.opacity = 0.3 - } - - context.draw(line) + func draw(layout: Text.Layout, in context: inout GraphicsContext) { + for (index, line) in layout.enumerated() { + if index.isMultiple(of: 2) { + context.opacity = 1 + } else { + context.opacity = 0.3 + } + + context.draw(line) + } } - } } struct BoxedRenderer: TextRenderer { - func draw(layout: Text.Layout, in context: inout GraphicsContext) { - for line in layout { - for run in line { - for glyph in run { - context - .stroke( - Rectangle().path(in: glyph.typographicBounds.rect), - with: .color(.blue), - lineWidth: 2 - ) + func draw(layout: Text.Layout, in context: inout GraphicsContext) { + for line in layout { + for run in line { + for glyph in run { + context + .stroke( + Rectangle().path(in: glyph.typographicBounds.rect), + with: .color(.blue), + lineWidth: 2 + ) + } + context + .stroke( + Rectangle().path(in: run.typographicBounds.rect), + with: .color(.green), + lineWidth: 2 + ) + } + + context + .stroke( + Rectangle().path(in: line.typographicBounds.rect), + with: .color(.red), + lineWidth: 2 + ) + context.draw(line) } - context - .stroke( - Rectangle().path(in: run.typographicBounds.rect), - with: .color(.green), - lineWidth: 2 - ) - } - - context - .stroke( - Rectangle().path(in: line.typographicBounds.rect), - with: .color(.red), - lineWidth: 2 - ) - context.draw(line) } - } } struct WaveRenderer: TextRenderer { - var strength: Double - var frequency: Double - - var animatableData: Double { - get { strength } - set { strength = newValue } - } - - func draw(layout: Text.Layout, in context: inout GraphicsContext) { - for line in layout { - for run in line { - for (index, glyph) in run.enumerated() { - let yOffset = strength * sin(Double(index) * frequency) - var copy = context - - copy.translateBy(x: 0, y: yOffset) - copy.draw(glyph, options: .disablesSubpixelQuantization) + var strength: Double + var frequency: Double + + var animatableData: Double { + get { strength } + set { strength = newValue } + } + + func draw(layout: Text.Layout, in context: inout GraphicsContext) { + for line in layout { + for run in line { + for (index, glyph) in run.enumerated() { + let yOffset = strength * sin(Double(index) * frequency) + var copy = context + + copy.translateBy(x: 0, y: yOffset) + copy.draw(glyph, options: .disablesSubpixelQuantization) + } + } } - } } - } } struct QuakeRenderer: TextRenderer { - var moveAmount: Double - - var animatableData: Double { - get { moveAmount } - set { moveAmount = newValue } - } - - func draw(layout: Text.Layout, in context: inout GraphicsContext) { - for line in layout { - for run in line { - for glyph in run { - var copy = context - let yOffset = Double.random(in: -moveAmount...moveAmount) - - copy.translateBy(x: 0, y: yOffset) - copy.draw(glyph, options: .disablesSubpixelQuantization) + var moveAmount: Double + + var animatableData: Double { + get { moveAmount } + set { moveAmount = newValue } + } + + func draw(layout: Text.Layout, in context: inout GraphicsContext) { + for line in layout { + for run in line { + for glyph in run { + var copy = context + let yOffset = Double.random(in: -moveAmount ... moveAmount) + + copy.translateBy(x: 0, y: yOffset) + copy.draw(glyph, options: .disablesSubpixelQuantization) + } + } } - } } - } } diff --git a/playground/samples/ThirdParty/JunoUISliderSample.swift b/playground/samples/ThirdParty/JunoUISliderSample.swift index 6838ced..6d23f12 100644 --- a/playground/samples/ThirdParty/JunoUISliderSample.swift +++ b/playground/samples/ThirdParty/JunoUISliderSample.swift @@ -8,28 +8,29 @@ import SwiftUI struct JunoUISliderSample: View { - @State var sliderValue: CGFloat = 0.5 - @State var isSliderActive = false - - var body: some View { - VStack { - GroupBox { - JunoSlider( - sliderValue: $sliderValue, - maxSliderValue: 1.0, - baseHeight: 10.0, - expandedHeight: 22.0, - label: "Volume") { changed in - isSliderActive = changed - } - } + @State var sliderValue: CGFloat = 0.5 + @State var isSliderActive = false + + var body: some View { + VStack { + GroupBox { + JunoSlider( + sliderValue: $sliderValue, + maxSliderValue: 1.0, + baseHeight: 10.0, + expandedHeight: 22.0, + label: "Volume" + ) { changed in + isSliderActive = changed + } + } + } + .padding() } - .padding() - } } #Preview { - JunoUISliderSample() + JunoUISliderSample() } /// This is copied from https://github.com/christianselig/JunoSlider @@ -37,157 +38,157 @@ struct JunoUISliderSample: View { /// /// A slider that expands on selection. public struct JunoSlider: View { - @Binding var sliderValue: CGFloat - let maxSliderValue: CGFloat - let baseHeight: CGFloat - let expandedHeight: CGFloat - let label: String - let editingChanged: ((Bool) -> Void)? - - @State private var isGestureActive: Bool = false - @State private var startingSliderValue: CGFloat? - @State private var sliderWidth = 10.0 // Just an initial value to prevent division by 0 - @State private var isAtTrackExtremity = false - - /// Create a slider that expands on selection. - /// - Parameters: - /// - sliderValue: Binding for the current value of the slider - /// - maxSliderValue: The highest value the slider can be - /// - baseHeight: The slider's height when not expanded - /// - expandedHeight: The slider's height when selected (thus expanded) - /// - label: A string to describe what the data the slider represents - /// - editingChanged: An optional block that is called when the slider updates to sliding and when it stops - public init( - sliderValue: Binding, - maxSliderValue: CGFloat, - baseHeight: CGFloat = 9.0, - expandedHeight: CGFloat = 20.0, - label: String, - editingChanged: ((Bool) -> Void)? = nil - ) { - self._sliderValue = sliderValue - self.maxSliderValue = maxSliderValue - self.baseHeight = baseHeight - self.expandedHeight = expandedHeight - self.label = label - self.editingChanged = editingChanged - } - -#if os(macOS) - public var body: some View { - Text("JunoSlider does not support macOS") - } -#else - public var body: some View { - ZStack { - // visionOS (on device) does not like when drag targets are smaller than 40pt tall, so add an almost-transparent (as it still needs to be interactive) that enforces an effective minimum height. If the slider is tall than this on its own it's essentially just ignored. - Color.orange.opacity(0.0001) - .frame(height: 40.0) - - Capsule() - .background { - GeometryReader { proxy in - Color.clear - .onAppear { - sliderWidth = proxy.size.width - } - } + @Binding var sliderValue: CGFloat + let maxSliderValue: CGFloat + let baseHeight: CGFloat + let expandedHeight: CGFloat + let label: String + let editingChanged: ((Bool) -> Void)? + + @State private var isGestureActive: Bool = false + @State private var startingSliderValue: CGFloat? + @State private var sliderWidth = 10.0 // Just an initial value to prevent division by 0 + @State private var isAtTrackExtremity = false + + /// Create a slider that expands on selection. + /// - Parameters: + /// - sliderValue: Binding for the current value of the slider + /// - maxSliderValue: The highest value the slider can be + /// - baseHeight: The slider's height when not expanded + /// - expandedHeight: The slider's height when selected (thus expanded) + /// - label: A string to describe what the data the slider represents + /// - editingChanged: An optional block that is called when the slider updates to sliding and when it stops + public init( + sliderValue: Binding, + maxSliderValue: CGFloat, + baseHeight: CGFloat = 9.0, + expandedHeight: CGFloat = 20.0, + label: String, + editingChanged: ((Bool) -> Void)? = nil + ) { + _sliderValue = sliderValue + self.maxSliderValue = maxSliderValue + self.baseHeight = baseHeight + self.expandedHeight = expandedHeight + self.label = label + self.editingChanged = editingChanged + } + + #if os(macOS) + public var body: some View { + Text("JunoSlider does not support macOS") } - .frame(height: isGestureActive ? expandedHeight : baseHeight) - .foregroundStyle( - Color(white: 0.1, opacity: 0.5) - .shadow( - .inner( - color: .black.opacity(0.3), - radius: 3.0, - y: 2.0 - ) - ) - ) - .shadow(color: .white.opacity(0.2), radius: 1, y: 1) - .overlay(alignment: .leading) { - Capsule() - .overlay(alignment: .trailing) { - Circle() - .foregroundStyle(Color.white) - .shadow(radius: 1.0) - .padding(innerCirclePadding) - .opacity(isGestureActive ? 1.0 : 0.0) + #else + public var body: some View { + ZStack { + // visionOS (on device) does not like when drag targets are smaller than 40pt tall, so add an almost-transparent (as it still needs to be interactive) that enforces an effective minimum height. If the slider is tall than this on its own it's essentially just ignored. + Color.orange.opacity(0.0001) + .frame(height: 40.0) + + Capsule() + .background { + GeometryReader { proxy in + Color.clear + .onAppear { + sliderWidth = proxy.size.width + } + } + } + .frame(height: isGestureActive ? expandedHeight : baseHeight) + .foregroundStyle( + Color(white: 0.1, opacity: 0.5) + .shadow( + .inner( + color: .black.opacity(0.3), + radius: 3.0, + y: 2.0 + ) + ) + ) + .shadow(color: .white.opacity(0.2), radius: 1, y: 1) + .overlay(alignment: .leading) { + Capsule() + .overlay(alignment: .trailing) { + Circle() + .foregroundStyle(Color.white) + .shadow(radius: 1.0) + .padding(innerCirclePadding) + .opacity(isGestureActive ? 1.0 : 0.0) + } + .foregroundStyle( + Color(white: isGestureActive ? 0.85 : 1.0) + ) + .frame( + width: calculateProgressWidth(), + height: isGestureActive ? expandedHeight : baseHeight + ) + } + .clipShape( + .capsule + ) // Best attempt at fixing a bug https://twitter.com/ChristianSelig/status/1757139789457829902 + .contentShape(.hoverEffect, .capsule) } - .foregroundStyle( - Color(white: isGestureActive ? 0.85 : 1.0) - ) - .frame( - width: calculateProgressWidth(), - height: isGestureActive ? expandedHeight : baseHeight + .gesture( + DragGesture(minimumDistance: 0.0) + .onChanged { value in + if startingSliderValue == nil { + startingSliderValue = sliderValue + isGestureActive = true + editingChanged?(true) + } + + let percentagePointsIncreased = value.translation.width / sliderWidth + let initialPercentage = ( + startingSliderValue ?? sliderValue + ) / maxSliderValue + let newPercentage = min( + 1.0, + max(0.0, initialPercentage + percentagePointsIncreased) + ) + sliderValue = newPercentage * maxSliderValue + + if newPercentage == 0.0, !isAtTrackExtremity { + isAtTrackExtremity = true + } else if newPercentage == 1.0, !isAtTrackExtremity { + isAtTrackExtremity = true + } else if newPercentage > 0.0, newPercentage < 1.0 { + isAtTrackExtremity = false + } + } + .onEnded { value in + // Check if they just tapped somewhere on the bar rather than actually dragging, in which case update the progress to the position they tapped + if value.translation.width == 0.0 { + let newPercentage = value.location.x / sliderWidth + + withAnimation { + sliderValue = newPercentage * maxSliderValue + } + } + + startingSliderValue = nil + isGestureActive = false + editingChanged?(false) + } ) - } - .clipShape( - .capsule - ) // Best attempt at fixing a bug https://twitter.com/ChristianSelig/status/1757139789457829902 - .contentShape(.hoverEffect, .capsule) - } - .gesture( - DragGesture(minimumDistance: 0.0) - .onChanged { value in - if startingSliderValue == nil { - startingSliderValue = sliderValue - isGestureActive = true - editingChanged?(true) - } - - let percentagePointsIncreased = value.translation.width / sliderWidth - let initialPercentage = ( - startingSliderValue ?? sliderValue - ) / maxSliderValue - let newPercentage = min( - 1.0, - max(0.0, initialPercentage + percentagePointsIncreased) - ) - sliderValue = newPercentage * maxSliderValue - - if newPercentage == 0.0 && !isAtTrackExtremity { - isAtTrackExtremity = true - } else if newPercentage == 1.0 && !isAtTrackExtremity { - isAtTrackExtremity = true - } else if newPercentage > 0.0 && newPercentage < 1.0 { - isAtTrackExtremity = false - } - } - .onEnded { value in - // Check if they just tapped somewhere on the bar rather than actually dragging, in which case update the progress to the position they tapped - if value.translation.width == 0.0 { - let newPercentage = value.location.x / sliderWidth - - withAnimation { - sliderValue = newPercentage * maxSliderValue + .hoverEffect(.highlight) + .animation(.default, value: isGestureActive) + .accessibilityRepresentation { + Slider(value: $sliderValue, in: 0.0 ... maxSliderValue, label: { + Text(label) + }, onEditingChanged: { editingChanged in + self.editingChanged?(editingChanged) + }) } - } - - startingSliderValue = nil - isGestureActive = false - editingChanged?(false) } - ) - .hoverEffect(.highlight) - .animation(.default, value: isGestureActive) - .accessibilityRepresentation { - Slider(value: $sliderValue, in: 0.0 ... maxSliderValue, label: { - Text(label) - }, onEditingChanged: { editingChanged in - self.editingChanged?(editingChanged) - }) + #endif + + private var innerCirclePadding: CGFloat { expandedHeight * 0.15 } + + private func calculateProgressWidth() -> CGFloat { + let minimumWidth = isGestureActive ? expandedHeight : baseHeight + let calculatedWidth = (sliderValue / maxSliderValue) * sliderWidth + + // Don't let the bar get so small that it disappears + return max(minimumWidth, calculatedWidth) } - } -#endif - - private var innerCirclePadding: CGFloat { expandedHeight * 0.15 } - - private func calculateProgressWidth() -> CGFloat { - let minimumWidth = isGestureActive ? expandedHeight : baseHeight - let calculatedWidth = (sliderValue / maxSliderValue) * sliderWidth - - // Don't let the bar get so small that it disappears - return max(minimumWidth, calculatedWidth) - } } diff --git a/playground/samples/ViewGroupings/FormSample.swift b/playground/samples/ViewGroupings/FormSample.swift index 72e6d64..d3b8ac6 100644 --- a/playground/samples/ViewGroupings/FormSample.swift +++ b/playground/samples/ViewGroupings/FormSample.swift @@ -8,50 +8,50 @@ import SwiftUI struct FormSample: View { - @State private var notifyMeAbout: NotifyMeAboutType = .directMessages - @State private var playNotificationSounds: Bool = true - @State private var sendReadReceipts: Bool = false - @State private var profileImageSize: ProfileImageSize = .medium - - var body: some View { - Form { - Section(header: Text("Notifications")) { - Picker("Notify Me Abiut", selection: $notifyMeAbout) { - Text("Direct Messages").tag(NotifyMeAboutType.directMessages) - Text("Mentions").tag(NotifyMeAboutType.mentions) - Text("Anything").tag(NotifyMeAboutType.anything) - } - Toggle("Play notification sounds", isOn: $playNotificationSounds) - Toggle("Send read receipts", isOn: $sendReadReceipts) - } - Section(header: Text("User Profiles")) { - Picker("Profile Image Size", selection: $profileImageSize) { - Text("Large").tag(ProfileImageSize.large) - Text("Medium").tag(ProfileImageSize.medium) - Text("Small").tag(ProfileImageSize.small) + @State private var notifyMeAbout: NotifyMeAboutType = .directMessages + @State private var playNotificationSounds: Bool = true + @State private var sendReadReceipts: Bool = false + @State private var profileImageSize: ProfileImageSize = .medium + + var body: some View { + Form { + Section(header: Text("Notifications")) { + Picker("Notify Me Abiut", selection: $notifyMeAbout) { + Text("Direct Messages").tag(NotifyMeAboutType.directMessages) + Text("Mentions").tag(NotifyMeAboutType.mentions) + Text("Anything").tag(NotifyMeAboutType.anything) + } + Toggle("Play notification sounds", isOn: $playNotificationSounds) + Toggle("Send read receipts", isOn: $sendReadReceipts) + } + Section(header: Text("User Profiles")) { + Picker("Profile Image Size", selection: $profileImageSize) { + Text("Large").tag(ProfileImageSize.large) + Text("Medium").tag(ProfileImageSize.medium) + Text("Small").tag(ProfileImageSize.small) + } + Button("Clear Image Cache") {} + } } - Button("Clear Image Cache") {} - } } - } } enum NotifyMeAboutType: String, CaseIterable, Identifiable { - case directMessages - case mentions - case anything - - var id: Self { self } + case directMessages + case mentions + case anything + + var id: Self { self } } enum ProfileImageSize: String, CaseIterable, Identifiable { - case large - case medium - case small - - var id: Self { self } + case large + case medium + case small + + var id: Self { self } } #Preview { - FormSample() + FormSample() } diff --git a/playgroundTests/playgroundTests.swift b/playgroundTests/playgroundTests.swift index 75b51f9..ee9447b 100644 --- a/playgroundTests/playgroundTests.swift +++ b/playgroundTests/playgroundTests.swift @@ -8,9 +8,5 @@ import Testing struct playgroundTests { - - @Test func example() async throws { - - } - + @Test func example() async throws {} } diff --git a/playgroundTests/sliderTests.swift b/playgroundTests/sliderTests.swift index db53a3b..c7967fc 100644 --- a/playgroundTests/sliderTests.swift +++ b/playgroundTests/sliderTests.swift @@ -1,19 +1,17 @@ // -// sliderTest.swift +// sliderTests.swift // playgroundTests // // Created by Taha Tesser on 08.08.2024. // -import Testing import SwiftUI +import Testing import XCTest struct sliderTests { - - @Test func testInitialSliderValue() throws { - let sliderSample = SliderSample() - XCTAssertEqual(sliderSample.sliderValue, 50.0, "Initial slider value should be 50.0") - } - + @Test func testInitialSliderValue() throws { + let sliderSample = SliderSample() + XCTAssertEqual(sliderSample.sliderValue, 50.0, "Initial slider value should be 50.0") + } } diff --git a/playgroundUITests/playgroundUITests.swift b/playgroundUITests/playgroundUITests.swift index c72b83c..4991292 100644 --- a/playgroundUITests/playgroundUITests.swift +++ b/playgroundUITests/playgroundUITests.swift @@ -8,7 +8,6 @@ import XCTest final class playgroundUITests: XCTestCase { - override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/playgroundUITests/playgroundUITestsLaunchTests.swift b/playgroundUITests/playgroundUITestsLaunchTests.swift index fd8bf90..a4a8737 100644 --- a/playgroundUITests/playgroundUITestsLaunchTests.swift +++ b/playgroundUITests/playgroundUITestsLaunchTests.swift @@ -8,7 +8,6 @@ import XCTest final class playgroundUITestsLaunchTests: XCTestCase { - override class var runsForEachTargetApplicationUIConfiguration: Bool { true }