From e076ec2b3b3888e6dd6dad497aefdc958000d550 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 11:51:55 +0330 Subject: [PATCH 1/6] refactor: use the `content` term to make the interface more match with the native api naming like the `ForEach` --- Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index 268c2e4..5334d98 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -2,12 +2,12 @@ import SwiftUI public let flowLayoutDefaultItemSpacing: CGFloat = 4 -public struct FlowLayout: View where Data.Element: Hashable { +public struct FlowLayout: View where Data.Element: Hashable { let mode: Mode @Binding var binding: RefreshBinding let items: Data let itemSpacing: CGFloat - @ViewBuilder let viewMapping: (Data.Element) -> ItemView + @ViewBuilder let content: (Data.Element) -> Content @State private var totalHeight: CGFloat @@ -15,12 +15,12 @@ public struct FlowLayout, items: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, - @ViewBuilder viewMapping: @escaping (Data.Element) -> ItemView) { + @ViewBuilder content: @escaping (Data.Element) -> Content) { self.mode = mode _binding = binding self.items = items self.itemSpacing = itemSpacing - self.viewMapping = viewMapping + self.content = content _totalHeight = State(initialValue: (mode == .scrollable) ? .zero : .infinity) } @@ -46,7 +46,7 @@ public struct FlowLayout g.size.width) { @@ -102,12 +102,12 @@ public extension FlowLayout where RefreshBinding == Never? { init(mode: Mode, items: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, - @ViewBuilder viewMapping: @escaping (Data.Element) -> ItemView) { + @ViewBuilder content: @escaping (Data.Element) -> Content) { self.init(mode: mode, binding: .constant(nil), items: items, itemSpacing: itemSpacing, - viewMapping: viewMapping) + content: content) } } From a614ccfe60919340c1073257ec335de7cb8cc551 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 11:52:57 +0330 Subject: [PATCH 2/6] feat: add unavailable interfaces to help Xcode figuring out how to migrate --- .../SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index 5334d98..176f38c 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -180,3 +180,39 @@ struct TestWithRange_Previews: PreviewProvider { }.padding() } } + +// MARK: Migration Helpers + +public extension FlowLayout { + @available(swift, obsoleted: 1.1.0, renamed: "attemptConnection") + var viewMapping: (Data.Element) -> Content { content } + + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:binding:items:itemSpacing:content:)") + init(mode: Mode, + binding: Binding, + items: Data, + itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, + @ViewBuilder viewMapping: @escaping (Data.Element) -> Content) { + self.init(mode: mode, + binding: binding, + items: items, + itemSpacing: itemSpacing, + content: viewMapping) + } +} + +public extension FlowLayout where RefreshBinding == Never? { + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:items:itemSpacing:content:)") + init(mode: Mode, + items: Data, + itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, + @ViewBuilder viewMapping: @escaping (Data.Element) -> Content) { + self.init( + mode: mode, + binding: .constant(nil), + items: items, + itemSpacing: itemSpacing, + content: viewMapping + ) + } +} From 0eb201023ec60694249bbbec38f133d11b53614d Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 12:05:08 +0330 Subject: [PATCH 3/6] refactor: use the term `data` instead of `items` --- .../SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index 176f38c..3cf1e7a 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -5,7 +5,7 @@ public let flowLayoutDefaultItemSpacing: CGFloat = 4 public struct FlowLayout: View where Data.Element: Hashable { let mode: Mode @Binding var binding: RefreshBinding - let items: Data + let data: Data let itemSpacing: CGFloat @ViewBuilder let content: (Data.Element) -> Content @@ -13,12 +13,12 @@ public struct FlowLayout, - items: Data, + data: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, @ViewBuilder content: @escaping (Data.Element) -> Content) { self.mode = mode _binding = binding - self.items = items + self.data = data self.itemSpacing = itemSpacing self.content = content _totalHeight = State(initialValue: (mode == .scrollable) ? .zero : .infinity) @@ -43,9 +43,9 @@ public struct FlowLayout Content) { self.init(mode: mode, binding: .constant(nil), - items: items, + data: data, itemSpacing: itemSpacing, content: content) } @@ -114,7 +114,7 @@ public extension FlowLayout where RefreshBinding == Never? { struct FlowLayout_Previews: PreviewProvider { static var previews: some View { FlowLayout(mode: .scrollable, - items: ["Some long item here", "And then some longer one", + data: ["Some long item here", "And then some longer one", "Short", "Items", "Here", "And", "A", "Few", "More", "And then a very very very long long long long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long long long one", "and", "then", "some", "short short short ones"]) { Text($0) @@ -129,25 +129,26 @@ struct FlowLayout_Previews: PreviewProvider { } struct TestWithDeletion: View { - @State private var items = ["Some long item here", "And then some longer one", + @State private var data = ["Some long item here", "And then some longer one", "Short", "Items", "Here", "And", "A", "Few", "More", "And then a very very very long long long long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long long long one", "and", "then", "some", "short short short ones"] var body: some View { VStack { Button("Delete all") { - items.removeAll() + data.removeAll() } Button("Restore") { - items = ["Some long item here", "And then some longer one", + data = ["Some long item here", "And then some longer one", "Short", "Items", "Here", "And", "A", "Few", "More", "And then a very very very long long long long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long longlong long long long long long long long one", "and", "then", "some", "short short short ones"] } Button("Add one") { - items.append("\(Date().timeIntervalSince1970)") + data.append("\(Date().timeIntervalSince1970)") } FlowLayout(mode: .vstack, - items: items) { + data: data) { + Text($0) .font(.system(size: 12)) .foregroundColor(.black) @@ -169,7 +170,7 @@ struct TestWithDeletion_Previews: PreviewProvider { struct TestWithRange_Previews: PreviewProvider { static var previews: some View { FlowLayout(mode: .scrollable, - items: 1..<100) { + data: 1..<100) { Text("\($0)") .font(.system(size: 12)) .foregroundColor(.black) @@ -187,7 +188,7 @@ public extension FlowLayout { @available(swift, obsoleted: 1.1.0, renamed: "attemptConnection") var viewMapping: (Data.Element) -> Content { content } - @available(swift, obsoleted: 1.1.0, renamed: "init(mode:binding:items:itemSpacing:content:)") + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:binding:data:itemSpacing:content:)") init(mode: Mode, binding: Binding, items: Data, @@ -195,14 +196,14 @@ public extension FlowLayout { @ViewBuilder viewMapping: @escaping (Data.Element) -> Content) { self.init(mode: mode, binding: binding, - items: items, + data: items, itemSpacing: itemSpacing, content: viewMapping) } } public extension FlowLayout where RefreshBinding == Never? { - @available(swift, obsoleted: 1.1.0, renamed: "init(mode:items:itemSpacing:content:)") + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:data:itemSpacing:content:)") init(mode: Mode, items: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, @@ -210,7 +211,7 @@ public extension FlowLayout where RefreshBinding == Never? { self.init( mode: mode, binding: .constant(nil), - items: items, + data: items, itemSpacing: itemSpacing, content: viewMapping ) From 33be8df5265d8c71bb6b714b21791c9bf7c7a50e Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 12:07:14 +0330 Subject: [PATCH 4/6] refactor: use the term `trigger` instead of `binding` --- .../SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index 3cf1e7a..e969b69 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -2,9 +2,9 @@ import SwiftUI public let flowLayoutDefaultItemSpacing: CGFloat = 4 -public struct FlowLayout: View where Data.Element: Hashable { +public struct FlowLayout: View where Data.Element: Hashable { let mode: Mode - @Binding var binding: RefreshBinding + @Binding var trigger: Trigger let data: Data let itemSpacing: CGFloat @ViewBuilder let content: (Data.Element) -> Content @@ -12,12 +12,12 @@ public struct FlowLayout, + trigger: Binding, data: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, @ViewBuilder content: @escaping (Data.Element) -> Content) { self.mode = mode - _binding = binding + _trigger = trigger self.data = data self.itemSpacing = itemSpacing self.content = content @@ -71,7 +71,7 @@ public struct FlowLayout Content) { self.init(mode: mode, - binding: .constant(nil), + trigger: .constant(nil), data: data, itemSpacing: itemSpacing, content: content) @@ -188,21 +188,21 @@ public extension FlowLayout { @available(swift, obsoleted: 1.1.0, renamed: "attemptConnection") var viewMapping: (Data.Element) -> Content { content } - @available(swift, obsoleted: 1.1.0, renamed: "init(mode:binding:data:itemSpacing:content:)") + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:trigger:data:itemSpacing:content:)") init(mode: Mode, - binding: Binding, + binding: Binding, items: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, @ViewBuilder viewMapping: @escaping (Data.Element) -> Content) { self.init(mode: mode, - binding: binding, + trigger: binding, data: items, itemSpacing: itemSpacing, content: viewMapping) } } -public extension FlowLayout where RefreshBinding == Never? { +public extension FlowLayout where Trigger == Never? { @available(swift, obsoleted: 1.1.0, renamed: "init(mode:data:itemSpacing:content:)") init(mode: Mode, items: Data, @@ -210,7 +210,7 @@ public extension FlowLayout where RefreshBinding == Never? { @ViewBuilder viewMapping: @escaping (Data.Element) -> Content) { self.init( mode: mode, - binding: .constant(nil), + trigger: .constant(nil), data: items, itemSpacing: itemSpacing, content: viewMapping From 2ade4f2ccef218a97259452e636a0d3357eac964 Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 12:08:44 +0330 Subject: [PATCH 5/6] refactor: use the apple style to specify generic constraints --- Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index e969b69..c9bf69f 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -2,7 +2,7 @@ import SwiftUI public let flowLayoutDefaultItemSpacing: CGFloat = 4 -public struct FlowLayout: View where Data.Element: Hashable { +public struct FlowLayout: View where Data: RandomAccessCollection, Data.Element: Hashable, Content: View { let mode: Mode @Binding var trigger: Trigger let data: Data From 3686ebbdb2119ebd61ad9f29d57f983f00ea91af Mon Sep 17 00:00:00 2001 From: Seyed Mojtaba Hosseini Zeidabadi Date: Tue, 3 Sep 2024 12:11:43 +0330 Subject: [PATCH 6/6] refactor: use the term `spacing` instead of `itemSpacing` --- .../SwiftUIFlowLayout/SwiftUIFlowLayout.swift | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift index c9bf69f..429a5e8 100644 --- a/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift +++ b/Sources/SwiftUIFlowLayout/SwiftUIFlowLayout.swift @@ -6,7 +6,7 @@ public struct FlowLayout: View where Data: RandomAccessC let mode: Mode @Binding var trigger: Trigger let data: Data - let itemSpacing: CGFloat + let spacing: CGFloat @ViewBuilder let content: (Data.Element) -> Content @State private var totalHeight: CGFloat @@ -14,12 +14,12 @@ public struct FlowLayout: View where Data: RandomAccessC public init(mode: Mode, trigger: Binding, data: Data, - itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, + spacing: CGFloat = flowLayoutDefaultItemSpacing, @ViewBuilder content: @escaping (Data.Element) -> Content) { self.mode = mode _trigger = trigger self.data = data - self.itemSpacing = itemSpacing + self.spacing = spacing self.content = content _totalHeight = State(initialValue: (mode == .scrollable) ? .zero : .infinity) } @@ -47,7 +47,7 @@ public struct FlowLayout: View where Data: RandomAccessC return ZStack(alignment: .topLeading) { ForEach(Array(data.enumerated()), id: \.offset) { index, item in content(item) - .padding([.horizontal, .vertical], itemSpacing) + .padding([.horizontal, .vertical], spacing) .alignmentGuide(.leading, computeValue: { d in if (abs(width - d.width) > g.size.width) { width = 0 @@ -101,12 +101,12 @@ private struct HeightReaderView: View { public extension FlowLayout where Trigger == Never? { init(mode: Mode, data: Data, - itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, + spacing: CGFloat = flowLayoutDefaultItemSpacing, @ViewBuilder content: @escaping (Data.Element) -> Content) { self.init(mode: mode, trigger: .constant(nil), data: data, - itemSpacing: itemSpacing, + spacing: spacing, content: content) } } @@ -188,7 +188,7 @@ public extension FlowLayout { @available(swift, obsoleted: 1.1.0, renamed: "attemptConnection") var viewMapping: (Data.Element) -> Content { content } - @available(swift, obsoleted: 1.1.0, renamed: "init(mode:trigger:data:itemSpacing:content:)") + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:trigger:data:spacing:content:)") init(mode: Mode, binding: Binding, items: Data, @@ -197,13 +197,13 @@ public extension FlowLayout { self.init(mode: mode, trigger: binding, data: items, - itemSpacing: itemSpacing, + spacing: itemSpacing, content: viewMapping) } } public extension FlowLayout where Trigger == Never? { - @available(swift, obsoleted: 1.1.0, renamed: "init(mode:data:itemSpacing:content:)") + @available(swift, obsoleted: 1.1.0, renamed: "init(mode:data:spacing:content:)") init(mode: Mode, items: Data, itemSpacing: CGFloat = flowLayoutDefaultItemSpacing, @@ -212,7 +212,7 @@ public extension FlowLayout where Trigger == Never? { mode: mode, trigger: .constant(nil), data: items, - itemSpacing: itemSpacing, + spacing: itemSpacing, content: viewMapping ) }