3
3
// License, v. 2.0. If a copy of the MPL was not distributed with this
4
4
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
6
- import SwiftUI
7
6
import DesignSystem
7
+ import SwiftUI
8
8
9
9
@available ( iOS 16 , * )
10
10
struct WrappingHStack : Layout {
@@ -15,52 +15,62 @@ struct WrappingHStack: Layout {
15
15
guard !subviews. isEmpty else {
16
16
return . zero
17
17
}
18
-
18
+
19
19
let height = subviews. map { $0. sizeThatFits ( proposal) . height } . max ( ) ?? 0.0
20
-
20
+
21
21
var rowWidths = [ CGFloat] ( )
22
22
var currentRowWidth : CGFloat = 0
23
23
subviews. forEach { subview in
24
- if currentRowWidth + hSpacing + subview. sizeThatFits ( proposal) . width >= proposal. width ?? 0.0 {
24
+ if currentRowWidth + hSpacing + subview. sizeThatFits ( proposal) . width >= proposal. width ?? 0.0
25
+ {
25
26
rowWidths. append ( currentRowWidth)
26
27
currentRowWidth = subview. sizeThatFits ( proposal) . width
27
28
} else {
28
29
currentRowWidth += hSpacing + subview. sizeThatFits ( proposal) . width
29
30
}
30
31
}
31
-
32
+
32
33
rowWidths. append ( currentRowWidth)
33
-
34
+
34
35
let rowCount = CGFloat ( rowWidths. count)
35
- return CGSize ( width: max ( rowWidths. max ( ) ?? 0.0 , proposal. width ?? 0.0 ) , height: rowCount * height + ( rowCount - 1 ) * vSpacing)
36
+ return CGSize (
37
+ width: max ( rowWidths. max ( ) ?? 0.0 , proposal. width ?? 0.0 ) ,
38
+ height: rowCount * height + ( rowCount - 1 ) * vSpacing
39
+ )
36
40
}
37
41
38
- func placeSubviews( in bounds: CGRect , proposal: ProposedViewSize , subviews: Subviews , cache: inout ( ) ) {
42
+ func placeSubviews(
43
+ in bounds: CGRect ,
44
+ proposal: ProposedViewSize ,
45
+ subviews: Subviews ,
46
+ cache: inout ( )
47
+ ) {
39
48
let height = subviews. map { $0. dimensions ( in: proposal) . height } . max ( ) ?? 0.0
40
-
49
+
41
50
guard !subviews. isEmpty else {
42
51
return
43
52
}
44
-
53
+
45
54
var x = bounds. minX
46
- var y = height / 2.0 + bounds. minY
47
-
55
+ var y = height + bounds. minY
56
+
48
57
subviews. forEach { subview in
49
58
x += subview. dimensions ( in: proposal) . width / 2.0
50
-
59
+
51
60
if x + subview. dimensions ( in: proposal) . width / 2.0 > bounds. maxX {
52
61
x = bounds. minX + subview. dimensions ( in: proposal) . width / 2.0
53
- y += height + vSpacing
62
+ y += subview . dimensions ( in : proposal ) . height + vSpacing
54
63
}
55
-
56
- subview. place ( at: CGPoint ( x: x, y: y) ,
57
- anchor: . center,
58
- proposal: ProposedViewSize (
59
- width: subview. dimensions ( in: proposal) . width,
60
- height: subview. dimensions ( in: proposal) . height
61
- )
64
+
65
+ subview. place (
66
+ at: CGPoint ( x: x, y: y) ,
67
+ anchor: . init( x: 0.5 , y: 1.0 ) ,
68
+ proposal: ProposedViewSize (
69
+ width: subview. dimensions ( in: proposal) . width,
70
+ height: subview. dimensions ( in: proposal) . height
71
+ )
62
72
)
63
-
73
+
64
74
x += subview. dimensions ( in: proposal) . width / 2.0 + hSpacing
65
75
}
66
76
}
@@ -69,24 +79,30 @@ struct WrappingHStack: Layout {
69
79
@available ( iOS, introduced: 15.0 , obsoleted: 16.0 )
70
80
struct WrappingHStackOld < Model, V> : View where Model: Hashable , V: View {
71
81
typealias ViewGenerator = ( Model ) -> V
72
-
82
+
73
83
var models : [ Model ]
74
84
var hSpacing : CGFloat
75
85
var vSpacing : CGFloat
76
86
var viewGenerator : ViewGenerator
77
87
var proxy : GeometryProxy
78
88
79
89
@State private var viewHeight = CGFloat . infinity
80
-
90
+
81
91
init ( geometry: GeometryProxy , models: [ Model ] , viewGenerator: @escaping ViewGenerator ) {
82
92
self . models = models
83
93
self . viewGenerator = viewGenerator
84
94
self . hSpacing = 2.0
85
95
self . vSpacing = 2.0
86
96
self . proxy = geometry
87
97
}
88
-
89
- init ( geometry: GeometryProxy , models: [ Model ] , hSpacing: Float , vSpacing: Float , viewGenerator: @escaping ViewGenerator ) {
98
+
99
+ init (
100
+ geometry: GeometryProxy ,
101
+ models: [ Model ] ,
102
+ hSpacing: Float ,
103
+ vSpacing: Float ,
104
+ viewGenerator: @escaping ViewGenerator
105
+ ) {
90
106
self . models = models
91
107
self . viewGenerator = viewGenerator
92
108
self . hSpacing = CGFloat ( hSpacing)
@@ -108,25 +124,29 @@ struct WrappingHStackOld<Model, V>: View where Model: Hashable, V: View {
108
124
ZStack ( alignment: . topLeading) {
109
125
ForEach ( models, id: \. self) { model in
110
126
viewGenerator ( model)
111
- . padding ( . horizontal, hSpacing)
112
- . padding ( . vertical, vSpacing)
113
- . alignmentGuide ( . leading, computeValue: { dimension in
114
- if abs ( width - dimension. width) > geometry. size. width {
115
- width = 0.0
116
- height -= dimension. height
127
+ . alignmentGuide (
128
+ . leading,
129
+ computeValue: { dimension in
130
+ if abs ( width - dimension. width) > geometry. size. width {
131
+ width = 0.0
132
+ height -= dimension. height + vSpacing
133
+ }
134
+
135
+ let result = width
136
+ width = model == models. last! ? 0.0 : width - dimension. width - hSpacing
137
+ return result
117
138
}
118
-
119
- let result = width
120
- width = model == models . last! ? 0.0 : width - dimension . width
121
- return result
122
- } )
123
- . alignmentGuide ( . top , computeValue : { dimension in
124
- let result = height
125
- if model == models . last! {
126
- height = 0.0
139
+ )
140
+ . alignmentGuide (
141
+ . top ,
142
+ computeValue : { dimension in
143
+ let result = height + dimension . height
144
+ if model == models . last! {
145
+ height = 0.0
146
+ }
147
+ return result
127
148
}
128
- return result
129
- } )
149
+ )
130
150
}
131
151
}
132
152
}
@@ -136,7 +156,7 @@ struct AIChatSuggestionsButton: View {
136
156
var title : String
137
157
var isLoading : Bool
138
158
var onSuggestionPressed : ( ( ) -> Void ) ?
139
-
159
+
140
160
var body : some View {
141
161
Button {
142
162
onSuggestionPressed ? ( )
@@ -147,7 +167,7 @@ struct AIChatSuggestionsButton: View {
147
167
. foregroundColor ( Color ( braveSystemName: . textInteractive) )
148
168
. multilineTextAlignment ( . leading)
149
169
. padding ( 12.0 )
150
-
170
+
151
171
if isLoading {
152
172
ProgressView ( )
153
173
. tint ( Color ( braveSystemName: . textInteractive) )
@@ -168,8 +188,12 @@ struct AIChatSuggestionsView: View {
168
188
var suggestions : [ String ]
169
189
var onSuggestionPressed : ( ( String ) -> Void ) ?
170
190
private var proxy : GeometryProxy
171
-
172
- init ( geometry: GeometryProxy , suggestions: [ String ] , onSuggestionPressed: ( ( String ) -> Void ) ? = nil ) {
191
+
192
+ init (
193
+ geometry: GeometryProxy ,
194
+ suggestions: [ String ] ,
195
+ onSuggestionPressed: ( ( String ) -> Void ) ? = nil
196
+ ) {
173
197
self . suggestions = suggestions
174
198
self . proxy = geometry
175
199
self . onSuggestionPressed = onSuggestionPressed
@@ -201,10 +225,13 @@ struct AIChatSuggestionsView_Preview: PreviewProvider {
201
225
GeometryReader { geometry in
202
226
AIChatSuggestionsView (
203
227
geometry: geometry,
204
- suggestions: [ " What Bluetooth version does it use? " ,
205
- " Summarize this page? " ,
206
- " What is Leo? " ,
207
- " What can the Leo assistant do for me? " ] )
228
+ suggestions: [
229
+ " What Bluetooth version does it use? " ,
230
+ " Summarize this page? " ,
231
+ " What is Leo? " ,
232
+ " What can the Leo assistant do for me? " ,
233
+ ]
234
+ )
208
235
. previewLayout ( . sizeThatFits)
209
236
}
210
237
}
0 commit comments