Skip to content

Commit 9d203fb

Browse files
committed
✨ Favourite handling
Signed-off-by: Peter Friese <[email protected]>
1 parent 4baf3f9 commit 9d203fb

File tree

4 files changed

+123
-60
lines changed

4 files changed

+123
-60
lines changed

Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/Features/Details/MovieCardView.swift

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,27 @@ import FirebaseDataConnect
2323
import FriendlyFlixSDK
2424

2525
struct MovieCardView: View {
26-
public var showDetails: Bool = false
27-
public var movie: Movie
28-
26+
@Environment(\.dismiss) private var dismiss
2927
private var connector = DataConnect.friendlyFlixConnector
3028

29+
private var showDetails: Bool = false
30+
private var movie: Movie
31+
3132
public init(showDetails: Bool, movie: Movie) {
3233
self.showDetails = showDetails
3334
self.movie = movie
3435

3536
isFavouriteRef = connector.getIfFavoritedMovieQuery.ref(movieId: movie.id)
3637
}
3738

39+
// MARK: - Favourite handling
40+
3841
private let isFavouriteRef: QueryRefObservation<GetIfFavoritedMovieQuery.Data, GetIfFavoritedMovieQuery.Variables>
3942
private var isFavourite: Bool {
4043
isFavouriteRef.data?.favorite_movie?.movieId != nil
4144
}
4245

43-
func toggleFavourite() {
46+
private func toggleFavourite() {
4447
Task {
4548
if isFavourite {
4649
let _ = try await connector.deleteFavoritedMovieMutation.execute(movieId: movie.id)
@@ -52,7 +55,6 @@ struct MovieCardView: View {
5255
}
5356
}
5457
}
55-
5658
}
5759

5860
extension MovieCardView {
@@ -101,17 +103,33 @@ extension MovieCardView {
101103
.background(.thinMaterial)
102104
}
103105
} details: {
104-
Text(movie.title)
105-
Button {
106-
toggleFavourite()
107-
} label: {
108-
Label(
109-
isFavourite ? "Remove from watch list" : "Add to watch list",
110-
systemImage: isFavourite ? "heart.slash" :"heart"
111-
)
106+
MovieDetailsView(movie: movie)
107+
}
108+
.toolbar {
109+
ToolbarItem {
110+
Button {
111+
toggleFavourite()
112+
} label: {
113+
Image(systemName: isFavourite ? "heart.fill" : "heart")
114+
.font(.headline)
115+
.foregroundColor(.white)
116+
.frame(width: 30, height: 30)
117+
.background(Color.black.opacity(0.6))
118+
.clipShape(Circle())
119+
}
120+
}
121+
ToolbarItem {
122+
Button {
123+
dismiss()
124+
} label: {
125+
Image(systemName: "xmark")
126+
.font(.headline)
127+
.foregroundColor(.white)
128+
.frame(width: 30, height: 30)
129+
.background(Color.black.opacity(0.6))
130+
.clipShape(Circle())
131+
}
112132
}
113-
114-
// MovieDetailsView(movie: movie)
115133
}
116134
.task {
117135
do {
@@ -124,6 +142,6 @@ extension MovieCardView {
124142
}
125143
}
126144

127-
// #Preview {
128-
// MovieCardView(showDetails: true, gradientConfiguration: GradienConfiguration.sample)
129-
// }
145+
#Preview {
146+
MovieCardView(showDetails: true, movie: Movie.mock)
147+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright © 2024 Google LLC. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import FirebaseDataConnect
16+
import FriendlyFlixSDK
17+
import SwiftUI
18+
19+
struct MovieDetailsView: View {
20+
var movie: Movie
21+
22+
var body: some View {
23+
VStack(alignment: .leading, spacing: 10) {
24+
// description
25+
VStack(alignment: .leading, spacing: 10) {
26+
Text("About")
27+
.font(.title2)
28+
.bold()
29+
.unredacted()
30+
31+
Text(movie.description)
32+
.font(.body)
33+
HStack {
34+
Spacer()
35+
}
36+
}
37+
}
38+
.padding()
39+
}
40+
}
41+
42+
#Preview {
43+
MovieDetailsView(movie: Movie.mock)
44+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright © 2024 Google LLC. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import Foundation
16+
17+
extension String {
18+
static func placeholder(length: Int) -> String {
19+
String(Array(repeating: "X", count: length))
20+
}
21+
}

Examples/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/Views/CardView.swift

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,10 @@ struct CardView<Hero: View, Title: View, Details: View>: View {
4343
self.details = details
4444
}
4545

46-
@ViewBuilder
47-
var dismissButton: some View {
48-
if showDetails {
49-
HStack {
50-
Spacer()
51-
Button {
52-
dismiss()
53-
} label: {
54-
Image(systemName: "xmark")
55-
.font(.headline)
56-
.foregroundColor(.white)
57-
.frame(width: 30, height: 30)
58-
.background(Color.black.opacity(0.6))
59-
.clipShape(Circle())
60-
}
61-
.padding([.top, .trailing], 30)
62-
}
63-
} else {
64-
EmptyView()
65-
}
66-
}
67-
6846
var cardView: some View {
6947
VStack(spacing: 0) {
7048
ZStack(alignment: .topLeading) {
7149
hero
72-
dismissButton
7350
heroTitle()
7451
}
7552
.clipShape(
@@ -105,6 +82,7 @@ struct CardView<Hero: View, Title: View, Details: View>: View {
10582
.statusBarHidden()
10683
}
10784
.ignoresSafeArea()
85+
10886
// Start: drag down to pop back
10987
.background(Color(UIColor.secondarySystemBackground))
11088
.scrollIndicators(scaleFactor < 1 ? .hidden : .automatic, axes: .vertical)
@@ -135,30 +113,32 @@ struct CardView<Hero: View, Title: View, Details: View>: View {
135113
}
136114

137115
#Preview {
138-
CardView(showDetails: true) {
139-
GradientView(configuration: GradienConfiguration.sample)
140-
.frame(height: 450)
141-
} heroTitle: {
142-
VStack(alignment: .leading) {
143-
Spacer()
144-
Text("Here be titles")
145-
.font(.title)
146-
Text("And subtitles")
147-
.font(.title3)
148-
}
149-
.foregroundColor(Color(UIColor.systemGroupedBackground))
150-
.padding()
151-
} details: {
152-
VStack {
153-
Text(
116+
NavigationStack {
117+
CardView(showDetails: true) {
118+
GradientView(configuration: GradienConfiguration.sample)
119+
.frame(height: 450)
120+
} heroTitle: {
121+
VStack(alignment: .leading) {
122+
Spacer()
123+
Text("Here be titles")
124+
.font(.title)
125+
Text("And subtitles")
126+
.font(.title3)
127+
}
128+
.foregroundColor(Color(UIColor.systemGroupedBackground))
129+
.padding()
130+
} details: {
131+
VStack {
132+
Text(
154133
"""
155134
Amet culpa excepteur sit ad tempor minim aute anim nisi voluptate do. Exercitation nisi adipisicing esse officia sit ullamco.
156135
Tempor ullamco irure proident cupidatat non Lorem ut voluptate est ad in deserunt esse velit exercitation. Tempor voluptate ex aute id.
157136
Fugiat in minim labore minim duis et duis eiusmod ullamco eiusmod minim deserunt voluptate.
158137
"""
159-
)
160-
.font(.body)
161-
.padding()
138+
)
139+
.font(.body)
140+
.padding()
141+
}
162142
}
163143
}
164144
}

0 commit comments

Comments
 (0)