Conversation
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/GoalsPromptScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/GoalsPromptScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/GoalsPromptScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/GoalsPromptViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/GoalsPromptViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/GoalsPromptViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/GoalsPromptViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/SignInPromptScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/GoalsPromptScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/GoalsPromptScreen.kt
Outdated
Show resolved
Hide resolved
|
I took account of your changes to reuse an old screen which I did. I was successfully able to add the networking logic to enable a user to set a goal during the onboarding process, which I tested using my own account. Also removed some unused imports and deleted unused files. |
There was a problem hiding this comment.
Pull request overview
This PR extends the onboarding flow to include a goals (workout days/week) step, persists that goal/skip choice during user creation, and adds GraphQL support for login + goal setting.
Changes:
- Add a Goals onboarding route/screen and wire Profile Creation to navigate into it.
- Update onboarding ViewModel + repository to pass/store “skip goal” + goal value, login the user, and call
SetWorkoutGoals. - Add new DataStore keys and update GraphQL operations/schema accordingly.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt |
Adds goal/skip state and onboarding navigation/create-user wiring |
app/src/main/java/com/cornellappdev/uplift/ui/screens/reminders/WorkoutReminderScreen.kt |
Introduces onboarding/settings wrappers and refactors core screen structure |
app/src/main/java/com/cornellappdev/uplift/ui/screens/onboarding/ProfileCreationScreen.kt |
Routes “Get started” to the goals onboarding step |
app/src/main/java/com/cornellappdev/uplift/ui/MainNavigationWrapper.kt |
Adds GoalsOnboarding destination to root navigation |
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt |
Expands createUser to login, store tokens, and set workout goal |
app/src/main/java/com/cornellappdev/uplift/data/repositories/DatastoreRepository.kt |
Adds DataStore keys for goal + tokens |
app/src/main/graphql/User.graphql |
Updates SetWorkoutGoals signature and adds LoginUser/DeleteUser mutations |
app/src/main/graphql/schema.graphqls |
Updates schema types/fields to match new backend expectations |
app/build.gradle |
Flips ONBOARDING_FLAG for debug build type |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/reminders/WorkoutReminderScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/reminders/WorkoutReminderScreen.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/reminders/WorkoutReminderScreen.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
…rding/ProfileCreationViewModel.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
…rding/ProfileCreationViewModel.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/screens/reminders/WorkoutReminderScreen.kt
Outdated
Show resolved
Hide resolved
…serInfoRepository.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
app/src/main/java/com/cornellappdev/uplift/data/repositories/UserInfoRepository.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/onboarding/ProfileCreationViewModel.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| private fun createUser() = viewModelScope.launch { | ||
| val state = getStateValue() | ||
| val user = state.user | ||
| val name = user?.displayName ?: "" | ||
| val email = user?.email ?: "" | ||
| val netId = email.substring(0, email.indexOf('@')) | ||
| if (userInfoRepository.createUser(email, name, netId)) { | ||
| val email = user?.email | ||
| if (email.isNullOrBlank()) { | ||
| Log.e("Error", "Cannot create user: missing or blank email") | ||
| userInfoRepository.signOut() | ||
| return@launch |
There was a problem hiding this comment.
createUser() reads state.user, but user is only populated asynchronously in init { viewModelScope.launch { ... } }. If the user taps Next/Skip before that coroutine runs, state.user will still be null and this path will sign the user out due to a missing email. Consider fetching firebaseAuth.currentUser directly inside createUser() (or populating user synchronously) so onboarding can’t race with initialization.
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import androidx.hilt.navigation.compose.hiltViewModel | ||
| import androidx.lifecycle.compose.collectAsStateWithLifecycle |
There was a problem hiding this comment.
Unused import: collectAsStateWithLifecycle is imported but not referenced anywhere in this file; please remove it to avoid warnings/linters failing.
| import androidx.lifecycle.compose.collectAsStateWithLifecycle |
| import com.cornellappdev.uplift.ui.components.goalsetting.GoalSlider | ||
| import com.cornellappdev.uplift.ui.components.goalsetting.WorkoutReminders | ||
| import com.cornellappdev.uplift.ui.components.general.UpliftButton | ||
| import com.cornellappdev.uplift.ui.viewmodels.onboarding.ProfileCreationViewModel |
There was a problem hiding this comment.
Unused import: ProfileCreationViewModel is imported but not used in this file; please remove it to avoid warnings/linters failing.
| import com.cornellappdev.uplift.ui.viewmodels.onboarding.ProfileCreationViewModel |
| /** | ||
| * @param reminders: list of reminders | ||
| * @param onRemindersChange: callback for when reminders are changed | ||
| * @param goalValue: value of the goal slider | ||
| * @param onGoalValueChange: callback for when the goal slider value is changed | ||
| * @param onBackClick: callback for when the back button is clicked | ||
| * @param isOnboarding: whether the user is in onboarding |
There was a problem hiding this comment.
KDoc for WorkoutReminderScreen no longer documents the required goalValue parameter (it was removed from the comment but the parameter is still present). Please update the KDoc so it matches the function signature.
| preferences[PreferencesKeys.ACCESS_TOKEN] = accessToken | ||
| preferences[PreferencesKeys.REFRESH_TOKEN] = refreshToken | ||
| if (!skip) { | ||
| preferences[PreferencesKeys.GOAL] = goal | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Access/refresh tokens are being persisted into the app DataStore (PreferencesKeys.ACCESS_TOKEN / REFRESH_TOKEN). Preferences DataStore is not encrypted by default, so this stores credentials at rest in plaintext. Since you already introduced TokenManager with EncryptedSharedPreferences, tokens should be stored only there (or move to an encrypted DataStore) and remove these DataStore writes.
| preferences[PreferencesKeys.ACCESS_TOKEN] = accessToken | |
| preferences[PreferencesKeys.REFRESH_TOKEN] = refreshToken | |
| if (!skip) { | |
| preferences[PreferencesKeys.GOAL] = goal | |
| } | |
| } | |
| } | |
| if (!skip) { | |
| preferences[PreferencesKeys.GOAL] = goal | |
| } | |
| } | |
| tokenManager.saveTokens(accessToken, refreshToken) | |
| } |
| val ACCESS_TOKEN = stringPreferencesKey("accessToken") | ||
| val REFRESH_TOKEN = stringPreferencesKey("refreshToken") |
There was a problem hiding this comment.
Adding ACCESS_TOKEN / REFRESH_TOKEN to PreferencesKeys implies these credentials will live in (unencrypted) Preferences DataStore. This is not appropriate for auth tokens; please remove these keys and keep tokens exclusively in an encrypted store (e.g., TokenManager / EncryptedSharedPreferences).
| val ACCESS_TOKEN = stringPreferencesKey("accessToken") | |
| val REFRESH_TOKEN = stringPreferencesKey("refreshToken") |
| } catch (e: Exception) { | ||
| Log.e("TokenManager", "Failed to initialize EncryptedSharedPreferences", e) | ||
| context.deleteSharedPreferences(fileName) | ||
| context.getSharedPreferences(fileName, Context.MODE_PRIVATE) | ||
| } |
There was a problem hiding this comment.
TokenManager falls back to plain SharedPreferences when EncryptedSharedPreferences initialization fails (catch block). That means access/refresh tokens may be stored unencrypted on some devices, defeating the purpose of introducing encrypted storage. Prefer failing closed here (e.g., clear tokens and force re-auth) rather than silently storing tokens in plaintext.

Overview
Implemented the "set your goals" page from the figma and added it to the onboarding flow. Currently, it does not upload the information to the database but that will be for future changes. I also made the base view model for the page with a few functions that will need to be updated when implementing the networking features. Finished networking for the onboarding pages allowing users to update their goals after creating their account. Handled encryption of access and refresh tokens and created an auth interceptor to allow us to send requests to backend without manually adding the http header with each request.
Changes Made
Refactored screen to separate usage for onboarding and settings (WorkoutReminderScreen.kt)
Designed a base view model for the screen (ProfileCreationViewModel.kt)
Updated create user function to enable users to add a goal (UserInfoRepository.kt)
Made small changes in MainNavigationWrapper.kt and DatastoreRepository.kt to enable above changes
Created a token manager to easily encrypt and decrypt the tokens (TokenManager.kt)
Engineered an auth interceptor to add authentication to each backend request we make (AuthInterceptor.kt)
Test Coverage
I was able to manually test and am successfully able to drag the slider over and move to the next page and create a user and view their goals. I also added logging for onboarding and users are successfully created and their goals are added if that page isn't skipped.
Screenshots (delete if not applicable)
Goals Onboarding Screen