Skip to content

Setting Option on Log-in Page#230

Open
brianhu72 wants to merge 5 commits intomainfrom
Brian_SettingUI
Open

Setting Option on Log-in Page#230
brianhu72 wants to merge 5 commits intomainfrom
Brian_SettingUI

Conversation

@brianhu72
Copy link
Copy Markdown

@brianhu72 brianhu72 commented Apr 16, 2026

Overview

I added direct access to the Settings screen from the Login page by introducing a clickable Settings icon. Previously, users could only access Settings after logging in, which limited usability for configuring preferences.

Changes Made

  • Added a Settings icon to the Login page UI based on Figma design
  • Implemented click handling to navigate to the Settings screen

Related PRs or Issues (optional)

This PR is created using the DarkMode code that hasn't been merged yet, so there will be lots of conflicts.

Summary by CodeRabbit

  • New Features

    • Added dark mode toggle in app settings with light, dark, and system theme options.
    • Users can now customize app appearance to match their preference.
  • Improvements

    • Enhanced theme system with dynamic color palette throughout the app.
    • Updated UI components to support both light and dark themes consistently.
    • Improved visual consistency across all screens and dialogs.
  • Chores

    • Updated Gradle to version 8.13.

@brianhu72 brianhu72 requested a review from caleb-bit April 16, 2026 15:46
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

This pull request introduces comprehensive dark mode and theming support across the Android Eatery app. It adds a centralized color theme system with light/dark variants, a new ThemeViewModel for managing theme state, a user preferences protobuf field for persistence, and migrates 70+ UI component files from hardcoded colors to theme-driven values. A new settings sheet allows users to select light/dark/system theme modes, with theme state flowing from storage through the repository and view model to update all UI colors dynamically. Build tooling is updated to Gradle 8.13.

Changes

