@@ -10,7 +10,7 @@ import SwiftUI
10
10
struct DetailsView : View {
11
11
private enum Constants {
12
12
static let chipSpacing : CGFloat = 8
13
- static let closeButtonSize : CGFloat = 44
13
+ static let backButtonSize : CGFloat = 44
14
14
static let horizontalPadding : CGFloat = 16
15
15
static let imageCornerRadius : CGFloat = 24
16
16
static let imageHeight : CGFloat = 200
@@ -19,7 +19,7 @@ struct DetailsView: View {
19
19
enum Icons {
20
20
static let area : String = " globe "
21
21
static let category : String = " square.grid.2x2 "
22
- static let close : String = " xmark "
22
+ static let back : String = " arrow.backward "
23
23
static let youtube : String = " play.rectangle.fill "
24
24
}
25
25
@@ -31,45 +31,35 @@ struct DetailsView: View {
31
31
}
32
32
33
33
@ObservedObject var viewModel : DetailsViewModel
34
- let onClose : ( ( ) -> Void ) ?
35
- let namespace : Namespace . ID
34
+ @Environment ( \. dismiss) private var dismiss
36
35
37
36
var body : some View {
38
- Group {
37
+ ZStack {
39
38
ScrollView {
40
39
VStack ( alignment: . leading, spacing: Constants . spacing) {
41
- VerticalItemView (
42
- viewModel: viewModel. verticalItemViewModel,
43
- namespace: namespace
44
- )
45
- . matchedGeometryEffect (
46
- id: MatchedGeometryEffectIdentifier ( . info, for: viewModel. id) ,
47
- in: namespace
48
- )
40
+ VerticalItemView ( viewModel: viewModel. verticalItemViewModel)
49
41
makeTagsChipsScrollView ( )
50
42
ingredientsSection
51
43
instructionsSection
52
44
}
45
+ . background ( Color ( . systemBackground) )
53
46
}
54
47
. ignoresSafeArea ( edges: . top)
48
+ . safeAreaInset ( edge: . top) {
49
+ HStack {
50
+ makeBackButton ( )
51
+ Spacer ( )
52
+ makeLikeButton ( )
53
+ }
54
+ . padding ( . horizontal, Constants . spacing)
55
+ . padding ( . vertical, Constants . spacing)
56
+ }
55
57
}
58
+ . navigationBarHidden ( true )
56
59
. background ( Color ( . systemBackground) )
57
- . onFirstAppear {
60
+ . onAppear {
58
61
viewModel. fetchMeal ( )
59
62
}
60
- . overlay (
61
- HStack ( alignment: . top, spacing: . zero) {
62
- makeLikeButton ( )
63
- Spacer ( )
64
- makeCloseButton ( )
65
- }
66
- . padding ( . horizontal, Constants . spacing)
67
- . padding ( . top, Constants . spacing)
68
- . transaction { transaction in
69
- transaction. animation = nil
70
- } ,
71
- alignment: . top
72
- )
73
63
}
74
64
}
75
65
@@ -95,7 +85,6 @@ private extension DetailsView {
95
85
Text ( Constants . Title. ingredients)
96
86
. font ( . headline)
97
87
. padding ( . top)
98
-
99
88
ForEach ( viewModel. ingredients, id: \. self) { ingredient in
100
89
HStack {
101
90
Text ( ingredient. name)
@@ -117,6 +106,9 @@ private extension DetailsView {
117
106
if let instructions = viewModel. instructions {
118
107
VStack {
119
108
makeInstructionsContent ( instructions: instructions)
109
+ if let url = viewModel. youtubeURL {
110
+ makeYoutubeLink ( url: url)
111
+ }
120
112
}
121
113
. padding ( Constants . spacing)
122
114
. frame ( maxWidth: . infinity)
@@ -125,22 +117,26 @@ private extension DetailsView {
125
117
}
126
118
127
119
@ViewBuilder
128
- func makeCloseButton ( ) -> some View {
129
- if !viewModel . isCloseButtonHidden {
130
- Button ( action : { onClose ? ( ) } ) {
131
- ZStack {
132
- Circle ( )
133
- . fill ( Color . black . opacity ( 0.3 ) )
134
- . shadow ( color: Color . black. opacity ( 0.1 ) , radius : 4 , x : 0 , y : 2 )
135
-
136
- Image ( systemName : Constants . Icons . close )
137
- . font ( . title )
138
- . symbolVariant ( viewModel . isLiked ? . fill : . none )
139
- . padding ( 12 )
140
- . foregroundColor ( . white )
141
- }
142
- . frame ( width : Constants . closeButtonSize , height : Constants . closeButtonSize )
120
+ func makeBackButton ( ) -> some View {
121
+ Button ( action : { dismiss ( ) } ) {
122
+ ZStack {
123
+ Circle ( )
124
+ . fill ( Color . black . opacity ( 0.3 ) )
125
+ . shadow (
126
+ color: Color . black. opacity ( 0.1 ) ,
127
+ radius : 4 ,
128
+ x : . zero ,
129
+ y : 2
130
+ )
131
+ Image ( systemName : Constants . Icons . back )
132
+ . font ( . title )
133
+ . padding ( 12 )
134
+ . foregroundColor ( . white )
143
135
}
136
+ . frame (
137
+ width: Constants . backButtonSize,
138
+ height: Constants . backButtonSize
139
+ )
144
140
}
145
141
}
146
142
@@ -160,19 +156,13 @@ private extension DetailsView {
160
156
VStack ( alignment: . leading, spacing: Constants . spacing) {
161
157
Text ( Constants . Title. instructions)
162
158
. font ( . headline)
163
- . frame ( maxWidth: . infinity, alignment: . leading)
164
-
159
+ . frame ( alignment: . leading)
165
160
Text ( instructions)
166
161
. font ( . body)
167
162
. multilineTextAlignment ( . leading)
168
- . frame ( maxWidth: . infinity, alignment: . leading)
169
-
170
- if let url = viewModel. youtubeURL {
171
- makeYoutubeLink ( url: url)
172
- }
163
+ . frame ( alignment: . leading)
173
164
}
174
165
. padding ( Constants . spacing)
175
- . frame ( maxWidth: . infinity)
176
166
. background ( Color . secondary. opacity ( 0.1 ) )
177
167
. cornerRadius ( Constants . spacing)
178
168
}
@@ -185,10 +175,9 @@ private extension DetailsView {
185
175
Text ( Constants . Title. youtube)
186
176
. bold ( )
187
177
}
188
- . frame ( maxWidth: . infinity)
189
178
. padding ( Constants . spacing)
190
- . foregroundColor ( . accent )
191
- . background ( Color . white )
179
+ . foregroundColor ( . white )
180
+ . background ( Color . accentColor )
192
181
. cornerRadius ( Constants . spacing)
193
182
}
194
183
}
@@ -197,7 +186,6 @@ private extension DetailsView {
197
186
// MARK: - Preview
198
187
199
188
#Preview( " Meal Details " ) {
200
- @Previewable @Namespace var namespace
201
189
let requester = APIRequester ( )
202
190
let mealsService = MealsService ( requester: requester)
203
191
let favoritesManager = FavoritesManager ( store: UserDefaults . standard)
@@ -228,9 +216,7 @@ private extension DetailsView {
228
216
youtubeURL: URL ( string: " example.com " ) ,
229
217
favoritesManager: favoritesManager,
230
218
mealsService: mealsService
231
- ) ,
232
- onClose: nil ,
233
- namespace: namespace
219
+ )
234
220
)
235
221
}
236
222
}
0 commit comments