Skip to content

Conversation

@ashtanko
Copy link
Owner

@ashtanko ashtanko commented Mar 22, 2025

Summary by CodeRabbit

  • New Features

    • Added a new Brown theme with light and dark variants, plus contrast options.
    • Expanded Yellow and Orange themes with consistent color schemes and contrast variants.
  • Style

    • Updated theme mappings: Mint themes now use the Brown palette; Experimental theme now uses updated Yellow Dark scheme.
    • Refined overall theming by delegating color schemes to dedicated theme sets for more consistent visuals.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 22, 2025

Walkthrough

The PR adds new theme classes (Yellow, Orange, Brown), updates MaterialTheme to use them, introduces Brown theme support, and adjusts theme mapping in ThemeCubit. It abstracts EmailListRepository into an interface with an implementation, wires it through DI (GetIt/Injectable and providers), adds a basic ThemeItem widget, and updates tests to use a mock.

Changes

Cohort / File(s) Summary
Theme system extraction and additions
lib/theme/style.dart, lib/theme/yellow/yellow_theme.dart, lib/theme/orange/orange_theme.dart, lib/theme/brown/brown_theme.dart, lib/theme/color_family.dart, lib/theme/extended_color.dart
Extracts color schemes into dedicated theme classes (Yellow, Orange), adds Brown theme and helper classes; MaterialTheme now delegates to these classes and exposes brownLight/brownDark.
Theme mapping in BLoC
lib/bloc/theme/theme_cubit.dart
Updates AppTheme mappings: lightMint → brownLight, darkMint → brownDark, experimental → yellowDark.
Repository abstraction and implementation
lib/repository/email_list_repository.dart
Converts EmailListRepository to an abstract class; adds EmailListRepositoryImpl with concrete loadData().
Dependency injection (GetIt/Injectable)
lib/di/di_initializer.config.dart, lib/di/di_repository_module.dart, lib/di/app_repository_providers.dart
Adds RepositoryModule factory for EmailListRepository, registers EmailListRepository via module, and updates provider to use EmailListRepositoryImpl. Adjusts generated module wrapper placement.
UI component
lib/features/settings/theme_item.dart
Adds placeholder StatelessWidget ThemeItem.
Tests
test/repository/email_list_repository_test.dart
Refactors test to mock EmailListRepository and stub loadData().

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant App
  participant GetIt as DI Container
  participant RepoModule as RepositoryModule
  participant UI as Widget/Bloc
  participant Repo as EmailListRepositoryImpl

  User->>App: Launch
  App->>GetIt: init()
  GetIt->>RepoModule: construct
  GetIt->>GetIt: register factory EmailListRepository = RepoModule.provide()
  UI->>GetIt: resolve EmailListRepository
  GetIt-->>UI: EmailListRepositoryImpl
  UI->>Repo: loadData()
  Repo-->>UI: Future<List<Email>>
Loading
sequenceDiagram
  autonumber
  actor User
  participant ThemeCubit
  participant MaterialTheme
  participant ThemeData

  User->>ThemeCubit: select AppTheme.darkMint
  ThemeCubit->>MaterialTheme: brownDark()
  MaterialTheme-->>ThemeCubit: ThemeData (Brown dark scheme)
  ThemeCubit-->>ThemeData: emit/update
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I twitched my ears at hues anew,
Brown and yellow joined the crew.
Repos split—impls in line,
DI burrows working fine.
Widgets nibble themes with cheer,
Mocked tests hop without a fear.
Thump-thump—release is near! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Refactor themes" accurately and concisely describes the primary purpose of the changeset: extracting and reorganizing theme definitions (new Yellow/Orange/Brown theme classes), introducing ExtendedColor/ColorFamily types, and updating MaterialTheme and theme mappings (including theme_cubit). It is short, focused, and gives a reviewer a clear sense of the PR's intent without unnecessary detail.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/refactor_themes

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
Contributor

@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: 2

🧹 Nitpick comments (7)
lib/theme/brown/brown_theme.dart (1)

3-309: Well-structured theme implementation.