Cohort / File(s) Summary
Theme Infrastructure
ui/theme/Color.kt, ui/theme/Theme.kt, util/PreviewUtil.kt
Introduced new ColorTheme/ColorMode schema with light/dark color palettes. Added LocalColorMode composition local, AppColorTheme wrapper, and currentColors accessor. Replaced EateryPreview to apply theme directly.
Theme Data & Persistence
ui/viewmodels/ThemeViewModel.kt, data/repositories/UserPreferencesRepository.kt, app/src/main/proto/user_prefs.proto
Created ThemeViewModel exposing isDarkMode state flow. Extended repository with isDarkModeFlow, setDarkMode(), setSystemMode(). Added isDarkMode protobuf field for persistence.
Theme Selection UI
ui/screens/ThemeSheet.kt, ui/screens/SettingsScreen.kt
Added new ThemeSheet composable with Light/Dark/Device Theme options. Updated SettingsScreen to route theme selection via modal bottom sheet and accept ThemeViewModel.
Core Navigation & Layout
MainActivity.kt, ui/navigation/MainTabbedNavigation.kt, ui/navigation/NavigationItem.kt
Updated MainActivity to use AppColorTheme with theme VM state. Extended BottomNavigationBar and SetupNavHost with ThemeViewModel injection. Added dark icon variants and THEME route.
Detail & Modal Components
ui/components/details/*.kt (AlertsSection, CalendarButton, EateryDetailsStickyHeader, EateryHourBottomSheet, EateryMealTabs, EateryMenusBottomSheet, FavoritesToggle, ItemFavoritesCard, PaymentWidgets)
Migrated 9 components to use currentColors instead of hardcoded theme constants (GrayZero, GrayFive, LightBlue, EateryBlue, Green, Red, Yellow). Updated backgrounds, text colors, icon tints, borders, and status indicators.
General UI Components
ui/components/general/*.kt (AppStoreRatingPopup, CalendarWeekSelector, CustomTextField, EateryCard, FavoriteButton, FilterRow, MenuItems, NoEateryFound, PaymentMethodsAvailable, PaymentMethodsBottomSheet, PermissionRequestDialog, SearchBar)
Migrated 12 components to centralized currentColors. FilterRow extended with ThemeViewModel and isDarkMode parameter to FilterButton. Updated colors for buttons, text, icons, borders across all components.
Home & Discovery Screens
ui/screens/HomeScreen.kt, ui/components/home/*.kt (AnnouncementsPopUp, DietaryWidgets, EateryDetailsLoading, EateryHomeSection, MainLoading)
Updated 5 home-related components to use currentColors. HomeScreen accepts ThemeViewModel, resolves dark mode, and threads it to content/icon selection for list/grid toggles.
Account & Auth Screens
ui/screens/ProfileScreen.kt, ui/components/login/*.kt (AccountPage, LoginPage)`
Extended LoginPage with onSettingsClicked callback. AccountPage wrapped in full-screen themed background with currentColors. Updated all text, icon, button, and divider colors.
Settings & Notification Screens
ui/components/settings/*.kt (AppIconBottomSheet, ReportBottomSheet, SettingsOption, SwitchOption), ui/screens/NotificationsHomeScreen.kt, ui/screens/NotificationsSettingsScreen.kt
Migrated 6 settings/notification components to currentColors for backgrounds, text, icons, switches, and buttons. Updated switch track/thumb and button styling to use theme-driven values.
Screen Details
ui/screens/EateryDetailScreen.kt, ui/screens/CompareMenusScreen.kt, ui/screens/FavoritesScreen.kt, ui/screens/SearchScreen.kt, ui/screens/UpcomingMenuScreen.kt
Migrated 5 detail/list screens with extensive color migrations. Updated status colors (error/success/accent), backgrounds, text, separators. UpcomingMenuScreen accepts ThemeViewModel with FilterButton dark mode support.
Remaining Screens
ui/screens/LegalScreen.kt, ui/screens/NearestScreen.kt, ui/screens/OnboardingScreen.kt, ui/screens/PrivacyScreen.kt, ui/screens/SupportScreen.kt, ui/screens/AboutScreen.kt
Migrated 6 screens to currentColors for text, icon tints, backgrounds, and button colors. Updated all hardcoded theme constants and Color.Black/Color.White references.
Comparison & Detail Components
ui/components/comparemenus/CompareMenusBotSheet.kt, ui/components/comparemenus/CompareMenusFAB.kt, ui/components/details/CalendarButton.kt (and similar grouped detail components)
Migrated FAB, bottom sheet, and small detail components to theme-driven styling. Updated backgrounds, button colors, icon tints, borders, and dividers.
Upcoming & Favorites Components
ui/components/upcoming/MealBottomSheet.kt, ui/components/upcoming/MenuCard.kt, ui/components/upcoming/UpcomingLoading.kt, ui/components/notifications/FavoriteItemRow.kt, ui/components/onboarding/IconSheet.kt, ui/components/onboarding/OnboardingCarousel.kt, ui/components/onboarding/OnboardingHeader.kt
Migrated 7 upcoming/notification/onboarding components to currentColors for text, icons, backgrounds, and loading states. Updated button, card, and shimmer colors.
ViewModel Updates
ui/viewmodels/FavoritesViewModel.kt, ui/viewmodels/UpcomingViewModel.kt
Replaced theme color constants (Green, Red, Orange, Yellow) with direct Compose Color values for availability/status indicators. Updated sorting and status color logic.
Drawable Resources
drawable/dark_mode.xml, drawable/light_mode.xml, drawable/system_setting.xml, drawable/ic_brightness.xml, drawable/ic_calendar_selected_dark.xml, drawable/ic_grid_view_selected_dark.xml, drawable/ic_grid_view_unselected_dark.xml, drawable/ic_home_selected_dark.xml, drawable/ic_list_view_selected_dark.xml, drawable/ic_list_view_unselected_dark.xml, drawable/ic_profile_selected_dark.xml
Added 11 new vector drawable resources for dark mode icons (theme selection, navigation variants) and 1 minor formatting fix to ic_grid_view_unselected.xml.
Build Configuration
gradle/wrapper/gradle-wrapper.properties
Updated Gradle wrapper from version 8.6 to 8.13.

Sequence Diagram(s)

sequenceDiagram
    actor User as User
    participant Settings as SettingsScreen
    participant ThemeSheet as ThemeSheet
    participant ViewModel as ThemeViewModel
    participant Repository as UserPreferencesRepository
    participant DataStore as DataStore
    participant UI as UI Components
    
    User->>Settings: Open Settings
    User->>Settings: Tap "Display" option
    Settings->>ThemeSheet: Show theme modal
    User->>ThemeSheet: Select Light/Dark/System
    ThemeSheet->>ViewModel: toggleDarkMode() / toggleLightMode() / toggleSystemMode()
    ViewModel->>Repository: setDarkMode(bool) or setSystemMode()
    Repository->>DataStore: Update isDarkMode preference
    DataStore-->>Repository: Persist value
    Repository-->>ViewModel: Emit isDarkModeFlow update
    ViewModel-->>UI: isDarkMode StateFlow updates
    UI->>UI: Recompose with new currentColors
    Note over UI: Colors change based on resolved dark mode
    ThemeSheet->>Settings: onDismiss()
    Settings-->>User: Theme applied
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

ui, feature, theming, dark-mode

Suggested reviewers

  • AndrewCheung360

Poem

🐰 In darkness and light, the colors now flow,

Through themes that cascade wherever we go,

With dark mode and system, the user takes hold,

Of hues that adapt—a sight to behold! ✨

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Setting Option on Log-in Page' is vague and does not clearly describe the main change. The term 'Setting Option' is ambiguous and does not convey that a Settings icon was added for navigation to the Settings screen. Revise the title to be more specific and descriptive, such as 'Add Settings icon to Login page' or 'Enable Settings access from Login page' to clearly communicate the primary change.
Description check ❓ Inconclusive The PR description is incomplete and lacks required sections. It is missing Test Coverage details, and the Overview is too brief without sufficient context about the scope and impact of changes. Expand the Overview to better describe the scope and impact of the dark mode changes. Add a comprehensive Test Coverage section detailing how the theme switching functionality was tested. Consider adding more detail to Next Steps if applicable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Brian_SettingUI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt (1)

551-558: ⚠️ Potential issue | 🟡 Minor

Invisible divider: background matches container.

The divider Spacer uses currentColors.backgroundDefault which is the same color as the parent Column background at line 508. This makes the divider invisible.

🐛 Proposed fix
 Spacer(
     modifier = Modifier
         .fillMaxWidth()
         .height(1.dp)
-        .background(currentColors.backgroundDefault, CircleShape)
+        .background(currentColors.borderDefault, CircleShape)
         .padding(horizontal = 16.dp)
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt`
around lines 551 - 558, The divider Spacer between payment methods is invisible
because it uses currentColors.backgroundDefault (same as the parent Column
background); change the spacer to use a contrasting color (for example
currentColors.surfaceVariant or currentColors.onSurface.copy(alpha = 0.08f)) or
replace it with Compose's Divider to ensure visibility; update the
Spacer/Divider in the block that checks if (index != selectedPaymentMethod.size)
within AccountPage (the Spacer currently using
.background(currentColors.backgroundDefault, CircleShape)) so it uses the chosen
contrasting color or Divider composable instead.
🧹 Nitpick comments (22)
app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FavoriteButton.kt (1)

40-40: Prefer a theme token over a hardcoded star color.

Line 40 hardcodes the selected tint, which makes future palette updates harder. Consider routing this through a named theme color role for consistency with the rest of this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FavoriteButton.kt`
at line 40, The tint for the favorite star in FavoriteButton is using a
hardcoded Color(0xFFFFD700); replace it with a theme color token instead — e.g.,
add/use a named color role like favorite/selected tint in your app theme (or use
an existing role such as currentColors.accentSelected or
MaterialTheme.colorScheme.secondary) and update the tint expression in
FavoriteButton to use that token when isFavorite is true so palette changes
follow the theme.
app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/FavoritesViewModel.kt (1)

147-147: Avoid sorting by a UI color constant.

Line 147 couples ordering to Color.Green. Prefer sorting by a semantic boolean (isAvailable) so ordering won’t break if display colors change.

♻️ Proposed refactor pattern
-                val itemFavoriteCards = menuItemsToEateries.map { (itemName, eateriesByItem) ->
-                    ItemFavoritesCardViewState(
+                val itemFavoriteCards = menuItemsToEateries.map { (itemName, eateriesByItem) ->
+                    val isAvailable = eateriesByItem.isNotEmpty()
+                    isAvailable to ItemFavoritesCardViewState(
                         itemName = itemName,
-                        availability = if (eateriesByItem.isEmpty()) EateryStatus(
+                        availability = if (!isAvailable) EateryStatus(
                             "Not available",
                             Color.Red
                         ) else EateryStatus("Available today", Color.Green),
                         ...
                     )
-                }.sortedByDescending { it.availability.statusColor == Color.Green }
+                }.sortedByDescending { it.first }
+                 .map { it.second }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/FavoritesViewModel.kt`
at line 147, The view model is sorting by a UI color constant
(sortedByDescending { it.availability.statusColor == Color.Green }) which
couples ordering to presentation; change the sort to use a semantic availability
flag (e.g., use Availability.isAvailable or a boolean on the item) instead.
Update FavoritesViewModel to sortByDescending on that boolean (e.g.,
it.availability.isAvailable) and, if the Availability/data model lacks such a
property, add a derived isAvailable getter on the Availability/data model (or
map availability status to a boolean in the view model) so ordering depends on
semantic state, not Color.Green.
app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/UpcomingViewModel.kt (1)

107-109: Extract the inline warning color into a named constant.

Line 108 hardcodes a magic hex value, which makes status-color maintenance harder across viewmodels.

♻️ Proposed cleanup
+private val CLOSING_SOON_COLOR = Color(0xFFFFA500)
...
                 eateryStatus = when {
                     isClosed() -> EateryStatus("Closed", Color.Red)
-                    isClosingSoon() -> EateryStatus("Closing Soon", Color(0xFFFFA500))
+                    isClosingSoon() -> EateryStatus("Closing Soon", CLOSING_SOON_COLOR)
                     else -> EateryStatus("Open", Color.Green)
                 },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/UpcomingViewModel.kt`
around lines 107 - 109, Inline warning color 0xFFFFA500 is a magic literal;
define a named Color constant (e.g., WARNING_COLOR or WarningColor) and use it
instead of Color(0xFFFFA500) in UpcomingViewModel's status mapping. Add the
constant in a shared place (a companion object in UpcomingViewModel or a common
UI/colors object so other viewmodels can reuse it), replace the inline
Color(0xFFFFA500) in the isClosingSoon() branch with the new constant, and
update any other viewmodels to import/use the same constant for consistent
maintenance.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/CompareMenusScreen.kt (1)

343-343: Use the local colors reference consistently.

These two lines still read currentColors directly while the composable already stores val colors = currentColors. Keeping one access pattern reduces visual noise.

Also applies to: 427-427

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/CompareMenusScreen.kt`
at line 343, Replace direct uses of currentColors with the local val colors
already defined in the composable to keep access consistent: find the places
that call currentColors.backgroundDefault (and the other occurrence at the
second site) and change them to colors.backgroundDefault; update both
occurrences referenced in the diff so the composable consistently uses the local
colors variable.
app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/FavoritesToggle.kt (1)

35-36: Prefer a theme token over hardcoded gold for active state.

Using Color(0xFFFFD700) here bypasses the centralized palette. Consider mapping this to a semantic theme color (or adding one) so active toggle styling stays consistent with the rest of the app.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/FavoritesToggle.kt`
around lines 35 - 36, The hardcoded gold literal in FavoritesToggle
(detailColor) bypasses the theme palette; replace Color(0xFFFFD700) with a
semantic theme token (e.g., use an existing token like
currentColors.accentPrimary or add a new token such as
currentColors.favoriteActive/highlightActive) and update the theme/provider
implementation to supply that color so FavoritesToggle uses that token when
active (also ensure any usages of backgroundColor keep using currentColors for
consistency).
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/OnboardingScreen.kt (1)

84-84: Small consistency cleanup: use colors instead of currentColors here.

Since val colors = currentColors is already declared, using it in these lines keeps the composable consistent.

Also applies to: 101-101

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/OnboardingScreen.kt`
at line 84, Replace uses of currentColors with the local alias colors in the
OnboardingScreen composable where color = currentColors.oppTextPrimary (and the
other occurrence noted). Locate the val colors = currentColors declaration in
OnboardingScreen and update the color assignments referencing
currentColors.oppTextPrimary to use colors.oppTextPrimary to keep naming
consistent.
app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/CalendarWeekSelector.kt (1)

88-91: Simplify redundant when branches for circle background.

At Line 89 and Line 90, both branches resolve to currentColors.textSecondary, so the condition adds noise without changing behavior.

♻️ Proposed simplification
-                        color = when {
-                            i == currSelectedDay && currSelectedDay == 0 -> currentColors.accentPrimary
-                            i == currSelectedDay || i == selectedDay -> currentColors.textSecondary
-                            else -> currentColors.textSecondary
-                        },
+                        color = if (i == currSelectedDay && currSelectedDay == 0) {
+                            currentColors.accentPrimary
+                        } else {
+                            currentColors.textSecondary
+                        },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/CalendarWeekSelector.kt`
around lines 88 - 91, The when expression determining the circle background in
CalendarWeekSelector should be simplified because the second and third branches
both return currentColors.textSecondary; update the when (the expression using
i, currSelectedDay, selectedDay and currentColors) to only include the
special-case branch (i == currSelectedDay && currSelectedDay == 0 ->
currentColors.accentPrimary) and a single fallback branch (else ->
currentColors.textSecondary), removing the redundant i == currSelectedDay || i
== selectedDay branch.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/EateryDetailScreen.kt (1)

858-861: Minor: Remove unnecessary blank lines.

Lines 858-859 appear to be formatting artifacts.

Cleanup
 private fun LazyListScope.menuHeadingItem(
     weekDayIndex: Int,
     nextEvent: Event,
     hoursOnClick: () -> Job
 ) {
-
-
     item {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/EateryDetailScreen.kt`
around lines 858 - 861, Remove the stray blank lines in the composable item
block where "val colors = currentColors" is declared; locate the item { ... }
block in EateryDetailScreen (the composable that references currentColors) and
delete the extra empty lines so the declaration sits directly inside the item
block without blank-line artifacts.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt (1)

78-109: Redundant boolean comparisons.

lightMode == true, darkMode == true, and systemMode == true can be simplified to just lightMode, darkMode, and systemMode.

Simplified comparisons
         ThemeRow(
             text = "Light",
-            isSelected = lightMode == true,
+            isSelected = lightMode,
             ...
         )
         ...
         ThemeRow(
             text = "Dark",
-            isSelected = darkMode == true,
+            isSelected = darkMode,
             ...
         )
         ...
         ThemeRow(
             text = "Device Theme",
-            isSelected = systemMode == true,
+            isSelected = systemMode,
             ...
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt`
around lines 78 - 109, The ThemeRow calls use redundant boolean comparisons
(lightMode == true, darkMode == true, systemMode == true); update the isSelected
arguments in the ThemeRow invocations to pass the boolean variables directly
(isSelected = lightMode, isSelected = darkMode, isSelected = systemMode) to
simplify code in ThemeSheet.kt and keep the onClick handlers unchanged.
app/src/main/java/com/cornellappdev/android/eatery/ui/navigation/NavigationItem.kt (1)

3-5: Remove unused imports.

hiltViewModel and ThemeViewModel are imported but not used in this file.

Clean imports
 package com.cornellappdev.android.eatery.ui.navigation

-import androidx.hilt.navigation.compose.hiltViewModel
 import com.cornellappdev.android.eatery.R
-import com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/navigation/NavigationItem.kt`
around lines 3 - 5, Remove the unused imports hiltViewModel and ThemeViewModel
from NavigationItem.kt; open the file and delete the lines importing
androidx.hilt.navigation.compose.hiltViewModel and
com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel so only necessary
imports (e.g., R) remain, then run the IDE's "optimize imports" or build to
ensure no remaining unused import warnings.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/UpcomingMenuScreen.kt (1)

285-288: Potential ViewModel scoping concern with default parameter.

Injecting ThemeViewModel via hiltViewModel() as a default parameter in UpcomingFilterRow may create a separate ViewModel instance scoped to this composable's navigation destination, rather than sharing the app-level theme state.

Consider passing the resolved isDarkMode boolean directly instead of the ViewModel to avoid scoping issues:

Alternative approach
 `@Composable`
 private fun UpcomingFilterRow(
     coroutineScope: CoroutineScope,
     showModalBottomSheet: suspend () -> Unit,
     mealFilter: MealFilter,
     upcomingMenuFilters: List<Filter>,
     selectedFilters: List<Filter>,
     onToggleFilterClicked: (Filter) -> Unit,
     filterRowState: LazyListState,
-    themeViewModel : ThemeViewModel = hiltViewModel()
+    isDarkMode: Boolean
 ) {
-    val isDarkMode by themeViewModel.isDarkMode.collectAsState()
-    val resolvedDarkMode = isDarkMode ?: isSystemInDarkTheme()
     FilterRow(
         customItemsBefore = {
             item {
                 FilterButton(
                     ...
-                    resolvedDarkMode
+                    isDarkMode
                 )
             }
         },

Then resolve the dark mode state at a higher level (e.g., UpcomingMenuScreen) and pass it down.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/UpcomingMenuScreen.kt`
around lines 285 - 288, The UpcomingFilterRow currently defaults its
themeViewModel parameter to hiltViewModel(), which can create a ViewModel scoped
to the composable's destination and cause separate theme state; instead resolve
the theme at a higher level (e.g., in UpcomingMenuScreen) by collecting
ThemeViewModel.isDarkMode there and pass the boolean down to UpcomingFilterRow
(replace the themeViewModel parameter with an isDarkMode: Boolean or use
resolvedDarkMode), ensuring you reference ThemeViewModel, hiltViewModel(),
UpcomingFilterRow, UpcomingMenuScreen, isDarkMode and resolvedDarkMode when
locating and updating the code.
app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt (3)

3-18: Remove unused imports.

Several imports are unused:

  • android.annotation.SuppressLint (line 3)
  • androidx.compose.foundation.isSystemInDarkTheme (line 4)
  • androidx.compose.runtime.Composable (line 5)
  • com.cornellappdev.android.eatery.data.repositories.UserRepository (line 9)
  • com.cornellappdev.android.eatery.ui.theme.ColorMode (line 10)
  • com.cornellappdev.android.eatery.ui.theme.ColorTheme (line 11)
Clean imports
 package com.cornellappdev.android.eatery.ui.viewmodels

-import android.annotation.SuppressLint
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.runtime.Composable
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.cornellappdev.android.eatery.data.repositories.UserPreferencesRepository
-import com.cornellappdev.android.eatery.data.repositories.UserRepository
-import com.cornellappdev.android.eatery.ui.theme.ColorMode
-import com.cornellappdev.android.eatery.ui.theme.ColorTheme
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 import javax.inject.Inject
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt`
around lines 3 - 18, The listed imports in ThemeViewModel.kt are unused—remove
the lines importing android.annotation.SuppressLint,
androidx.compose.foundation.isSystemInDarkTheme,
androidx.compose.runtime.Composable,
com.cornellappdev.android.eatery.data.repositories.UserRepository,
com.cornellappdev.android.eatery.ui.theme.ColorMode, and
com.cornellappdev.android.eatery.ui.theme.ColorTheme; keep the remaining imports
(e.g., ViewModel, viewModelScope, UserPreferencesRepository, HiltViewModel,
coroutine flow imports) and then run your IDE's "Optimize/Organize Imports" to
verify no other unused imports remain.

24-27: Redundant stateIn() on an already-hot StateFlow.

Per the context snippet, repository.isDarkModeFlow is already a StateFlow (created with stateIn() in the repository). Wrapping it again with stateIn() creates an unnecessary intermediate flow.

You can directly expose the repository's StateFlow:

Simplified approach
-    val isDarkMode : StateFlow<Boolean?> = repository.isDarkModeFlow.stateIn(
-        viewModelScope,
-        started = SharingStarted.Eagerly,
-        initialValue = null)
+    val isDarkMode: StateFlow<Boolean?> = repository.isDarkModeFlow
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt`
around lines 24 - 27, The val isDarkMode in ThemeViewModel is redundantly
wrapping repository.isDarkModeFlow (which is already a StateFlow) with stateIn;
remove the extra stateIn call and directly expose repository.isDarkModeFlow as
the isDarkMode StateFlow (ensuring the declared type matches the repository
flow's element type), i.e., assign isDarkMode = repository.isDarkModeFlow and
drop the viewModelScope/stateIn boilerplate.

29-41: Method names are misleading - they set, not toggle.

toggleDarkMode(), toggleLightMode(), and toggleSystemMode() don't toggle—they unconditionally set the mode. Consider renaming for clarity:

Suggested naming
-    fun toggleDarkMode()
+    fun setDarkMode()
     {
         viewModelScope.launch { repository.setDarkMode(true)}
     }
-    fun toggleLightMode()
+    fun setLightMode()
     {
         viewModelScope.launch { repository.setDarkMode(false)}
     }

-    fun toggleSystemMode()
+    fun setSystemMode()
     {
         viewModelScope.launch {repository.setSystemMode()}
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt`
around lines 29 - 41, The three ViewModel methods are misnamed because they set
modes rather than toggling; rename toggleDarkMode to setDarkMode,
toggleLightMode to setLightMode, and toggleSystemMode to setSystemMode (or
setSystemModePreference if you prefer clearer wording) and update all call sites
accordingly; keep the existing calls to repository.setDarkMode(true/false) and
repository.setSystemMode(), only change the ViewModel method names
(ThemeViewModel.toggleDarkMode, ThemeViewModel.toggleLightMode,
ThemeViewModel.toggleSystemMode) and any imports/usages that reference them.
app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/EateryCard.kt (1)

184-185: Hardcoded orange color for "closing soon" warning.

The warning icon/banner uses a hardcoded orange Color(0xFFFFA500) while the rest of the file migrates to theme colors. Consider adding a warning semantic color to the theme palette for consistency.

Suggested approach
-                       contentColor = Color(0xFFFFA500),
+                       contentColor = currentColors.warning, // Add warning color to theme
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/EateryCard.kt`
around lines 184 - 185, The code uses a hardcoded orange Color(0xFFFFA500) for
the "closing soon" contentColor; add a semantic warning color to your theme
palette (e.g., warning in your AppColors/ThemeColors data class and concrete
values for light/dark) and replace the hardcoded literal in EateryCard with the
theme value (e.g., MaterialTheme.colors.warning or YourTheme.colors.warning) so
the banner uses the themed semantic color consistently across dark/light themes.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SupportScreen.kt (1)

165-169: Verify semantic color choice for icon tint.

Using colors.backgroundSecondary for the arrow icon tint appears semantically inconsistent. Based on the color definitions, backgroundSecondary is the blue header/navigation background color, not an accent color for icons. Consider using colors.accentPrimary or colors.textSecondary for consistency with icon styling elsewhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SupportScreen.kt`
around lines 165 - 169, The arrow icon in SupportScreen's composable (the Icon
using Icons.Outlined.ArrowOutward) is tinted with colors.backgroundSecondary
which is the header/nav blue and not semantically appropriate; update the tint
to a semantic icon color such as colors.accentPrimary or colors.textSecondary to
match other icon styling in the screen and ensure consistency across the UI.
app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt (1)

58-58: Remove unused import.

hiltViewModel is imported but not used in this file (ThemeViewModel is imported but never instantiated or used).

♻️ Proposed fix
-import androidx.hilt.navigation.compose.hiltViewModel

Also remove the unused ThemeViewModel import at line 67:

-import com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt`
at line 58, Remove the unused imports in AccountPage.kt: delete the unused
hiltViewModel import and also remove the unused ThemeViewModel import reference
(since ThemeViewModel is never instantiated or used in this file); ensure no
other code references hiltViewModel or ThemeViewModel in this file before
committing.
app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt (2)

43-43: Remove unused import.

UserPreferencesRepository is imported but not used in this file.

♻️ Proposed fix
-import com.cornellappdev.android.eatery.data.repositories.UserPreferencesRepository
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt`
at line 43, The file contains an unused import of UserPreferencesRepository in
SettingsScreen.kt; remove the import statement for UserPreferencesRepository so
the file no longer imports an unused symbol and rebuild to ensure no references
to UserPreferencesRepository remain in SettingsScreen or its functions (e.g.,
SettingsScreen) before committing.

111-116: Verify Settings title color choice.

The "Settings" title uses currentColors.backgroundSecondary which is typically the blue navigation/header background color. For heading text, currentColors.textPrimary is likely more appropriate and consistent with other screen headers (e.g., SupportScreen uses colors.textPrimary for its title at line 103).

♻️ Proposed fix
 Text(
     text = "Settings",
-    color = currentColors.backgroundSecondary,
+    color = currentColors.textPrimary,
     style = EateryBlueTypography.h2,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt`
around lines 111 - 116, The Settings title currently uses
currentColors.backgroundSecondary; change it to use currentColors.textPrimary to
match other screen headers (e.g., SupportScreen's title) for consistent heading
color. Locate the Text composable rendering "Settings" in SettingsScreen (the
Text with style = EateryBlueTypography.h2) and update its color property from
currentColors.backgroundSecondary to currentColors.textPrimary; ensure no other
style or modifier changes are made.
app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FilterRow.kt (2)

84-88: Simplify boolean comparison.

isDarkMode==true is redundant since isDarkMode is already a Boolean. Direct boolean check is cleaner.

♻️ Proposed fix
-    if (isDarkMode==true)
-    {
+    if (isDarkMode) {
         background = colorInterp(progress, Color.White, Color(0xFF272727))
         contentColor = colorInterp(progress, Color.Black, Color.White)
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FilterRow.kt`
around lines 84 - 88, In FilterRow.kt simplify the redundant boolean comparison
by changing the conditional that currently reads "if (isDarkMode==true)" to a
direct boolean check "if (isDarkMode)"; locate the block around the isDarkMode
variable in the FilterRow composable (the lines setting background and
contentColor with colorInterp) and replace the equality check with the direct
boolean expression to make the code cleaner and idiomatic.

69-74: Consider making isDarkMode a named parameter with default.

The isDarkMode parameter is required, but placing it after icon (which has a default) creates an awkward call site pattern. Consider either:

  1. Moving isDarkMode before icon, or
  2. Providing a default value (e.g., isDarkMode: Boolean = false)

This would improve API ergonomics and reduce breaking changes for existing callers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FilterRow.kt`
around lines 69 - 74, The FilterButton signature requires callers to pass
isDarkMode after an optional icon, making call sites awkward; update the
FilterButton function declaration (the parameters in FilterButton) to make
isDarkMode an optional named parameter with a default (e.g., isDarkMode: Boolean
= false) so callers can omit it or pass it by name, or alternatively move
isDarkMode before icon in the parameter list to avoid breaking ergonomics—apply
the change in the FilterButton function declaration and update any callers if
needed.
app/src/main/java/com/cornellappdev/android/eatery/ui/theme/Color.kt (1)

5-20: Remove the legacy commented-out palette block.

Line 5–20 is dead commented code and makes the theme file harder to scan/maintain. Please delete it now that the role-based palette is in place.

Proposed cleanup
-/*
-val EateryBlue = Color(0xFF4A90E2)
-val colors.backgroundDefault = Color(0xFFEFF1F4)
-val colors.backgroundSecondary = Color(0xFFE1E4E8)
-val backgroundDefault92 = Color(0xFFD1D5DA)
-val colors.backgroundDefault10 = Color(0xFF959da5)
-val colors.textSecondary = Color(0xFF586069)
-val colors.textPrimary = Color(0xFF444D56)
-val LightBlue = Color(0xFFE8EFF8)
-val LightRed = Color(0xFFFEF0EF)
-val Red = Color(0xFFF2655D)
-val Green = Color(0xFF63C774)
-val colors.accentPressed = Color(0xFFFEC50E)
-val Orange = Color(0xFFFF990E)
-
- */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/theme/Color.kt` around
lines 5 - 20, Delete the legacy commented-out palette block in Color.kt (the
multi-line comment containing EateryBlue, LightBlue, Red, Green, Orange and
various colors.background... entries) so the theme file only contains the active
role-based palette; remove the entire comment block (the /* ... */ section) and
run formatter/compile to ensure no leftover references remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/cornellappdev/android/eatery/MainActivity.kt`:
- Around line 17-19: The root composable must install Material theme locals so
Material3 components get app typography and shapes: wrap the existing
AppColorTheme usage in MainActivity's setContent with the MaterialTheme
composable (the Material3 androidx.compose.material3.MaterialTheme) so that
NavigationSetup is called inside MaterialTheme (e.g., MaterialTheme {
AppColorTheme { NavigationSetup(...) } } or the equivalent ordering), leaving
ThemeViewModel/AppColorTheme intact but ensuring MaterialTheme locals are
provided to NavigationSetup and its children.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/comparemenus/CompareMenusBotSheet.kt`:
- Around line 136-146: The disabled button state in CompareMenusBotSheet uses a
nearly identical background and text color (ButtonDefaults.buttonColors
backgroundColor = colors.backgroundDefault92 with contentColor =
colors.backgroundDefault), making the "Select at least X more" label hard to
read; change the disabled contentColor to a high-contrast color (e.g., a
disabled text or on-background color from your palette) in the
ButtonDefaults.buttonColors when selectedEateries.size < 2 and remove the
hard-coded color override on the Text (so the Text uses the button's content
color) by updating the ButtonDefaults.buttonColors call and the Text usage
around selectedEateries, ButtonDefaults.buttonColors, and the Text composable.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryDetailsStickyHeader.kt`:
- Line 146: The Divider in EateryDetailsStickyHeader currently uses
colors.backgroundDefault (the same as the container) so the separator is
invisible; update the Divider's color argument in the EateryDetailsStickyHeader
composable to a contrasting token (for example use colors.outline /
colors.surfaceVariant / onBackground.copy(alpha = ...) or another theme outline
color) so the divider is visible against the header background.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/NoEateryFound.kt`:
- Around line 48-49: The reset button in NoEateryFound (the Button where
backgroundColor = currentColors.accentPrimary) uses Text(color =
currentColors.backgroundDefault) which yields poor contrast; change the Text
color to a high-contrast token (e.g., currentColors.onAccentPrimary or use
contentColorFor(currentColors.accentPrimary)) so the label meets accessible
contrast, and apply the same change to the other Button instance referenced
(lines 56-57). Ensure you update the Text(...) color only for those Buttons or
use ButtonDefaults.buttonColors/contentColorFor to keep colors consistent.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/PaymentMethodsAvailable.kt`:
- Around line 198-201: The enum PaymentMethodsAvailable currently stores
hardcoded Color values (property color) that don't adapt to dark mode, causing
text to remain fixed while icons use theme-aware colors (see icon tint usage
with currentColors.error/currentColors.success at the icon locations). Fix by
removing the hardcoded Color from the enum and instead resolve the color at
render time where SpanStyle is applied (the SpanStyle(color =
paymentMethod.color) usage), using the same theme-aware values used for icon
tints (currentColors.*), or alternatively change the enum to expose a
color-provider function (e.g., a method like getColor(currentColors) or a
lambda) and call that from the composable when building SpanStyle so text colors
follow dark mode like the icons.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/HomeScreen.kt`:
- Around line 599-606: The painterResource conditional that picks the list view
icon is missing the case for (!isGridView && !isDarkMode); update the branches
used by the painter assignment so the four cases map correctly: (isGridView &&
isDarkMode) -> ic_list_view_unselected_dark, (isGridView && !isDarkMode) ->
ic_list_view_unselected, (!isGridView && isDarkMode) ->
ic_list_view_selected_dark, and the final else -> ic_list_view_selected (replace
the current ic_list_view_unselected in the else). Adjust the conditional around
painter = painterResource(...) that uses isGridView and isDarkMode so the
non-grid non-dark path shows the selected icon while leaving tint and modifier
(Modifier.clickable { onListClick() }) unchanged.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SearchScreen.kt`:
- Around line 338-339: The shimmer currently uses identical colors (baseColor =
currentColors.backgroundDefault and highlightColor = colors.backgroundDefault)
so the highlight is invisible; update the highlightColor to a lighter or
contrasting background variant (e.g., use colors.backgroundElevated,
currentColors.backgroundMuted, or a lightened version of
currentColors.backgroundDefault) in the SearchScreen shimmer configuration to
restore visible shimmer contrast while keeping baseColor as
currentColors.backgroundDefault.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt`:
- Around line 320-324: The Text composable is force-unwrapping
state.user.userName using !! which can crash if userName is null; replace the
forced unwrap in the string expression (the usage in the Text call) with a safe
call and a fallback, e.g., use state.user.userName?.substringBefore('@') ?:
"<fallback>" (or another user-friendly default) so the UI won't crash when
userName is null.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt`:
- Around line 111-134: ThemeSheet currently calls onDismiss() from the Done
Button even when no selection was made, so the user's preference isn't saved;
update ThemeSheet to either pre-select the current theme when the sheet opens or
disable the Done button until a selection exists—simplest fix: track whether a
selection state (e.g., darkMode/lightMode/systemMode or a nullable selectedTheme
variable) is non-null and set Button(enabled = selectedTheme != null) for the
Done Button, and only invoke
viewModel.toggleDarkMode()/toggleLightMode()/toggleSystemMode() when a selection
is present before calling onDismiss(); ensure the Button text/semantics reflect
the disabled state so users know an option must be chosen.
- Around line 54-57: Replace the three independent booleans (darkMode,
lightMode, systemMode) in ThemeSheet with a single sealed enum or enum class
(e.g., ThemeOption { DARK, LIGHT, SYSTEM }) stored in one remember {
mutableStateOf(...) } and initialize it from the ThemeViewModel's current theme
value (use the ViewModel property that indicates the user's preference) so the
UI reflects existing settings; update ThemeRow invocations to check/emit the
single ThemeOption value instead of individual booleans and adjust the Done
button logic to apply the selected ThemeOption (including handling SYSTEM by
using isSystemInDarkTheme() where needed) and persist via the ThemeViewModel
methods.

In `@app/src/main/res/drawable/ic_list_view_selected_dark.xml`:
- Around line 1-18: In HomeScreen.kt update the icon mapping for the list-view
selection branch: where the code checks the booleans isGridView and isDarkMode
(the branch for !isGridView && !isDarkMode) it currently returns
ic_list_view_unselected — change that to return the selected drawable
ic_list_view_selected so the selected state shows the correct light-mode icon;
keep all other dark-mode and grid-view branches unchanged.

In `@gradle/wrapper/gradle-wrapper.properties`:
- Line 4: The gradle-wrapper properties currently point to Gradle 8.13 which is
outside AGP 8.1.1's tested compatibility; update the distributionUrl in
gradle-wrapper.properties (the distributionUrl entry) to a supported version
such as gradle-8.4-bin.zip (or another version within the AGP 8.1.1
compatibility matrix) to ensure a tested Gradle/AGP combination and avoid
potential build instability.

---

Outside diff comments:
In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt`:
- Around line 551-558: The divider Spacer between payment methods is invisible
because it uses currentColors.backgroundDefault (same as the parent Column
background); change the spacer to use a contrasting color (for example
currentColors.surfaceVariant or currentColors.onSurface.copy(alpha = 0.08f)) or
replace it with Compose's Divider to ensure visibility; update the
Spacer/Divider in the block that checks if (index != selectedPaymentMethod.size)
within AccountPage (the Spacer currently using
.background(currentColors.backgroundDefault, CircleShape)) so it uses the chosen
contrasting color or Divider composable instead.

---

Nitpick comments:
In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/FavoritesToggle.kt`:
- Around line 35-36: The hardcoded gold literal in FavoritesToggle (detailColor)
bypasses the theme palette; replace Color(0xFFFFD700) with a semantic theme
token (e.g., use an existing token like currentColors.accentPrimary or add a new
token such as currentColors.favoriteActive/highlightActive) and update the
theme/provider implementation to supply that color so FavoritesToggle uses that
token when active (also ensure any usages of backgroundColor keep using
currentColors for consistency).

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/CalendarWeekSelector.kt`:
- Around line 88-91: The when expression determining the circle background in
CalendarWeekSelector should be simplified because the second and third branches
both return currentColors.textSecondary; update the when (the expression using
i, currSelectedDay, selectedDay and currentColors) to only include the
special-case branch (i == currSelectedDay && currSelectedDay == 0 ->
currentColors.accentPrimary) and a single fallback branch (else ->
currentColors.textSecondary), removing the redundant i == currSelectedDay || i
== selectedDay branch.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/EateryCard.kt`:
- Around line 184-185: The code uses a hardcoded orange Color(0xFFFFA500) for
the "closing soon" contentColor; add a semantic warning color to your theme
palette (e.g., warning in your AppColors/ThemeColors data class and concrete
values for light/dark) and replace the hardcoded literal in EateryCard with the
theme value (e.g., MaterialTheme.colors.warning or YourTheme.colors.warning) so
the banner uses the themed semantic color consistently across dark/light themes.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FavoriteButton.kt`:
- Line 40: The tint for the favorite star in FavoriteButton is using a hardcoded
Color(0xFFFFD700); replace it with a theme color token instead — e.g., add/use a
named color role like favorite/selected tint in your app theme (or use an
existing role such as currentColors.accentSelected or
MaterialTheme.colorScheme.secondary) and update the tint expression in
FavoriteButton to use that token when isFavorite is true so palette changes
follow the theme.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FilterRow.kt`:
- Around line 84-88: In FilterRow.kt simplify the redundant boolean comparison
by changing the conditional that currently reads "if (isDarkMode==true)" to a
direct boolean check "if (isDarkMode)"; locate the block around the isDarkMode
variable in the FilterRow composable (the lines setting background and
contentColor with colorInterp) and replace the equality check with the direct
boolean expression to make the code cleaner and idiomatic.
- Around line 69-74: The FilterButton signature requires callers to pass
isDarkMode after an optional icon, making call sites awkward; update the
FilterButton function declaration (the parameters in FilterButton) to make
isDarkMode an optional named parameter with a default (e.g., isDarkMode: Boolean
= false) so callers can omit it or pass it by name, or alternatively move
isDarkMode before icon in the parameter list to avoid breaking ergonomics—apply
the change in the FilterButton function declaration and update any callers if
needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt`:
- Line 58: Remove the unused imports in AccountPage.kt: delete the unused
hiltViewModel import and also remove the unused ThemeViewModel import reference
(since ThemeViewModel is never instantiated or used in this file); ensure no
other code references hiltViewModel or ThemeViewModel in this file before
committing.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/navigation/NavigationItem.kt`:
- Around line 3-5: Remove the unused imports hiltViewModel and ThemeViewModel
from NavigationItem.kt; open the file and delete the lines importing
androidx.hilt.navigation.compose.hiltViewModel and
com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel so only necessary
imports (e.g., R) remain, then run the IDE's "optimize imports" or build to
ensure no remaining unused import warnings.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/CompareMenusScreen.kt`:
- Line 343: Replace direct uses of currentColors with the local val colors
already defined in the composable to keep access consistent: find the places
that call currentColors.backgroundDefault (and the other occurrence at the
second site) and change them to colors.backgroundDefault; update both
occurrences referenced in the diff so the composable consistently uses the local
colors variable.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/EateryDetailScreen.kt`:
- Around line 858-861: Remove the stray blank lines in the composable item block
where "val colors = currentColors" is declared; locate the item { ... } block in
EateryDetailScreen (the composable that references currentColors) and delete the
extra empty lines so the declaration sits directly inside the item block without
blank-line artifacts.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/OnboardingScreen.kt`:
- Line 84: Replace uses of currentColors with the local alias colors in the
OnboardingScreen composable where color = currentColors.oppTextPrimary (and the
other occurrence noted). Locate the val colors = currentColors declaration in
OnboardingScreen and update the color assignments referencing
currentColors.oppTextPrimary to use colors.oppTextPrimary to keep naming
consistent.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt`:
- Line 43: The file contains an unused import of UserPreferencesRepository in
SettingsScreen.kt; remove the import statement for UserPreferencesRepository so
the file no longer imports an unused symbol and rebuild to ensure no references
to UserPreferencesRepository remain in SettingsScreen or its functions (e.g.,
SettingsScreen) before committing.
- Around line 111-116: The Settings title currently uses
currentColors.backgroundSecondary; change it to use currentColors.textPrimary to
match other screen headers (e.g., SupportScreen's title) for consistent heading
color. Locate the Text composable rendering "Settings" in SettingsScreen (the
Text with style = EateryBlueTypography.h2) and update its color property from
currentColors.backgroundSecondary to currentColors.textPrimary; ensure no other
style or modifier changes are made.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SupportScreen.kt`:
- Around line 165-169: The arrow icon in SupportScreen's composable (the Icon
using Icons.Outlined.ArrowOutward) is tinted with colors.backgroundSecondary
which is the header/nav blue and not semantically appropriate; update the tint
to a semantic icon color such as colors.accentPrimary or colors.textSecondary to
match other icon styling in the screen and ensure consistency across the UI.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt`:
- Around line 78-109: The ThemeRow calls use redundant boolean comparisons
(lightMode == true, darkMode == true, systemMode == true); update the isSelected
arguments in the ThemeRow invocations to pass the boolean variables directly
(isSelected = lightMode, isSelected = darkMode, isSelected = systemMode) to
simplify code in ThemeSheet.kt and keep the onClick handlers unchanged.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/UpcomingMenuScreen.kt`:
- Around line 285-288: The UpcomingFilterRow currently defaults its
themeViewModel parameter to hiltViewModel(), which can create a ViewModel scoped
to the composable's destination and cause separate theme state; instead resolve
the theme at a higher level (e.g., in UpcomingMenuScreen) by collecting
ThemeViewModel.isDarkMode there and pass the boolean down to UpcomingFilterRow
(replace the themeViewModel parameter with an isDarkMode: Boolean or use
resolvedDarkMode), ensuring you reference ThemeViewModel, hiltViewModel(),
UpcomingFilterRow, UpcomingMenuScreen, isDarkMode and resolvedDarkMode when
locating and updating the code.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/theme/Color.kt`:
- Around line 5-20: Delete the legacy commented-out palette block in Color.kt
(the multi-line comment containing EateryBlue, LightBlue, Red, Green, Orange and
various colors.background... entries) so the theme file only contains the active
role-based palette; remove the entire comment block (the /* ... */ section) and
run formatter/compile to ensure no leftover references remain.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/FavoritesViewModel.kt`:
- Line 147: The view model is sorting by a UI color constant (sortedByDescending
{ it.availability.statusColor == Color.Green }) which couples ordering to
presentation; change the sort to use a semantic availability flag (e.g., use
Availability.isAvailable or a boolean on the item) instead. Update
FavoritesViewModel to sortByDescending on that boolean (e.g.,
it.availability.isAvailable) and, if the Availability/data model lacks such a
property, add a derived isAvailable getter on the Availability/data model (or
map availability status to a boolean in the view model) so ordering depends on
semantic state, not Color.Green.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt`:
- Around line 3-18: The listed imports in ThemeViewModel.kt are unused—remove
the lines importing android.annotation.SuppressLint,
androidx.compose.foundation.isSystemInDarkTheme,
androidx.compose.runtime.Composable,
com.cornellappdev.android.eatery.data.repositories.UserRepository,
com.cornellappdev.android.eatery.ui.theme.ColorMode, and
com.cornellappdev.android.eatery.ui.theme.ColorTheme; keep the remaining imports
(e.g., ViewModel, viewModelScope, UserPreferencesRepository, HiltViewModel,
coroutine flow imports) and then run your IDE's "Optimize/Organize Imports" to
verify no other unused imports remain.
- Around line 24-27: The val isDarkMode in ThemeViewModel is redundantly
wrapping repository.isDarkModeFlow (which is already a StateFlow) with stateIn;
remove the extra stateIn call and directly expose repository.isDarkModeFlow as
the isDarkMode StateFlow (ensuring the declared type matches the repository
flow's element type), i.e., assign isDarkMode = repository.isDarkModeFlow and
drop the viewModelScope/stateIn boilerplate.
- Around line 29-41: The three ViewModel methods are misnamed because they set
modes rather than toggling; rename toggleDarkMode to setDarkMode,
toggleLightMode to setLightMode, and toggleSystemMode to setSystemMode (or
setSystemModePreference if you prefer clearer wording) and update all call sites
accordingly; keep the existing calls to repository.setDarkMode(true/false) and
repository.setSystemMode(), only change the ViewModel method names
(ThemeViewModel.toggleDarkMode, ThemeViewModel.toggleLightMode,
ThemeViewModel.toggleSystemMode) and any imports/usages that reference them.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/UpcomingViewModel.kt`:
- Around line 107-109: Inline warning color 0xFFFFA500 is a magic literal;
define a named Color constant (e.g., WARNING_COLOR or WarningColor) and use it
instead of Color(0xFFFFA500) in UpcomingViewModel's status mapping. Add the
constant in a shared place (a companion object in UpcomingViewModel or a common
UI/colors object so other viewmodels can reuse it), replace the inline
Color(0xFFFFA500) in the isClosingSoon() branch with the new constant, and
update any other viewmodels to import/use the same constant for consistent
maintenance.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1fc8cba9-d136-42d1-b1a0-fd781baca059

📥 Commits

Reviewing files that changed from the base of the PR and between 82aa46c and b112204.

📒 Files selected for processing (82)
  • app/src/main/java/com/cornellappdev/android/eatery/MainActivity.kt
  • app/src/main/java/com/cornellappdev/android/eatery/data/repositories/UserPreferencesRepository.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/comparemenus/CompareMenusBotSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/comparemenus/CompareMenusFAB.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/AlertsSection.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/CalendarButton.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryDetailsStickyHeader.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryHourBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryMealTabs.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryMenusBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/FavoritesToggle.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/ItemFavoritesCard.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/PaymentWidgets.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/AppStoreRatingPopup.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/CalendarWeekSelector.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/CustomTextField.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/EateryCard.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FavoriteButton.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/FilterRow.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/MenuItems.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/NoEateryFound.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/PaymentMethodsAvailable.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/PaymentMethodsBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/PermissionRequestDialog.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/SearchBar.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/home/AnnouncementsPopUp.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/home/DietaryWidgets.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/home/EateryDetailsLoading.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/home/EateryHomeSection.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/home/MainLoading.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/AccountPage.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/login/LoginPage.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/notifications/FavoriteItemRow.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/onboarding/IconSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/onboarding/OnboardingCarousel.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/onboarding/OnboardingHeader.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/settings/AppIconBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/settings/ReportBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/settings/SettingsOption.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/settings/SwitchOption.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/upcoming/MealBottomSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/upcoming/MenuCard.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/components/upcoming/UpcomingLoading.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/navigation/MainTabbedNavigation.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/navigation/NavigationItem.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/AboutScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/CompareMenusScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/EateryDetailScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/FavoritesScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/HomeScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/LegalScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/NearestScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/NotificationsHomeScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/NotificationsSettingsScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/OnboardingScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/PrivacyScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ProfileScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SearchScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SupportScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/screens/UpcomingMenuScreen.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/theme/Color.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/theme/Theme.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/FavoritesViewModel.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/ThemeViewModel.kt
  • app/src/main/java/com/cornellappdev/android/eatery/ui/viewmodels/UpcomingViewModel.kt
  • app/src/main/java/com/cornellappdev/android/eatery/util/PreviewUtil.kt
  • app/src/main/proto/user_prefs.proto
  • app/src/main/res/drawable/dark_mode.xml
  • app/src/main/res/drawable/ic_brightness.xml
  • app/src/main/res/drawable/ic_calendar_selected_dark.xml
  • app/src/main/res/drawable/ic_grid_view_selected_dark.xml
  • app/src/main/res/drawable/ic_grid_view_unselected.xml
  • app/src/main/res/drawable/ic_grid_view_unselected_dark.xml
  • app/src/main/res/drawable/ic_home_selected_dark.xml
  • app/src/main/res/drawable/ic_list_view_selected_dark.xml
  • app/src/main/res/drawable/ic_list_view_unselected_dark.xml
  • app/src/main/res/drawable/ic_profile_selected_dark.xml
  • app/src/main/res/drawable/light_mode.xml
  • app/src/main/res/drawable/system_setting.xml
  • gradle/wrapper/gradle-wrapper.properties

Comment on lines +17 to +19
import com.cornellappdev.android.eatery.ui.theme.AppColorTheme
import com.cornellappdev.android.eatery.ui.theme.ColorTheme
import com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep a MaterialTheme wrapper at the root.

AppColorTheme only provides LocalColorMode; it does not install Material theme locals. With this change, any Material3 component under NavigationSetup falls back to library defaults instead of the app typography/theme values.

🎨 Proposed fix
+import androidx.compose.material3.MaterialTheme
 import com.cornellappdev.android.eatery.ui.theme.AppColorTheme
 import com.cornellappdev.android.eatery.ui.theme.ColorTheme
 import com.cornellappdev.android.eatery.ui.viewmodels.ThemeViewModel
@@
-            AppColorTheme(activeMode) {
-                NavigationSetup(hasOnboarded)
-            }
+            MaterialTheme(typography = typography) {
+                AppColorTheme(activeMode) {
+                    NavigationSetup(hasOnboarded)
+                }
+            }

Also applies to: 42-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/android/eatery/MainActivity.kt` around
lines 17 - 19, The root composable must install Material theme locals so
Material3 components get app typography and shapes: wrap the existing
AppColorTheme usage in MainActivity's setContent with the MaterialTheme
composable (the Material3 androidx.compose.material3.MaterialTheme) so that
NavigationSetup is called inside MaterialTheme (e.g., MaterialTheme {
AppColorTheme { NavigationSetup(...) } } or the equivalent ordering), leaving
ThemeViewModel/AppColorTheme intact but ensuring MaterialTheme locals are
provided to NavigationSetup and its children.

Comment on lines 136 to 146
colors = ButtonDefaults.buttonColors(
backgroundColor = if (selectedEateries.size < 2) GrayTwo else EateryBlue,
contentColor = if (selectedEateries.size < 2) GrayZero else Color.White
backgroundColor = if (selectedEateries.size < 2) colors.backgroundDefault92 else colors.accentPrimary,
contentColor = if (selectedEateries.size < 2) colors.backgroundDefault else currentColors.backgroundDefault
)
) {
Text(
text = if (selectedEateries.size < 2) "Select at least ${2 - selectedEateries.size} more"
else "Compare ${selectedEateries.size} now",
style = EateryBlueTypography.h5,
color = Color.White
color = colors.backgroundDefault
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Button text color may have poor contrast when disabled.

When selectedEateries.size < 2, the button background is colors.backgroundDefault92 and the text color is colors.backgroundDefault. These are likely similar shades, making the "Select at least X more" text nearly invisible.

Consider using a contrasting text color for the disabled state:

Proposed fix
         colors = ButtonDefaults.buttonColors(
             backgroundColor = if (selectedEateries.size < 2) colors.backgroundDefault92 else colors.accentPrimary,
-            contentColor = if (selectedEateries.size < 2) colors.backgroundDefault else currentColors.backgroundDefault
+            contentColor = if (selectedEateries.size < 2) colors.textSecondary else currentColors.backgroundDefault
         )
     ) {
         Text(
             text = if (selectedEateries.size < 2) "Select at least ${2 - selectedEateries.size} more"
             else "Compare ${selectedEateries.size} now",
             style = EateryBlueTypography.h5,
-            color = colors.backgroundDefault
+            color = if (selectedEateries.size < 2) colors.textSecondary else colors.backgroundDefault
         )
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
colors = ButtonDefaults.buttonColors(
backgroundColor = if (selectedEateries.size < 2) GrayTwo else EateryBlue,
contentColor = if (selectedEateries.size < 2) GrayZero else Color.White
backgroundColor = if (selectedEateries.size < 2) colors.backgroundDefault92 else colors.accentPrimary,
contentColor = if (selectedEateries.size < 2) colors.backgroundDefault else currentColors.backgroundDefault
)
) {
Text(
text = if (selectedEateries.size < 2) "Select at least ${2 - selectedEateries.size} more"
else "Compare ${selectedEateries.size} now",
style = EateryBlueTypography.h5,
color = Color.White
color = colors.backgroundDefault
)
colors = ButtonDefaults.buttonColors(
backgroundColor = if (selectedEateries.size < 2) colors.backgroundDefault92 else colors.accentPrimary,
contentColor = if (selectedEateries.size < 2) colors.textSecondary else currentColors.backgroundDefault
)
) {
Text(
text = if (selectedEateries.size < 2) "Select at least ${2 - selectedEateries.size} more"
else "Compare ${selectedEateries.size} now",
style = EateryBlueTypography.h5,
color = if (selectedEateries.size < 2) colors.textSecondary else colors.backgroundDefault
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/comparemenus/CompareMenusBotSheet.kt`
around lines 136 - 146, The disabled button state in CompareMenusBotSheet uses a
nearly identical background and text color (ButtonDefaults.buttonColors
backgroundColor = colors.backgroundDefault92 with contentColor =
colors.backgroundDefault), making the "Select at least X more" label hard to
read; change the disabled contentColor to a high-contrast color (e.g., a
disabled text or on-background color from your palette) in the
ButtonDefaults.buttonColors when selectedEateries.size < 2 and remove the
hard-coded color override on the Text (so the Text uses the button's content
color) by updating the ButtonDefaults.buttonColors call and the Text usage
around selectedEateries, ButtonDefaults.buttonColors, and the Text composable.


Divider(
color = GrayZero,
color = colors.backgroundDefault,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Divider color matches the header background, so the separator disappears.

Line 146 uses colors.backgroundDefault, which is the same tone used for the container background on Line 83.

💡 Suggested fix
-        Divider(
-            color = colors.backgroundDefault,
-            thickness = 1.dp
-        )
+        Divider(
+            color = colors.backgroundSecondary,
+            thickness = 1.dp
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/details/EateryDetailsStickyHeader.kt`
at line 146, The Divider in EateryDetailsStickyHeader currently uses
colors.backgroundDefault (the same as the container) so the separator is
invisible; update the Divider's color argument in the EateryDetailsStickyHeader
composable to a contrasting token (for example use colors.outline /
colors.surfaceVariant / onBackground.copy(alpha = ...) or another theme outline
color) so the divider is visible against the header background.

Comment on lines +48 to 49
backgroundColor = currentColors.accentPrimary
),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reset button text contrast is too low against its background.

backgroundColor = currentColors.accentPrimary with Text(color = currentColors.backgroundDefault) produces insufficient contrast and hurts readability.

Proposed fix
         Text(
             text = "Reset filters",
-            color =
-            currentColors.backgroundDefault
+            color = currentColors.textPrimary
         )

Also applies to: 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/NoEateryFound.kt`
around lines 48 - 49, The reset button in NoEateryFound (the Button where
backgroundColor = currentColors.accentPrimary) uses Text(color =
currentColors.backgroundDefault) which yields poor contrast; change the Text
color to a high-contrast token (e.g., currentColors.onAccentPrimary or use
contentColorFor(currentColors.accentPrimary)) so the label meets accessible
contrast, and apply the same change to the other Button instance referenced
(lines 56-57). Ensure you update the Text(...) color only for those Buttons or
use ButtonDefaults.buttonColors/contentColorFor to keep colors consistent.

Comment on lines 198 to +201
enum class PaymentMethodsAvailable(val drawable: Int, val color: Color, val text: String) {
BRB(drawable = R.drawable.ic_small_brbs, color = Red, text = "BRBs"),
CASH(drawable = R.drawable.ic_small_cash, color = Green, text = "Cash or credit"),
SWIPES(drawable = R.drawable.ic_small_swipes, color = EateryBlue, text = "Meal swipes");
BRB(drawable = R.drawable.ic_small_brbs, color = Color.Red, text = "BRBs"),
CASH(drawable = R.drawable.ic_small_cash, color = Color.Green, text = "Cash or credit"),
SWIPES(drawable = R.drawable.ic_small_swipes, color = Color(0xFF808080), text = "Meal swipes");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent dark mode support for inline text colors.

The enum's color property uses hardcoded colors (Color.Red, Color.Green, Color(0xFF808080)) which won't adapt to dark mode. Meanwhile, the icon tints at lines 124, 143, and 161 use theme-aware colors like currentColors.error and currentColors.success.

This creates visual inconsistency: the icons will change color in dark mode, but the inline text (via SpanStyle(color = paymentMethod.color) at line 53) will remain fixed.

💡 Potential approach

Since enum properties can't directly reference composable currentColors, consider either:

  1. Making the color property a function that accepts a ColorMode parameter
  2. Moving the color logic to where the SpanStyle is applied (line 53) using currentColors directly
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/components/general/PaymentMethodsAvailable.kt`
around lines 198 - 201, The enum PaymentMethodsAvailable currently stores
hardcoded Color values (property color) that don't adapt to dark mode, causing
text to remain fixed while icons use theme-aware colors (see icon tint usage
with currentColors.error/currentColors.success at the icon locations). Fix by
removing the hardcoded Color from the enum and instead resolve the color at
render time where SpanStyle is applied (the SpanStyle(color =
paymentMethod.color) usage), using the same theme-aware values used for icon
tints (currentColors.*), or alternatively change the enum to expose a
color-provider function (e.g., a method like getColor(currentColors) or a
lambda) and call that from the composable when building SpanStyle so text colors
follow dark mode like the icons.

Comment on lines 320 to 324
Text(
text = "Log out",
style = EateryBlueTypography.button
text = "Logged in as ${state.user.userName!!.substringBefore('@')}",
style = EateryBlueTypography.h5,
color = currentColors.textSecondary
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid force unwrap on nullable userName.

Using !! on state.user.userName will crash if the value is null. Use safe access with a fallback instead.

🛡️ Proposed fix
 Text(
-    text = "Logged in as ${state.user.userName!!.substringBefore('@')}",
+    text = "Logged in as ${state.user.userName?.substringBefore('@') ?: "Unknown"}",
     style = EateryBlueTypography.h5,
     color = currentColors.textSecondary
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Text(
text = "Log out",
style = EateryBlueTypography.button
text = "Logged in as ${state.user.userName!!.substringBefore('@')}",
style = EateryBlueTypography.h5,
color = currentColors.textSecondary
)
Text(
text = "Logged in as ${state.user.userName?.substringBefore('@') ?: "Unknown"}",
style = EateryBlueTypography.h5,
color = currentColors.textSecondary
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/SettingsScreen.kt`
around lines 320 - 324, The Text composable is force-unwrapping
state.user.userName using !! which can crash if userName is null; replace the
forced unwrap in the string expression (the usage in the Text call) with a safe
call and a fallback, e.g., use state.user.userName?.substringBefore('@') ?:
"<fallback>" (or another user-friendly default) so the UI won't crash when
userName is null.

Comment on lines +54 to +57
var darkMode by remember { mutableStateOf(false) }
var lightMode by remember { mutableStateOf(false) }
var systemMode by remember { mutableStateOf(false) }
val isSystemDark = isSystemInDarkTheme()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

State management can lead to invalid states and missing initialization.

Three separate booleans (darkMode, lightMode, systemMode) allow invalid states where all are false or multiple are true. Additionally, the initial selection doesn't reflect the user's current preference from ThemeViewModel.

Consider:

  1. Using a single state variable with an enum
  2. Initializing from the ViewModel's current state
Suggested refactor
+enum class ThemeSelection { LIGHT, DARK, SYSTEM, NONE }

 `@Composable`
 fun ThemeSheet(viewModel : ThemeViewModel = hiltViewModel(),
                 onDismiss : () -> Unit)
 {
     val coroutineScope = rememberCoroutineScope()
-    var darkMode by remember { mutableStateOf(false) }
-    var lightMode by remember { mutableStateOf(false) }
-    var systemMode by remember { mutableStateOf(false) }
-    val isSystemDark = isSystemInDarkTheme()
+    val currentIsDarkMode by viewModel.isDarkMode.collectAsState()
+    var selectedTheme by remember(currentIsDarkMode) {
+        mutableStateOf(
+            when (currentIsDarkMode) {
+                true -> ThemeSelection.DARK
+                false -> ThemeSelection.LIGHT
+                null -> ThemeSelection.SYSTEM
+            }
+        )
+    }

Then update the ThemeRow calls and Done button logic accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt`
around lines 54 - 57, Replace the three independent booleans (darkMode,
lightMode, systemMode) in ThemeSheet with a single sealed enum or enum class
(e.g., ThemeOption { DARK, LIGHT, SYSTEM }) stored in one remember {
mutableStateOf(...) } and initialize it from the ThemeViewModel's current theme
value (use the ViewModel property that indicates the user's preference) so the
UI reflects existing settings; update ThemeRow invocations to check/emit the
single ThemeOption value instead of individual booleans and adjust the Done
button logic to apply the selected ThemeOption (including handling SYSTEM by
using isSystemInDarkTheme() where needed) and persist via the ThemeViewModel
methods.

Comment on lines +111 to +134
Button(
onClick = {
if (darkMode) {
viewModel.toggleDarkMode()
} else if (lightMode) {
viewModel.toggleLightMode()
} else if (systemMode) {
viewModel.toggleSystemMode()
}
onDismiss()
},
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(32.dp),
colors = buttonColors(
containerColor = currentColors.backgroundSecondary,
contentColor = currentColors.textPrimary
)
)
{
Text(
"Done", fontWeight = FontWeight.Bold, textAlign = TextAlign.Center,
color = currentColors.oppTextPrimary
)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Done button silently does nothing if no option is selected.

If the user opens the sheet and clicks "Done" without selecting any option, onDismiss() is called but no preference is saved. Consider either:

  1. Pre-selecting the current theme on sheet open (see previous comment)
  2. Disabling the Done button until a selection is made
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/android/eatery/ui/screens/ThemeSheet.kt`
around lines 111 - 134, ThemeSheet currently calls onDismiss() from the Done
Button even when no selection was made, so the user's preference isn't saved;
update ThemeSheet to either pre-select the current theme when the sheet opens or
disable the Done button until a selection exists—simplest fix: track whether a
selection state (e.g., darkMode/lightMode/systemMode or a nullable selectedTheme
variable) is non-null and set Button(enabled = selectedTheme != null) for the
Done Button, and only invoke
viewModel.toggleDarkMode()/toggleLightMode()/toggleSystemMode() when a selection
is present before calling onDismiss(); ensure the Button text/semantics reflect
the disabled state so users know an option must be chosen.

Comment on lines +1 to +18
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="38dp"
android:height="28dp"
android:viewportWidth="38"
android:viewportHeight="28">
<path
android:pathData="M0,14C0,6.268 6.268,0 14,0H37.838V28H14C6.268,28 0,21.732 0,14Z"
android:fillColor="#272727"/>
<path
android:pathData="M12.864,6.811L24.972,6.811A0.757,0.757 0,0 1,25.729 7.568L25.729,9.081A0.757,0.757 0,0 1,24.972 9.838L12.864,9.838A0.757,0.757 0,0 1,12.107 9.081L12.107,7.568A0.757,0.757 0,0 1,12.864 6.811z"
android:fillColor="#4A90E2"/>
<path
android:pathData="M12.864,12.108L24.972,12.108A0.757,0.757 0,0 1,25.729 12.865L25.729,14.378A0.757,0.757 0,0 1,24.972 15.135L12.864,15.135A0.757,0.757 0,0 1,12.107 14.378L12.107,12.865A0.757,0.757 0,0 1,12.864 12.108z"
android:fillColor="#4A90E2"/>
<path
android:pathData="M12.864,17.405L24.972,17.405A0.757,0.757 0,0 1,25.729 18.162L25.729,19.676A0.757,0.757 0,0 1,24.972 20.432L12.864,20.432A0.757,0.757 0,0 1,12.107 19.676L12.107,18.162A0.757,0.757 0,0 1,12.864 17.405z"
android:fillColor="#4A90E2"/>
</vector>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

home_file="$(fd -i 'HomeScreen.kt' app/src/main/java | head -n1)"
if [ -z "${home_file:-}" ]; then
  echo "HomeScreen.kt not found"
  exit 1
fi

echo "Inspecting icon mapping block in: $home_file"
sed -n '595,615p' "$home_file"

echo
echo "Drawable references used in HomeScreen:"
rg -n 'ic_list_view_(selected|unselected)(_dark)?' "$home_file"

Repository: cuappdev/eatery-blue-android

Length of output: 1960


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Searching for list view drawables ==="
fd -e xml 'ic_list_view' app/src/main/res/drawable*/

echo
echo "=== Searching for grid view drawables (for comparison) ==="
fd -e xml 'ic_grid_view' app/src/main/res/drawable*/

echo
echo "=== All drawable files in drawable directories ==="
ls -la app/src/main/res/drawable*/ 2>/dev/null | grep -E '(ic_list_view|ic_grid_view)' || echo "No matches found"

Repository: cuappdev/eatery-blue-android

Length of output: 1321


Fix selected list-view icon mapping for light mode.

The list-view icon selection logic at line 603 in HomeScreen.kt incorrectly falls back to ic_list_view_unselected in light mode. When not in grid view and not in dark mode (!isGridView && !isDarkMode), the selected state should display ic_list_view_selected, not the unselected icon.

Fix
- else {R.drawable.ic_list_view_unselected}),
+ else {R.drawable.ic_list_view_selected}),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/res/drawable/ic_list_view_selected_dark.xml` around lines 1 -
18, In HomeScreen.kt update the icon mapping for the list-view selection branch:
where the code checks the booleans isGridView and isDarkMode (the branch for
!isGridView && !isDarkMode) it currently returns ic_list_view_unselected —
change that to return the selected drawable ic_list_view_selected so the
selected state shows the correct light-mode icon; keep all other dark-mode and
grid-view branches unchanged.

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What Gradle versions are officially supported by Android Gradle Plugin 8.1.1? Please include the Android Developers compatibility table.

💡 Result:

Android Gradle Plugin (AGP) 8.1.1 officially requires Gradle 8.0 (minimum). It is compatible with Gradle 8.0 and higher versions up to the maximum tested by Gradle at the time, typically up to 8.4 or similar, but higher versions may work. For best performance with Kotlin DSL, Gradle 8.1 is recommended. The official Android Developers compatibility table from https://developer.android.com/build/releases/about-agp lists: Plugin version | Minimum required Gradle version 8.1 | 8.0 This applies to AGP 8.1.x including 8.1.1, as confirmed by the shared compatibility section for AGP 8.1 in release notes. Patch releases like 8.1.1 do not change Gradle requirements. Gradle compatibility matrix confirms testing with AGP 8.0/8.1.

Citations:


🏁 Script executed:

# Find and inspect build.gradle to confirm AGP version
fd -t f 'build.gradle' -x cat -n {} \; | head -20

Repository: cuappdev/eatery-blue-android

Length of output: 932


Use a Gradle version within the tested compatibility matrix for AGP 8.1.1.

Gradle 8.13 exceeds the officially tested range for AGP 8.1.1 (minimum Gradle 8.0, typically tested up to ~8.4). While the minimum requirement is met, untested version combinations can introduce build instability. Consider downgrading to a version within the tested matrix, such as Gradle 8.4 or earlier.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle/wrapper/gradle-wrapper.properties` at line 4, The gradle-wrapper
properties currently point to Gradle 8.13 which is outside AGP 8.1.1's tested
compatibility; update the distributionUrl in gradle-wrapper.properties (the
distributionUrl entry) to a supported version such as gradle-8.4-bin.zip (or
another version within the AGP 8.1.1 compatibility matrix) to ensure a tested
Gradle/AGP combination and avoid potential build instability.

Copy link
Copy Markdown
Contributor

@caleb-bit caleb-bit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to postpone review for now because of merge conflicts and also becaues this PR includes all the changes for dark mode because the destination is set to main. Generally you want your PR diffs to reflect the PR description. There are two better options:

  • Start all feature branches from main, keeping separate features on separate branches.
  • Set the PR destination to the dark mode branch so that it's only the minor settings UI change that appears in the diffs. This is more useful for cases (maybe this one) where a feature depends on another feature.

For now, the easiest fix looks like

  1. Change the destination to the dark mode branch. (You should be able to merge this by yourself)
  2. Include this change in the PR description for dark mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants