Skip to content

Commit abeefca

Browse files
authored
refactor: improvements for the FDC quickstart (#1679)
* refactor: remove actor biography * refactor: update rating to be out of 10, and limit chars * refactor: show movie name in the review card * refactor: handle movie clicks from profile screen * add movie clicks to author details and profile
1 parent 4f65921 commit abeefca

File tree

7 files changed

+76
-47
lines changed

7 files changed

+76
-47
lines changed

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,25 @@ class MainActivity : ComponentActivity() {
109109
}
110110
)
111111
}
112-
composable<ActorDetailRoute>() { ActorDetailScreen() }
112+
composable<ActorDetailRoute>() {
113+
ActorDetailScreen(
114+
onMovieClicked = { movieId ->
115+
navController.navigate(
116+
MovieDetailRoute(movieId),
117+
{ launchSingleTop = true }
118+
)
119+
}
120+
)
121+
}
113122
searchScreen()
114-
composable<ProfileRoute> { ProfileScreen() }
123+
composable<ProfileRoute> { ProfileScreen(
124+
onMovieClicked = { movieId ->
125+
navController.navigate(
126+
MovieDetailRoute(movieId),
127+
{ launchSingleTop = true }
128+
)
129+
}
130+
) }
115131
}
116132
}
117133
}

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/feature/actordetail/ActorDetailScreen.kt

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.google.firebase.example.dataconnect.feature.actordetail
22

3+
import androidx.compose.foundation.border
34
import androidx.compose.foundation.layout.Column
45
import androidx.compose.foundation.layout.Row
56
import androidx.compose.foundation.layout.Spacer
@@ -9,14 +10,17 @@ import androidx.compose.foundation.layout.height
910
import androidx.compose.foundation.layout.padding
1011
import androidx.compose.foundation.layout.width
1112
import androidx.compose.foundation.rememberScrollState
13+
import androidx.compose.foundation.shape.CircleShape
1214
import androidx.compose.foundation.verticalScroll
1315
import androidx.compose.material3.MaterialTheme
1416
import androidx.compose.material3.Scaffold
1517
import androidx.compose.material3.Text
1618
import androidx.compose.runtime.Composable
1719
import androidx.compose.runtime.collectAsState
1820
import androidx.compose.runtime.getValue
21+
import androidx.compose.ui.Alignment
1922
import androidx.compose.ui.Modifier
23+
import androidx.compose.ui.draw.clip
2024
import androidx.compose.ui.layout.ContentScale
2125
import androidx.compose.ui.res.stringResource
2226
import androidx.compose.ui.unit.dp
@@ -36,14 +40,13 @@ data class ActorDetailRoute(val actorId: String)
3640

3741
@Composable
3842
fun ActorDetailScreen(
39-
actorDetailViewModel: ActorDetailViewModel = viewModel()
43+
actorDetailViewModel: ActorDetailViewModel = viewModel(),
44+
onMovieClicked: (actorId: String) -> Unit
4045
) {
4146
val uiState by actorDetailViewModel.uiState.collectAsState()
4247
ActorDetailScreen(
4348
uiState = uiState,
44-
onMovieClicked = {
45-
// TODO
46-
}
49+
onMovieClicked = onMovieClicked
4750
)
4851
}
4952

