Skip to content

Conversation

@fulleni
Copy link
Member

@fulleni fulleni commented Nov 25, 2025

Status

READY

Description

This pull request significantly refactors the application's settings management and administrative interface. It generalizes user-specific application settings into a broader 'AppSettings' model, impacting core BLoC logic and data repositories. The 'App Configuration' page has been completely reorganized into new 'General', 'Features', and 'User' tabs for improved usability. Ad-related settings have been streamlined, and the 'excerpt' field has been removed from headline content management, simplifying the overall configuration and content creation experience.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

- Update core dependency to latest version
- Update ref in pubspec.yaml and pubspec.lock
[WHAT]: Refactors the `AppConfigurationPage` to implement the new three-tab structure: "App", "Features", and "User".

[WHY]: This is the central step in aligning the UI with the new `RemoteConfig` model. It replaces the old structure with a new one that directly reflects the hierarchical `app`, `features`, and `user` properties of the model, improving clarity and maintainability.

[HOW]: The `TabController` length is changed to 3. The `TabBar` is updated with the new, admin-centric localized tab titles. The `TabBarView` is updated to render the three new tab widgets: `AppConfigurationTab`, `FeaturesConfigurationTab`, and `UserConfigurationTab`, passing the `remoteConfig` and `onConfigChanged` callback to each.
[WHAT]: Creates three new tab view widgets: `AppConfigurationTab`, `FeaturesConfigurationTab`, and `UserConfigurationTab`.

[WHY]: These widgets form the new top-level UI structure for the App Configuration page, directly corresponding to the `app`, `features`, and `user` properties of the new `RemoteConfig` model. This decomposition is essential for creating a maintainable, model-driven UI.

[HOW]: Each file defines a `StatelessWidget` that accepts the `RemoteConfig` model and an `onConfigChanged` callback. They will serve as containers for the various configuration forms, organized into `ExpansionTile` widgets that reflect the nested model structure.
[WHAT]: Creates new form widgets for `MaintenanceConfig`, `UpdateConfig`, `GeneralAppConfig`, and `NavigationAdConfiguration`.

[WHY]: These new widgets are required to manage the settings for the corresponding new models in the `RemoteConfig` structure. They encapsulate the form logic for these specific configuration sections, making the UI modular and easier to manage.

[HOW]: Each form is a `StatefulWidget` that manages its own `TextEditingController`s and binds to the respective sub-model within `RemoteConfig`. They use the shared `AppConfigTextField` and `SwitchListTile` widgets to ensure UI consistency and propagate changes up via the `onConfigChanged` callback.
[WHAT]: Creates the `UserLimitsConfigForm` widget.

[WHY]: This widget replaces the old `UserPreferenceLimitsForm` and is responsible for managing the simple, role-based integer limits (`followedItems`, `savedHeadlines`) found in the new `UserLimitsConfig` model.

[HOW]: The widget uses a `TabBar` to switch between user roles (`Guest`, `Standard`, `Premium`). For each role, it displays `AppConfigIntField` widgets bound to the corresponding values in the `remoteConfig.user.limits` map, ensuring a clear and organized UI for managing role-based limits.
[WHAT]: Refactors `AdConfigForm` and `AdPlatformConfigForm` to align with the new `AdConfig` and `AdPlatformIdentifiers` models.

[WHY]: The old forms were based on a different model structure. This refactoring is necessary to correctly bind the UI to the new, simplified ad configuration models. `AdConfigForm` now only handles the global `enabled` switch. `AdPlatformConfigForm` is updated to manage the new generic ad IDs (`nativeAdId`, `bannerAdId`, `interstitialAdId`).

[HOW]: In `AdConfigForm`, the logic is simplified to a single `SwitchListTile` bound to `remoteConfig.features.ads.enabled`. In `AdPlatformConfigForm`, the `_buildAdUnitIdentifierFields` method is rewritten to create `AppConfigTextField`s for the three new generic ad IDs, and the `onChanged` logic is updated to use the new `AdPlatformIdentifiers.copyWith` method.
[WHAT]: Refactors `FeedAdSettingsForm` and `FeedDecoratorForm` to use the new `FeaturesConfig` model paths.

[WHY]: These forms need to be updated to read from and write to the correct locations within the new `RemoteConfig.features` structure.

[HOW]: The `remoteConfig` access path is updated in both widgets. For `FeedAdSettingsForm`, it now accesses `remoteConfig.features.ads.feedAdConfiguration`. For `FeedDecoratorForm`, it now accesses `remoteConfig.features.feed.decorators`. The internal `copyWith` logic is updated to correctly rebuild the nested state object.
[WHAT]: Refactors the `PushNotificationSettingsForm` to align with the new `PushNotificationConfig` model.

[WHY]: The form's data binding needs to be updated to point to the new location of the push notification configuration within the main `RemoteConfig` state object.