The BrownTheme class provides a comprehensive set of color schemes for different brightness levels and contrast requirements. The code is well-organized and follows a consistent pattern for defining color schemes.

One suggestion to consider for future improvements would be to extract common color values into constants to reduce duplication, especially for colors that appear in multiple schemes.

lib/theme/orange/orange_theme.dart (2)

3-7: Inconsistent class design compared to BrownTheme.

Unlike BrownTheme, OrangeTheme accepts a TextTheme in its constructor and stores it as a member variable, but it's not used in any of the static methods. Consider either:

  1. Making the methods non-static and using the textTheme member variable, or
  2. Removing the constructor and textTheme field to make it consistent with BrownTheme
-class OrangeTheme {
-  OrangeTheme(this.textTheme);
-
-  final TextTheme textTheme;
+class OrangeTheme {

8-313: Inconsistent method naming convention.

The method naming convention in OrangeTheme (e.g., orangeLightScheme()) differs from BrownTheme (e.g., lightScheme()). This inconsistency can make the API less intuitive. Consider standardizing the naming convention across all theme classes for better maintainability.

For example, rename methods to match BrownTheme's convention:

-static ColorScheme orangeLightScheme() {
+static ColorScheme lightScheme() {

And similarly for the other methods.

lib/theme/yellow/yellow_theme.dart (3)

3-53: Consider reducing duplication or adding documentation.

The yellowLightScheme() function is quite verbose. You could reduce duplication across similar methods (e.g. grouping shared values, extracting a helper) or add brief doc comments explaining the purpose of specific color sets to improve maintainability.


157-206: Optional doc comments could improve clarity.

The yellowDarkScheme() function seems correct. A short explanation describing the intent (e.g., usage scenario, recommended background color) can help newer developers.


208-257: Possible candidate for reduced repetition or a single parameterized function.

yellowDarkMediumContrastScheme() replicates many values from other variants, which can lead to duplication. Consider a pattern to share common color definitions across your theme variants.

lib/theme/style.dart (1)

36-36: Possible redundant comment.

The //BrownTheme comment may be superfluous since the method names themselves convey that these are Brown theme variants. Consider removing it if it doesn’t add clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c83ba7 and a77dbf3.

📒 Files selected for processing (14)
  • lib/app/app.dart (1 hunks)
  • lib/bloc/theme/theme_cubit.dart (1 hunks)
  • lib/di/di_initializer.config.dart (3 hunks)
  • lib/di/di_repository_module.dart (2 hunks)
  • lib/features/settings/theme_item.dart (1 hunks)
  • lib/repository/email_list_repository.dart (1 hunks)
  • lib/theme/brown/brown_theme.dart (1 hunks)
  • lib/theme/color_family.dart (1 hunks)
  • lib/theme/extended_color.dart (1 hunks)
  • lib/theme/orange/orange_theme.dart (1 hunks)
  • lib/theme/style.dart (1 hunks)
  • lib/theme/yellow/yellow_theme.dart (1 hunks)
  • pubspec.yaml (1 hunks)
  • test/repository/email_list_repository_test.dart (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
test/repository/email_list_repository_test.dart

[error] 34-34: MissingStubError: 'loadData'. No stub was found which matches the arguments of this method call: loadData(). Add a stub for this method using Mockito's 'when' API, or generate the MockEmailListRepository mock with the @GenerateNiceMocks annotation.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (25)
pubspec.yaml (1)

98-98: No effective change in Flutter intl configuration

The line appears to be unchanged in terms of functionality, as it remains enabled: true before and after the changes.

lib/theme/color_family.dart (1)

5-25: Good implementation of ColorFamily class with proper value equality

The ColorFamily class is well-structured and follows good practices:

  • Uses Equatable for value-based equality
  • Has properly documented required parameters
  • Follows immutable pattern with final fields
  • Includes all properties in the props list for equality comparison

This will provide a strong foundation for your theme system refactoring, enabling consistent color definitions across different themes.

lib/di/di_repository_module.dart (2)

3-3: Added import for EmailListRepository

The import statement correctly brings in the necessary EmailListRepository class.


14-16:

✅ Verification successful

Properly registered EmailListRepository in DI container

The implementation correctly uses the @factoryMethod annotation to register the EmailListRepositoryImpl as the implementation for EmailListRepository interface. This follows dependency injection best practices by:

  1. Allowing the interface to be injected rather than the concrete implementation
  2. Using the factory method pattern for creating instances
  3. Maintaining consistency with other repository registrations in this file

🏁 Script executed:

#!/bin/bash
# Check if EmailListRepository is properly implemented as an abstract class
# with EmailListRepositoryImpl as its concrete implementation

echo "Checking EmailListRepository implementation:"
rg -A 10 "abstract class EmailListRepository" 
echo "Checking EmailListRepositoryImpl implementation:"
rg -A 10 "class EmailListRepositoryImpl implements EmailListRepository"

Length of output: 1647


DI Registration Verified: The EmailListRepository is Registered Correctly

  • The interface and implementation are defined as expected in lib/repository/email_list_repository.dart:
    • EmailListRepository is correctly declared as an abstract class.
    • EmailListRepositoryImpl properly implements the interface.
  • The DI registration in lib/di/di_repository_module.dart uses the @factoryMethod annotation to provide EmailListRepositoryImpl for the EmailListRepository interface, following dependency injection best practices.

The verification confirms that the current implementation correctly follows the intended DI pattern. No further changes are needed.

lib/bloc/theme/theme_cubit.dart (2)

12-12: Theme mapping updated for lightMint

The theme mapping for AppTheme.lightMint has been changed from using yellowLightMediumContrast() to brownLight(), which aligns with the new theme refactoring approach. This change is consistent with the PR objective of refactoring themes.


15-16: Theme mappings updated for darkMint and experimental themes

The theme mappings have been appropriately updated:

  • AppTheme.darkMint now uses brownDark() instead of yellowDarkMediumContrast()
  • AppTheme.experimental now uses yellowDark() instead of yellowDarkMediumContrast()

These changes are part of the broader theme system refactoring which appears to organize color schemes into more specific theme classes.

lib/theme/extended_color.dart (1)

6-37: Well-structured ExtendedColor class for theme management

The newly added ExtendedColor class provides a comprehensive structure for managing colors across different theme modes and contrast levels. It appropriately extends Equatable for value equality comparison and includes all necessary properties for the theme system refactoring.

The class design follows good practices:

  • Clear constructor with required parameters
  • Proper field declarations
  • Overridden props getter for equality comparison

This is a good addition to the theme system that will help manage colors consistently.

lib/di/di_initializer.config.dart (4)

24-25: Added import for EmailListRepository

The import for EmailListRepository has been properly added to support the dependency injection registration.


48-48: Repositioned DIDataModule declaration

The declaration of dIDataModule has been moved but maintains its functionality.


51-53: Added dependency injection for EmailListRepository

The factory registration for EmailListRepository has been added to the dependency injection container. This aligns with the broader refactoring to move from context-based repository providers to direct retrieval via dependency injection.


74-74: Repositioned DIDataModule class declaration

The class declaration for _$DIDataModule has been repositioned without functional changes.

lib/repository/email_list_repository.dart (2)

6-8: Good use of abstraction to improve design.

The introduction of an abstract EmailListRepository class establishes a clear contract through the loadData() method, which is a good application of the dependency inversion principle. This abstraction will make it easier to test and potentially implement alternative data sources in the future.


10-17: Implementation looks good.

The concrete implementation EmailListRepositoryImpl properly implements the interface and maintains the original functionality. This refactoring allows for better separation of concerns and improves testability.

lib/app/app.dart (2)

34-35: DI approach improved with direct container retrieval.

Good refactoring from context-based repository retrieval to direct dependency injection with diContainer.get<EmailListRepository>(). This approach is more explicit and removes the dependency on the BuildContext for retrieving repositories.


41-42: Consistent DI pattern application.

The same container-based DI approach is correctly applied here for the LaunchesRepository, maintaining consistency throughout the codebase.

lib/theme/yellow/yellow_theme.dart (3)

55-104: Looks good overall.

The yellowLightMediumContrastScheme() method follows the same structure as the light scheme. No issues spotted; contrast values appear logically consistent. Consider adding doc comments for clarity.


106-155: All good.

The yellowLightHighContrastScheme() is properly defined, with no evident errors. This keeps the code style consistent.


259-309: Implementation is consistent with the rest.

The yellowDarkHighContrastScheme() approach is aligned with the other theme definitions. No further issues noted.

lib/theme/style.dart (7)

2-5: Imports look appropriate.

These newly added imports correctly reference the new theme files. No concerns here.


13-13: Straightforward usage of the new theme method.

yellowLight() correctly delegates to YellowTheme.yellowLightScheme(). No issues found.


17-17: Proper dark scheme usage.

yellowDark() calls YellowTheme.yellowDarkScheme(). This follows the expected pattern.


21-21: Implementation aligns with new OrangeTheme.

orangeLight() correctly references OrangeTheme.orangeLightScheme(). No concerns.


25-25: Dark variant usage is consistent.

orangeDark() references OrangeTheme.orangeDarkScheme() in a similar manner. Looks good.


28-29: Brown dark theme logic is fine.

brownDark() simply delegates to BrownTheme.darkScheme(). No issues spotted.


32-33: Brown light theme logic is fine.

brownLight() calls BrownTheme.lightScheme(). This matches the established pattern.

Comment on lines +3 to +10
class ThemeItem extends StatelessWidget {
const ThemeItem({super.key});

@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

ThemeItem widget is incomplete and needs implementation details

The current implementation uses a Placeholder widget, which is only meant for development and not for production use. For a proper theme item widget in a settings screen, you should:

  1. Include properties to represent theme data (name, colors, etc.)
  2. Implement a visual preview of the theme
  3. Add selection mechanism (typically with a radio button or highlight)
  4. Connect to the theme system for actual theme switching

Consider implementing a more complete version:

 class ThemeItem extends StatelessWidget {
-  const ThemeItem({super.key});
+  const ThemeItem({
+    super.key,
+    required this.themeName,
+    required this.isSelected,
+    required this.onSelect,
+    required this.themeColor,
+  });
+
+  final String themeName;
+  final bool isSelected;
+  final VoidCallback onSelect;
+  final Color themeColor;

   @override
   Widget build(BuildContext context) {
-    return const Placeholder();
+    return InkWell(
+      onTap: onSelect,
+      child: Container(
+        padding: const EdgeInsets.all(16),
+        decoration: BoxDecoration(
+          border: Border.all(
+            color: isSelected ? themeColor : Colors.grey.shade300,
+            width: isSelected ? 2 : 1,
+          ),
+          borderRadius: BorderRadius.circular(8),
+        ),
+        child: Row(
+          children: [
+            Container(
+              width: 24,
+              height: 24,
+              decoration: BoxDecoration(
+                color: themeColor,
+                shape: BoxShape.circle,
+              ),
+            ),
+            const SizedBox(width: 16),
+            Text(themeName),
+            const Spacer(),
+            if (isSelected)
+              Icon(Icons.check_circle, color: themeColor),
+          ],
+        ),
+      ),
+    );
   }
 }
📝 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
class ThemeItem extends StatelessWidget {
const ThemeItem({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
import 'package:flutter/material.dart';
class ThemeItem extends StatelessWidget {
const ThemeItem({
super.key,
required this.themeName,
required this.isSelected,
required this.onSelect,
required this.themeColor,
});
final String themeName;
final bool isSelected;
final VoidCallback onSelect;
final Color themeColor;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onSelect,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(
color: isSelected ? themeColor : Colors.grey.shade300,
width: isSelected ? 2 : 1,
),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: themeColor,
shape: BoxShape.circle,
),
),
const SizedBox(width: 16),
Text(themeName),
const Spacer(),
if (isSelected) Icon(Icons.check_circle, color: themeColor),
],
),
),
);
}
}

@codacy-production
Copy link

codacy-production bot commented Mar 22, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
-0.86% (target: -1.00%) 34.69%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (897fdcf) 3907 3127 80.04%
Head commit (93591cb) 3918 (+11) 3102 (-25) 79.17% (-0.86%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#3) 49 17 34.69%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

# Conflicts:
#	lib/app/app.dart
#	lib/di/di_initializer.config.dart
Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
lib/di/di_repository_module.dart (2)

18-20: Consider singleton lifecycle for repository

If EmailListRepository holds caches/state, prefer a lazy singleton to prevent multiple instances.

Optional diff:

-  @factoryMethod
-  EmailListRepository provideEmailListRepository() => EmailListRepositoryImpl();
+  @lazySingleton
+  EmailListRepository provideEmailListRepository() => EmailListRepositoryImpl();

15-16: Method name “provideAccidentsRepository” is misleading

It returns ThemeRepository; rename for clarity and regenerate DI.

Suggested diff:

-  ThemeRepository provideAccidentsRepository(ThemeStorage themeStorage) =>
+  ThemeRepository provideThemeRepository(ThemeStorage themeStorage) =>
       ThemeRepositoryImpl(themeStorage);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bab3cc4 and 93591cb.

📒 Files selected for processing (4)
  • lib/bloc/theme/theme_cubit.dart (1 hunks)
  • lib/di/app_repository_providers.dart (1 hunks)
  • lib/di/di_initializer.config.dart (3 hunks)
  • lib/di/di_repository_module.dart (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/bloc/theme/theme_cubit.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Flutter Integration Tests (31)
  • GitHub Check: App
🔇 Additional comments (1)
lib/di/di_initializer.config.dart (1)

32-33: Generated wiring looks correct; avoid manual edits

EmailListRepository is registered via repositoryModule; wrapper _$RepositoryModule is present. If you switch to @lazySingleton or rename provideThemeRepository, re-run code generation.

Also applies to: 57-57, 61-63, 92-93

Comment on lines +15 to 16
create: (context) => EmailListRepositoryImpl(),
),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Unify DI source to avoid duplicate EmailListRepository instances

Directly instantiating EmailListRepositoryImpl here while also registering EmailListRepository in GetIt can yield two separate instances and divergent state/caches. Fetch it from GetIt like the other repositories.

Apply this diff:

       RepositoryProvider<EmailListRepository>(
-        create: (context) => EmailListRepositoryImpl(),
+        create: (context) => diContainer.get<EmailListRepository>(),
       ),
📝 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
create: (context) => EmailListRepositoryImpl(),
),
RepositoryProvider<EmailListRepository>(
create: (context) => diContainer.get<EmailListRepository>(),
),
🤖 Prompt for AI Agents
In lib/di/app_repository_providers.dart around lines 15 to 16, the provider is
directly instantiating EmailListRepositoryImpl which can create a separate
instance from the one registered in GetIt; replace the direct construction with
retrieving the singleton from GetIt (e.g., use
GetIt.instance.get<EmailListRepository>() or the project's getIt helper) so the
provider returns the same registered EmailListRepository; also add the GetIt
import if missing and remove any unused direct-impl import.

@codecov
Copy link

codecov bot commented Sep 18, 2025

Codecov Report

❌ Patch coverage is 34.69388% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.83%. Comparing base (897fdcf) to head (93591cb).

Files with missing lines Patch % Lines
lib/theme/extended_color.dart 0.00% 11 Missing ⚠️
lib/theme/color_family.dart 0.00% 7 Missing ⚠️
lib/theme/orange/orange_theme.dart 28.57% 5 Missing ⚠️
lib/theme/brown/brown_theme.dart 33.33% 4 Missing ⚠️
lib/theme/yellow/yellow_theme.dart 33.33% 4 Missing ⚠️
lib/repository/email_list_repository.dart 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #3      +/-   ##
==========================================
- Coverage   84.90%   83.83%   -1.08%     
==========================================
  Files         150      155       +5     
  Lines        3194     3205      +11     
==========================================
- Hits         2712     2687      -25     
- Misses        482      518      +36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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