Skip to content

Refactor widget prefs 6177951123037805482#118

Closed
harrydbarnes wants to merge 19 commits intomainfrom
refactor-widget-prefs-6177951123037805482
Closed

Refactor widget prefs 6177951123037805482#118
harrydbarnes wants to merge 19 commits intomainfrom
refactor-widget-prefs-6177951123037805482

Conversation

@harrydbarnes
Copy link
Owner

Refactored DayAheadWidget and WidgetUpdateWorker to use UserPreferencesRepository for better architectural consistency. Added summary flow and location check to the repository.

google-labs-jules bot and others added 19 commits January 20, 2026 07:02
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Implemented permission result handling in MainActivity to refresh data or show feedback.
- Replaced hardcoded SimpleDateFormat with DateUtils in CalendarCard to respect user time format preference.
- Added TODO in MainViewModel regarding hardcoded news category.
- Replaced e.printStackTrace() with Log.e() in repositories for better error tracking.
- Added TAG constants to repositories.
- Implemented permission result handling in MainActivity.
- Replaced hardcoded date format with DateUtils in CalendarCard.
- Re-implemented dynamic news category selection in MainViewModel.
- Added isLoading state to MainViewModel.
- Replaced e.printStackTrace() with Log.e() in repositories.
- Updated repositories to return Boolean success/failure status.
- Implemented transactional replaceAll in ArticleDao/NewsRepository to prevent data loss.
- Implemented retry logic in WidgetUpdateWorker based on refresh success.
- Created missing colors.xml to fix build failure.
- Implemented settings navigation in HomeScreen.
- Implemented permission result handling in MainActivity.
- Replaced hardcoded date format with DateUtils in CalendarCard.
- Re-implemented dynamic news category selection in MainViewModel.
- Added isLoading state to MainViewModel.
- Fixed combine function signature in MainViewModel to handle 8 flows.
- Replaced e.printStackTrace() with Log.e() in repositories.
- Updated repositories to return Boolean success/failure status.
- Implemented transactional replaceAll in ArticleDao/NewsRepository to prevent data loss.
- Implemented retry logic in WidgetUpdateWorker based on refresh success.
- Created missing colors.xml to fix build failure.
- Implemented settings navigation in HomeScreen.
…Repository.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Implemented permission result handling in MainActivity.
- Replaced hardcoded date format with DateUtils in CalendarCard.
- Re-implemented dynamic news category selection in MainViewModel.
- Added isLoading state to MainViewModel.
- Fixed combine function signature in MainViewModel to handle 8 flows.
- Replaced e.printStackTrace() with Log.e() in repositories.
- Updated repositories to return Boolean success/failure status.
- Implemented transactional replaceAll in ArticleDao/NewsRepository to prevent data loss.
- Implemented retry logic in WidgetUpdateWorker based on refresh success.
- Created missing colors.xml to fix build failure.
- Implemented settings navigation in HomeScreen.
- Fixed syntax error in CalendarRepository.
- Implemented permission result handling in MainActivity.
- Replaced hardcoded date format with DateUtils in CalendarCard.
- Re-implemented dynamic news category selection in MainViewModel.
- Added isLoading state to MainViewModel.
- Refactored MainViewModel combine logic to use chained calls for type safety.
- Replaced e.printStackTrace() with Log.e() in repositories and DayAheadWidget.
- Updated repositories to return Boolean success/failure status.
- Implemented transactional replaceAll in ArticleDao/NewsRepository.
- Implemented retry logic in WidgetUpdateWorker.
- Created missing colors.xml to fix build failure.
- Implemented settings navigation in HomeScreen.
- Fixed CalendarRepository syntax error and extracted magic number.
- Added @JvmStatic to AppUtils for Java interop.
- Extracted Hilt versions in build.gradle.
- Added null/blank title filtering in NewsRepository.
- Implemented permission result handling in MainActivity.
- Replaced hardcoded date format with DateUtils in CalendarCard.
- Re-implemented dynamic news category selection in MainViewModel.
- Added isLoading state to MainViewModel.
- Refactored MainViewModel combine logic to use chained calls for type safety.
- Replaced e.printStackTrace() with Log.e() in repositories and DayAheadWidget.
- Updated repositories to return Boolean success/failure status.
- Implemented transactional replaceAll in ArticleDao/NewsRepository.
- Implemented retry logic in WidgetUpdateWorker.
- Created missing colors.xml to fix build failure.
- Implemented settings navigation in HomeScreen.
- Fixed CalendarRepository syntax error and extracted magic number.
- Added @JvmStatic to AppUtils for Java interop.
- Extracted Hilt versions in build.gradle.
- Added null/blank title filtering in NewsRepository.
- Implemented location fetching in MainActivity and updated MainViewModel.
- Updated Geocoder usage for API 33+.
- Updated `fetchLocationName` in `MainViewModel` to use `suspendCancellableCoroutine` for the Tiramisu `Geocoder` API, preventing a race condition where the coroutine scope would close before the callback fired.
- Refactored `DayAheadWidget` to inject `WeatherRepository` instead of `WeatherDao` and `Gson`.
- Simplified `DayAheadWidget.onUpdate` to fetch parsed weather data directly from the repository flow, removing data access and parsing logic from the UI component.
- Created `UserPreferencesRepository` to encapsulate SharedPreferences access and expose flows for user preferences.
- Updated `MainViewModel` to inject `UserPreferencesRepository` instead of direct SharedPreferences usage.
- Fixed race condition in `MainViewModel` Geocoder logic by implementing `GeocodeListener`.
- Updated `HomeScreen` to launch `SettingsActivity` on weather card click.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Refactored DayAheadWidget and WidgetUpdateWorker to use UserPreferencesRepository instead of accessing SharedPreferences directly.
This improves architectural consistency and centralizes data access logic.