[HOW]: The widget is updated to access its configuration from `remoteConfig.features.pushNotifications`. The `onChanged` callbacks are updated to use the correct `copyWith` path: `remoteConfig.copyWith(features: features.copyWith(pushNotifications: ...))`.
[WHAT]: Refactors `SavedFilterLimitsSection` and `SavedFilterLimitsForm` to bind to the new `UserLimitsConfig` model.

[WHY]: These widgets were previously bound to a different part of the configuration. They must be updated to read from and write to the `savedHeadlineFilters` and `savedSourceFilters` maps within `remoteConfig.user.limits`.

[HOW]: In `SavedFilterLimitsSection`, the `ExpansionTile`s are updated to pass the correct `SavedFilterLimitsForm` widgets. In `SavedFilterLimitsForm`, the `_getLimitsForRole` and `_onValueChanged` methods are completely rewritten to access and update the `UserLimitsConfig` model via `remoteConfig.user.limits`, using the correct nested `copyWith` logic.
- Remove 'hide AppStatus' directive from core package import
- This change simplifies the import statement and removes confusion about unused hidden elements
- Add app-wide settings tab and labels
- Introduce new sections for maintenance mode, updates, and general app settings
- Include navigation ad settings and frequency configuration
- Add labels for ad unit IDs and saved headlines limit
- Ensure new labels are included in both English and Arabic ARB files
- Modify the key of ExpansionTile in UserConfigurationTab
- Change from a constant ValueKey to a unique ValueKey based on expandedIndex
- This ensures that each ExpansionTile has a unique key, improving the widget's ability to rebuild correctly when its state changes
…ildScrollView

This change improves the layout by making the navigation ad settings form scrollable,
which helps to prevent overflow errors on smaller screens or when the keyboard is displayed.
- Add SingleChildScrollView to wrap the column of AppConfigIntField widgets
- This change allows the content to be scrollable and avoid overflow issues
- Improve user interface usability on smaller screens or when keyboard is open
- Remove unnecessary helper methods and direct map access
- Consolidate limits update logic into more concise functions
- Rename variables and methods to better reflect their purpose
- Improve code readability and maintainability
- Change controller keys for notification subscriptions from 'type.name' to 'notification_type.name'
- Update code to reflect new keys in both initialization and value update
- Improve readability and maintainability of the code
- Removed the export statement for 'in_article_ad_slot_type_l10n.dart' from the extensions.dart file.
- This change helps to clean up unused code and reduce potential clutter in the project.
…ed classes

- Rename UserAppSettings to AppSettings
- Update class references in AppBloc, AppEvent, and AppState
- Modify property names and method calls to use the new AppSettings class
- Adjust variable names to match
This commit updates the bootstrap file to align with changes in the core package.
Specifically, `UserAppSettings` has been renamed to `AppSettings`, and the `Headline`
model no longer includes an `excerpt` field. The `DataClient` and `DataRepository`
instantiations have been updated to use `AppSettings`, and the `headlinesFixturesData`
 is now mapped to remove the `excerpt` field to prevent compilation errors.
    This commit modifies the `App` widget and its state to use the new `AppSettings`
    model instead of `UserAppSettings`. It also updates the theme logic to correctly
    handle the `FeedItemClickBehavior` enum, replacing the deprecated `internalNavigation`
    with `defaultBehavior` to ensure compatibility with the updated core package.
…ting

- Change DataInMemory<UserAppSettings> to DataInMemory<AppSettings>
- Update logger name in appSettingsClient initialization
- Modify DataApi<AppSettings> to use 'app_settings' instead of 'user_app_settings'
- Update DataRepository<AppSettings> reference
- Improve code formatting in data client initializations
    This commit refactors the `AppBloc` to align with the updated core package models.
    `UserAppSettings` is replaced by `AppSettings`, and `FeedDisplayPreferences` is
    replaced by `FeedSettings`. The default settings creation logic is adjusted to
    use the new `FeedSettings` properties, including `feedItemDensity`, `feedItemImageStyle`,
    and `feedItemClickBehavior`, while removing obsolete fields.
    This commit updates the `AppUserAppSettingsChanged` event to use the `AppSettings`
    model instead of the deprecated `UserAppSettings` model, ensuring type consistency
    across the application's global state management.
    This commit modifies the `AppState` to hold an `AppSettings` object instead of
    `UserAppSettings`, aligning with the core package model changes. The `copyWith`
    method and `props` list are updated accordingly.
    This commit removes the `excerpt` field from `CreateHeadlineState` and updates
    the `isFormValid` getter, `copyWith` method, and `props` list. This change
    reflects the removal of the `excerpt` field from the `Headline` model in the
    core package.