@@ -92,38 +95,29 @@ fun ActorDetailScreen(
9295

9396
@Composable
9497
fun ActorInformation(
95-
modifier: Modifier = Modifier,
9698
actor: GetActorByIdQuery.Data.Actor?
9799
) {
98100
if (actor == null) {
99101
ErrorCard(stringResource(R.string.error_actor_not_found))
100102
} else {
101-
Column(
102-
modifier = modifier
103-
.padding(16.dp)
103+
Row(
104+
modifier = Modifier.padding(horizontal = 16.dp),
105+
verticalAlignment = Alignment.CenterVertically
104106
) {
107+
AsyncImage(
108+
model = actor.imageUrl,
109+
contentDescription = null,
110+
contentScale = ContentScale.Crop,
111+
modifier = Modifier
112+
.width(120.dp)
113+
.padding(vertical = 8.dp)
114+
.clip(CircleShape)
115+
)
116+
Spacer(modifier = Modifier.width(16.dp))
105117
Text(
106118
text = actor.name,
107119
style = MaterialTheme.typography.headlineLarge
108120
)
109-
Row {
110-
AsyncImage(
111-
model = actor.imageUrl,
112-
contentDescription = null,
113-
contentScale = ContentScale.Crop,
114-
modifier = Modifier
115-
.width(150.dp)
116-
.aspectRatio(9f / 16f)
117-
.padding(vertical = 8.dp)
118-
)
119-
// TODO(thatfiredev): Remove biography
120-
Text(
121-
text = stringResource(R.string.biography_not_available),
122-
modifier = Modifier
123-
.padding(horizontal = 16.dp)
124-
.fillMaxWidth()
125-
)
126-
}
127121
}
128122
}
129123
}

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/feature/moviedetail/MovieDetailViewModel.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class MovieDetailViewModel(
4545
_uiState.value = if (user == null) {
4646
MovieDetailUIState.Success(movie, isUserSignedIn = false)
4747
} else {
48-
4948
val isFavorite = moviesConnector.getIfFavoritedMovie.execute(
5049
movieId = UUID.fromString(movieId)
5150
).data.favorite_movie != null
@@ -92,7 +91,6 @@ class MovieDetailViewModel(
9291
rating = rating.roundToInt(),
9392
reviewText = text
9493
)
95-
// TODO(thatfiredev): should we have a way of only refetching the reviews?
9694
// Re-run the query to fetch movie
9795
fetchMovie()
9896
} catch (e: Exception) {

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/feature/moviedetail/UserReviews.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.compose.runtime.setValue
2020
import androidx.compose.ui.Alignment
2121
import androidx.compose.ui.Modifier
2222
import androidx.compose.ui.res.stringResource
23+
import androidx.compose.ui.text.style.TextAlign
2324
import androidx.compose.ui.unit.dp
2425
import com.google.firebase.dataconnect.movies.GetMovieByIdQuery
2526
import com.google.firebase.example.dataconnect.R
@@ -43,18 +44,25 @@ fun UserReviews(
4344
.padding(16.dp),
4445
horizontalAlignment = Alignment.CenterHorizontally
4546
) {
46-
var rating by remember { mutableFloatStateOf(3f) }
47+
var rating by remember { mutableFloatStateOf(5f) }
4748
Text("Rating: ${rating}")
4849
Slider(
4950
value = rating,
5051
onValueChange = { rating = Math.round(it).toFloat() },
51-
steps = 5,
52-
valueRange = 1f..5f
52+
steps = 10,
53+
valueRange = 1f..10f
5354
)
5455
TextField(
5556
value = reviewText,
56-
onValueChange = { reviewText = it },
57+
onValueChange = { if (it.length <= 280) reviewText = it },
5758
label = { Text(stringResource(R.string.hint_write_review)) },
59+
supportingText = {
60+
Text(
61+
"${reviewText.length} / 280",
62+
modifier = Modifier.fillMaxWidth(),
63+
textAlign = TextAlign.End
64+
)
65+
},
5866
modifier = Modifier.fillMaxWidth()
5967
)
6068

@@ -78,7 +86,7 @@ fun UserReviews(
7886
userName = it.user.username,
7987
date = it.reviewDate,
8088
rating = it.rating?.toDouble() ?: 0.0,
81-
text = it.reviewText ?: ""
89+
text = it.reviewText ?: "",
8290
)
8391
}
8492
}

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/feature/profile/ProfileScreen.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ object ProfileRoute
3636

3737
@Composable
3838
fun ProfileScreen(
39-
profileViewModel: ProfileViewModel = viewModel()
39+
profileViewModel: ProfileViewModel = viewModel(),
40+
onMovieClicked: (String) -> Unit,
4041
) {
4142
val uiState by profileViewModel.uiState.collectAsState()
4243
when (uiState) {
@@ -61,6 +62,7 @@ fun ProfileScreen(
6162
ui.username ?: "User",
6263
ui.reviews.orEmpty(),
6364
ui.favoriteMovies.orEmpty(),
65+
onMovieClicked = onMovieClicked,
6466
onSignOut = {
6567
profileViewModel.signOut()
6668
}
@@ -76,6 +78,7 @@ fun ProfileScreen(
7678
name: String,
7779
reviews: List<GetCurrentUserQuery.Data.User.ReviewsItem>,
7880
favoriteMovies: List<GetCurrentUserQuery.Data.User.FavoriteMoviesItem>,
81+
onMovieClicked: (String) -> Unit,
7982
onSignOut: () -> Unit
8083
) {
8184
val scrollState = rememberScrollState()
@@ -104,9 +107,7 @@ fun ProfileScreen(
104107
movies = favoriteMovies.mapNotNull {
105108
Movie(it.movie.id.toString(), it.movie.imageUrl, it.movie.title, it.movie.rating?.toFloat())
106109
},
107-
onMovieClicked = {
108-
// TODO
109-
}
110+
onMovieClicked = onMovieClicked
110111
)
111112
Spacer(modifier = Modifier.height(16.dp))
112113

@@ -140,7 +141,8 @@ fun ReviewsList(
140141
userName = userName,
141142
date = review.reviewDate,
142143
rating = review.rating?.toDouble() ?: 0.0,
143-
text = review.reviewText ?: ""
144+
text = review.reviewText ?: "",
145+
movieName = review.movie.title
144146
)
145147
}
146148
}

dataconnect/app/src/main/java/com/google/firebase/example/dataconnect/ui/components/ReviewCard.kt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ fun ReviewCard(
2929
userName: String,
3030
date: Date,
3131
rating: Double,
32-
text: String
32+
text: String,
33+
movieName: String? = null
3334
) {
3435
Card(
3536
modifier = Modifier
@@ -42,9 +43,13 @@ fun ReviewCard(
4243
.padding(16.dp)
4344
) {
4445
Text(
45-
text = userName,
46+
text = if (movieName != null) {
47+
userName + " on " + movieName
48+
} else {
49+
userName
50+
},
4651
fontWeight = FontWeight.Bold,
47-
style = MaterialTheme.typography.titleMedium
52+
style = MaterialTheme.typography.titleLarge
4853
)
4954
Row(
5055
modifier = Modifier.padding(bottom = 8.dp)
@@ -53,11 +58,18 @@ fun ReviewCard(
5358
text = SimpleDateFormat(
5459
"dd MMM, yyyy",
5560
Locale.getDefault()
56-
).format(date)
61+
).format(date),
62+
style = MaterialTheme.typography.titleMedium
5763
)
5864
Spacer(modifier = Modifier.width(8.dp))
59-
Text(text = "Rating: ")
60-
Text(text = "$rating")
65+
Text(
66+
text = "Rating: ",
67+
style = MaterialTheme.typography.titleMedium
68+
)
69+
Text(
70+
text = "$rating",
71+
style = MaterialTheme.typography.titleMedium
72+
)
6173
}
6274
Text(
6375
text = text,

dataconnect/app/src/main/res/values/strings.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
<!-- Actor Detail Screen -->
3434
<string name="error_actor_not_found">Couldn\'t find actor in the database</string>
35-
<string name="biography_not_available">Biography not available</string>
3635
<string name="title_main_roles">Main Roles</string>
3736
<string name="title_supporting_roles">Supporting Roles</string>
3837

0 commit comments

Comments
 (0)