Changes:
- Updated UserPreferencesRepository to expose summary flow and hasLocation method.
- Updated DayAheadWidget to inject UserPreferencesRepository and collect summary flow.
- Updated WidgetUpdateWorker to inject UserPreferencesRepository and use it for location check, preference retrieval, and summary saving.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @harrydbarnes, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a comprehensive architectural upgrade, transitioning the application from a legacy Java-based Android View system to a modern Kotlin-first stack. By adopting Jetpack Compose for the user interface, Hilt for dependency injection, and Room for local data persistence, the changes significantly enhance the app's maintainability, scalability, and overall developer experience. The refactoring centralizes data management through a new repository layer, ensuring a more robust and consistent approach to handling information across all features, including the DayAhead widget.

Highlights

  • Migration to Kotlin and Jetpack Compose: The application has undergone a significant rewrite, migrating core components like MainActivity and DayAheadWidget from Java to Kotlin and adopting Jetpack Compose for the UI. This replaces the old RecyclerView-based layout system with a modern declarative UI framework.
  • Introduction of Hilt for Dependency Injection: Hilt, a dependency injection library for Android, has been integrated into the project. This improves modularity, testability, and simplifies dependency management across the application, including DayAheadWidget and MainViewModel.
  • Implementation of Repository Pattern with Room Persistence: Data fetching and caching logic for weather, news, calendar, and fun facts have been refactored into dedicated repository classes (WeatherRepository, NewsRepository, CalendarRepository, FunFactRepository). These repositories now utilize the Room persistence library for local data storage, improving offline capabilities and data consistency.
  • Refactored Widget Update Worker: The WidgetUpdateWorker has been updated to leverage the new repository pattern and Hilt for dependency injection. This ensures that widget data updates are consistent with the application's new data flow architecture.
  • Streamlined ViewModel Logic: The MainViewModel has been refactored to use Kotlin Flow and StateFlow for reactive data handling, delegating data operations entirely to the new repository layer. This simplifies the ViewModel's responsibilities and improves its testability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request refactors the DayAheadWidget and WidgetUpdateWorker to use UserPreferencesRepository for better architectural consistency. It also adds summary flow and location check to the repository. The changes include migrating from Java to Kotlin, incorporating Hilt for dependency injection, Room for local data persistence, and Compose for UI. The MainActivity is also converted to Kotlin and uses Compose for the UI. The DashboardAdapter, associated layouts, and older models are removed as part of the migration to Compose.

<uses-permission android:name="android.permission.health.READ_STEPS" />

<application
android:name=".TheLoopApplication"
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Adding android:name to the application tag is crucial for Hilt to initialize correctly. This ensures that Hilt's application component is properly set up.

Comment on lines +4 to +5
id 'org.jetbrains.kotlin.kapt' version '1.9.10'
id 'com.google.dagger.hilt.android'
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

It's good to see Hilt integrated for dependency injection. However, ensure that kotlin-kapt is applied before dagger.hilt.android to avoid potential issues with annotation processing order.

Comment on lines +23 to +26
lateinit var weatherRepository: WeatherRepository

@Inject
lateinit var userPreferencesRepository: UserPreferencesRepository
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using @Inject lateinit var for dependency injection is correct here. Consider using constructor injection instead for better testability and clarity.

Comment on lines +33 to 35
if (!userPreferencesRepository.hasLocation()) {
return Result.success()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Returning Result.success() when userPreferencesRepository.hasLocation() is false might not be the best approach. It might be better to return Result.failure() or Result.retry() to indicate that the worker needs to be retried when location data is available.

Comment on lines +142 to 145
suspend fun fetchWeather(lat: Double, lon: Double) {
fetchLocationName(lat, lon)
weatherRepo.refresh(lat, lon, userPrefsRepo.tempUnit.first())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Consider wrapping the fetchLocationName and weatherRepo.refresh calls in a try-catch block to handle potential exceptions and ensure that errors are properly handled.

Comment on lines +35 to +37
// Return true to prevent WidgetUpdateWorker from retrying indefinitely
return@withContext true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Returning true when the calendar permission is not granted might prevent the worker from retrying when the permission is eventually granted. Consider returning false and handling the permission check in the MainActivity to trigger a refresh when the permission is granted.

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.

1 participant