…event

    This commit removes the `CreateHeadlineExcerptChanged` event as the `excerpt`
    field is no longer part of the `Headline` model in the core package.
    This commit removes all logic related to the `excerpt` field from the
    `CreateHeadlineBloc`, including its event handler and its usage when
    constructing new `Headline` objects, to align with the updated `Headline`
    model in the core package.
    This commit removes the `TextFormField` for the `excerpt` field and its
    corresponding controller and validation logic from `CreateHeadlinePage`.
    This change is necessary because the `excerpt` field has been removed
    from the `Headline` model in the core package.
    This commit removes the `excerpt` field from `EditHeadlineState` and updates
    the `isFormValid` getter, `copyWith` method, and `props` list. This change
    reflects the removal of the `excerpt` field from the `Headline` model in the
    core package.
    This commit removes the `EditHeadlineExcerptChanged` event as the `excerpt`
    field is no longer part of the `Headline` model in the core package.
    This commit removes all logic related to the `excerpt` field from the
    `EditHeadlineBloc`, including its event handler, its population during loading,
    and its usage when updating `Headline` objects, to align with the updated
    `Headline` model in the core package.
    This commit removes the `TextFormField` for the `excerpt` field and its
    corresponding controller and state update logic from `EditHeadlinePage`.
    This change is necessary because the `excerpt` field has been removed
    from the `Headline` model in the core package.
…ings

    This commit refactors the `SettingsBloc` to align with the updated core package
    models. `UserAppSettings` is replaced by `AppSettings`, and `FeedDisplayPreferences`
    is replaced by `FeedSettings`. The default settings creation logic is adjusted
    to use the new `FeedSettings` properties, including `feedItemDensity`,
    `feedItemImageStyle`, and `feedItemClickBehavior`, while removing obsolete fields.
    This commit modifies the `SettingsState` to hold an `AppSettings` object instead
    of `UserAppSettings`, aligning with the core package model changes. The `props`
    list is updated accordingly.
    This commit updates the `SettingsPage` to use the `AppSettings` model instead
    of `UserAppSettings` for its `SettingsBloc` and `AppBloc` interactions, ensuring
    type consistency with the updated core package.
- Remove unused variable 'features' in FeaturesConfigurationTab build method
- This change simplifies the code by removing an unnecessary variable assignment
- Set pagination limit to 20 for initial fetch to ensure proper infinite scrolling functionality
- Added comment提醒 do not lower the limit below 20 for the initial fetch
- Update core package reference from c0c41c0 to 3779a8b
- This update ensures the project uses the latest version of the core package
…I strings

- Replace MaintenanceConfigForm with a simple SwitchListTile for better maintainability
- Update Arabic and English localization strings for app update management and legal information
- Remove unused import of MaintenanceConfigForm
- Adjust expansion tile titles to use new localized strings
@gemini-code-assist
Copy link

gemini-code-assist bot commented Nov 25, 2025

Summary of Changes

Hello @fulleni, 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 significantly refactors the application's settings management and administrative interface. It generalizes user-specific application settings into a broader 'AppSettings' model, impacting core BLoC logic and data repositories. The 'App Configuration' page has been completely reorganized into new 'General', 'Features', and 'User' tabs for improved usability. Ad-related settings have been streamlined, and the 'excerpt' field has been removed from headline content management, simplifying the overall configuration and content creation experience.

Highlights

  • App Settings Refactor: The application's settings management has been refactored by renaming 'UserAppSettings' to 'AppSettings' across the codebase, including BLoCs, states, and repositories, to generalize application-wide settings.
  • App Configuration UI Overhaul: The administrative 'App Configuration' page has been completely restructured into three new, more intuitive tabs: 'General', 'Features', and 'User'. This replaces the previous 'General', 'Feed', and 'Advertisements' tabs for a clearer organization of settings.
  • Simplified Ad Management: Ad configuration forms have been consolidated and simplified. Specific 'article ad' and 'interstitial ad' settings have been removed in favor of a new 'Navigation Ad Settings' form, which manages interstitial ad frequency based on internal and external navigations.
  • Headline Excerpt Removal: The 'excerpt' field has been removed from the headline creation and editing flows, simplifying the content management process by reducing unnecessary fields.
  • Localization Updates: New localization keys have been added to support the redesigned app configuration UI and updated terminology, ensuring the application remains translatable and user-friendly across different languages.
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

@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

This pull request introduces a significant and well-executed refactoring across the application. The changes primarily focus on restructuring the remote configuration, renaming UserAppSettings to AppSettings for clarity, and simplifying various models and UI components. The new organization of the 'App Configuration' page into 'General', 'Features', and 'User' tabs is a great improvement for maintainability. The code modernization using sealed and final classes is also a welcome change. Overall, the codebase is cleaner and more organized. I have one minor suggestion to replace a magic number with a constant to further improve code clarity.

- Change 'Do nto' to 'Do not' in a comment within the SearchableSelectionBloc class
@fulleni fulleni merged commit 615e5ba into main Nov 25, 2025
1 check failed
@fulleni fulleni deleted the aa branch November 25, 2025 19:41
@github-project-automation github-project-automation bot moved this from Backlog to Done in Flutter News App Project Nov 25, 2025
@fulleni fulleni restored the aa branch November 25, 2025 19:44
@fulleni fulleni deleted the aa branch November 25, 2025 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants