diff --git a/app/src/main/java/com/cornellappdev/score/MainActivity.kt b/app/src/main/java/com/cornellappdev/score/MainActivity.kt
index 512793e..aaf0da5 100644
--- a/app/src/main/java/com/cornellappdev/score/MainActivity.kt
+++ b/app/src/main/java/com/cornellappdev/score/MainActivity.kt
@@ -5,11 +5,12 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import com.cornellappdev.score.nav.root.RootNavigation
+import com.cornellappdev.score.screen.OnboardingProfileSelectScreen
import com.cornellappdev.score.screen.OnboardingScreen
import com.google.firebase.Firebase
import com.google.firebase.analytics.FirebaseAnalytics
@@ -18,6 +19,7 @@ import dagger.hilt.android.AndroidEntryPoint
private const val APP_PREFERENCES = "score_app_preferences"
private const val KEY_ONBOARDING_COMPLETED = "onboarding_completed"
+private const val KEY_ONBOARDING_PROFILE_PICTURE = "onboarding_profile_picture"
private lateinit var firebaseAnalytics: FirebaseAnalytics
@@ -31,8 +33,8 @@ class MainActivity : AppCompatActivity() {
val onboardingCompleted = preferences.getBoolean(KEY_ONBOARDING_COMPLETED, false)
setContent {
- var showOnboarding by rememberSaveable {
- mutableStateOf(!onboardingCompleted)
+ var onboardingStep by rememberSaveable {
+ mutableIntStateOf(if (onboardingCompleted) 2 else 0)
}
val completeOnboarding = remember {
@@ -40,18 +42,25 @@ class MainActivity : AppCompatActivity() {
preferences.edit()
.putBoolean(KEY_ONBOARDING_COMPLETED, true)
.apply()
- showOnboarding = false
+ onboardingStep = 2
}
}
- if (showOnboarding) {
- OnboardingScreen(
- onSignUp = completeOnboarding,
+ when (onboardingStep) {
+ 0 -> OnboardingScreen(
+ onSignUp = { onboardingStep = 1 },
onLogIn = completeOnboarding,
onLater = completeOnboarding
)
- } else {
- RootNavigation()
+ 1 -> OnboardingProfileSelectScreen(
+ onNext = { selectedPicture ->
+ preferences.edit()
+ .putString(KEY_ONBOARDING_PROFILE_PICTURE, selectedPicture.name)
+ .apply()
+ completeOnboarding()
+ }
+ )
+ else -> RootNavigation()
}
}
diff --git a/app/src/main/java/com/cornellappdev/score/screen/EditProfileScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/EditProfileScreen.kt
index f81b4b0..4c93ff0 100644
--- a/app/src/main/java/com/cornellappdev/score/screen/EditProfileScreen.kt
+++ b/app/src/main/java/com/cornellappdev/score/screen/EditProfileScreen.kt
@@ -4,23 +4,14 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.selection.selectable
-import androidx.compose.foundation.selection.selectableGroup
-import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -30,11 +21,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.cornellappdev.score.R
@@ -89,31 +78,10 @@ fun EditProfileScreen(
modifier = Modifier.padding(horizontal = 24.dp)
)
Spacer(Modifier.height(24.dp))
- Row(
- modifier = Modifier.widthIn(max = 393.dp).fillMaxWidth()
- .padding(horizontal = 24.dp).selectableGroup(),
- horizontalArrangement = Arrangement.spacedBy(20.dp)
- ) {
- ProfilePicture.entries.forEach { picture ->
- val selected = picture == selectedPicture
- Box(
- modifier = Modifier.weight(1f).aspectRatio(1f).clip(CircleShape)
- .selectable(selected = selected, role = Role.RadioButton,
- onClick = { onPictureSelected(picture) }),
- contentAlignment = Alignment.Center
- ) {
- Image(
- painter = painterResource(picture.drawable),
- contentDescription = stringResource(picture.label),
- modifier = Modifier.fillMaxSize()
- )
- if (selected) {
- Box(Modifier.fillMaxSize().background(Color.White.copy(alpha = 0.6f), CircleShape)
- .border(3.dp, Color(0xFF4DBB35), CircleShape))
- }
- }
- }
- }
+ ProfilePictureOptions(
+ selectedPicture = selectedPicture,
+ onPictureSelected = onPictureSelected
+ )
}
}
}
diff --git a/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt
new file mode 100644
index 0000000..1dfa4a7
--- /dev/null
+++ b/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt
@@ -0,0 +1,170 @@
+package com.cornellappdev.score.screen
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.cornellappdev.score.R
+import com.cornellappdev.score.theme.CrimsonPrimary
+import com.cornellappdev.score.theme.Style
+
+@Composable
+fun OnboardingProfileSelectScreen(
+ onNext: (ProfilePicture) -> Unit,
+ modifier: Modifier = Modifier,
+ displayName: String? = null
+) {
+ var selectedPicture by rememberSaveable { mutableStateOf(ProfilePicture.TENNIS) }
+ val name = displayName ?: stringResource(R.string.onboarding_default_name)
+
+ BoxWithConstraints(
+ modifier = modifier
+ .fillMaxSize()
+ .background(Color.White)
+ ) {
+ val designScale = minOf(maxWidth.value / 393f, maxHeight.value / 852f)
+ val designDp: (Float) -> Dp = { (it * designScale).dp }
+
+ Column(modifier = Modifier.fillMaxSize()) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = designDp(79f)),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(
+ text = stringResource(R.string.edit_profile),
+ style = Style.heading1,
+ color = Color(0xFF333333)
+ )
+ Spacer(Modifier.height(designDp(4f)))
+ Text(
+ text = stringResource(R.string.onboarding_profile_subtitle),
+ style = Style.bodyMedium,
+ color = Color(0xFF333333)
+ )
+
+ Spacer(Modifier.height(designDp(47f)))
+ Image(
+ painter = painterResource(selectedPicture.drawable),
+ contentDescription = stringResource(
+ R.string.selected_profile_picture,
+ stringResource(selectedPicture.label)
+ ),
+ modifier = Modifier.size(designDp(100f))
+ )
+ Spacer(Modifier.height(designDp(16f)))
+ Text(
+ text = name,
+ style = Style.bodyMedium,
+ color = Color.Black
+ )
+
+ Spacer(Modifier.height(designDp(60f)))
+ Text(
+ text = stringResource(R.string.onboarding_select_profile_picture),
+ style = Style.metricMedium,
+ color = Color.Black,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 24.dp)
+ )
+ Spacer(Modifier.height(designDp(24f)))
+ ProfilePictureOptions(
+ selectedPicture = selectedPicture,
+ onPictureSelected = { selectedPicture = it },
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+
+ Spacer(Modifier.weight(1f))
+ OnboardingProfileFooter(
+ onNext = { onNext(selectedPicture) },
+ designDp = designDp
+ )
+ }
+ }
+}
+
+@Composable
+private fun OnboardingProfileFooter(
+ onNext: () -> Unit,
+ designDp: (Float) -> Dp
+) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(
+ start = 24.dp,
+ end = 24.dp,
+ top = designDp(24f),
+ bottom = designDp(60f)
+ ),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Button(
+ onClick = onNext,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(designDp(48f)),
+ shape = CircleShape,
+ colors = ButtonDefaults.buttonColors(
+ containerColor = CrimsonPrimary,
+ contentColor = Color.White
+ )
+ ) {
+ Text(
+ text = stringResource(R.string.next),
+ style = Style.heading3,
+ color = Color.White
+ )
+ }
+
+ Spacer(Modifier.height(designDp(16f)))
+ RowProgressDots()
+ }
+}
+
+@Composable
+private fun RowProgressDots() {
+ androidx.compose.foundation.layout.Row(
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Box(Modifier.size(8.dp).background(CrimsonPrimary, CircleShape))
+ Box(Modifier.size(8.dp).background(Color(0xFFEAEAEA), CircleShape))
+ }
+}
+
+@Preview(showBackground = true, widthDp = 393, heightDp = 852)
+@Composable
+private fun OnboardingProfileSelectScreenPreview() {
+ OnboardingProfileSelectScreen(onNext = {})
+}
diff --git a/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt b/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt
new file mode 100644
index 0000000..ed5fcc2
--- /dev/null
+++ b/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt
@@ -0,0 +1,87 @@
+package com.cornellappdev.score.screen
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.selection.selectable
+import androidx.compose.foundation.selection.selectableGroup
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.dp
+import com.cornellappdev.score.components.ScorePreview
+
+/**
+ * Shared profile picture choices used by profile editing and first-time onboarding.
+ */
+@Composable
+fun ProfilePictureOptions(
+ selectedPicture: ProfilePicture,
+ onPictureSelected: (ProfilePicture) -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Row(
+ modifier = modifier
+ .widthIn(max = 393.dp)
+ .fillMaxWidth()
+ .padding(horizontal = 24.dp)
+ .selectableGroup(),
+ horizontalArrangement = Arrangement.SpaceBetween
+ ) {
+ ProfilePicture.entries.forEach { picture ->
+ val selected = picture == selectedPicture
+ Box(
+ modifier = Modifier
+ .size(70.dp)
+ .clip(CircleShape)
+ .selectable(
+ selected = selected,
+ role = Role.RadioButton,
+ onClick = { onPictureSelected(picture) }
+ ),
+ contentAlignment = Alignment.Center
+ ) {
+ Image(
+ painter = painterResource(picture.drawable),
+ contentDescription = stringResource(picture.label),
+ modifier = Modifier.fillMaxSize()
+ )
+ if (selected) {
+ Box(
+ Modifier
+ .fillMaxSize()
+ .background(Color.White.copy(alpha = 0.6f), CircleShape)
+ .border(3.dp, Color(0xFF55B63C), CircleShape)
+ )
+ }
+ }
+ }
+ }
+}
+
+@Preview(showBackground = true, widthDp = 393)
+@Composable
+private fun ProfilePictureOptionsPreview() {
+ ScorePreview(backgroundColor = Color.White) {
+ ProfilePictureOptions(
+ selectedPicture = ProfilePicture.TENNIS,
+ onPictureSelected = {},
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c264cc3..474c141 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -7,4 +7,8 @@
Tennis
Baseball
Soccer
+ Claire Yu
+ You can change this later in the profile page.
+ Select profile picture:
+ Next
\ No newline at end of file