Skip to content

fix(color-picking): Fix color picking failure and card overflow#998

Merged
lollipopkit merged 6 commits intolollipopkit:mainfrom
GT-610:fix/color-picking
Jan 10, 2026
Merged

fix(color-picking): Fix color picking failure and card overflow#998
lollipopkit merged 6 commits intolollipopkit:mainfrom
GT-610:fix/color-picking

Conversation

@GT-610
Copy link
Copy Markdown
Collaborator

@GT-610 GT-610 commented Jan 10, 2026

Summary by CodeRabbit

  • New Features

    • Conditional dynamic color theming that follows system dynamic colors when available, with a saved-color-seed fallback.
  • Improvements

    • Primary color editor pre-fills current hex, updates live with picker, validates and saves immediately.
    • "Follow System" option shown only when dynamic color is available.
    • Slightly increased card height for layout.
    • App bar styling flattened by removing scrolled-under elevation.

✏️ Tip: You can customize this high-level summary in your review settings.

And uniformly set the scrolledUnderElevation of the AppBar to 0 to optimize visual effects
… updates

Add initial value display for the color seed input box on the settings page

Modify the color saving logic to notify the application of theme updates

Retrieve the system's primary color setting upon application startup

Optimize the theme color synchronization logic
Adjust the card height constant value from 108.0 to 110.0
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 10, 2026

Walkthrough

Dynamic color handling and settings for the app color seed were updated: ThemeData now uses colorSchemeSeed and app bars set scrolledUnderElevation = 0.0; settings pre-fill/validate the seed editor and conditionally show "Follow System". A card height constant was increased.

Changes

Cohort / File(s) Summary
Dynamic Color Theming
lib/app.dart
_buildDynamicColor() now constructs ThemeData with colorSchemeSeed (light/dark), adds appBarTheme.scrolledUnderElevation = 0.0, and falls back to stored seed from Stores.setting.colorSeed.fetch() when system seeds are unavailable. Assigns UIs.primaryColor and UIs.colorSeed before building app.
Settings — Color Seed Editor
lib/view/page/setting/entries/app.dart
Editor pre-fills the hex value, updates the text controller on color pick, validates and saves hex to settings, updates UIs.primaryColor/UIs.colorSeed when applicable, notifies RNodes.app, and only shows the color picker when not following system color.
Settings — Imports / Parts
lib/view/page/setting/entry.dart
Added import 'package:dynamic_color/dynamic_color.dart'; and reordered part directive for AI entries.
Layout Adjustment
lib/view/page/server/tab/tab.dart
Increased _kCardHeightNormal from 108.0 to 110.0.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant Stores as Stores.setting
    participant ThemeBuilder as _buildDynamicColor/_build
    participant UIState as UIs
    participant SettingsUI as AppSettings

    App->>Stores: read useSystemPrimaryColor
    alt system primary enabled
        App->>ThemeBuilder: _buildDynamicColor()
        ThemeBuilder->>Stores: fetch system light/dark seed (dynamic_color)
        ThemeBuilder->>ThemeBuilder: build ThemeData with colorSchemeSeed + appBarTheme(scrolledUnderElevation=0.0)
        ThemeBuilder->>UIState: set primaryColor & colorSeed
    else system primary disabled
        App->>ThemeBuilder: _build()
        ThemeBuilder->>Stores: fetch stored colorSeed
        ThemeBuilder->>UIState: set primaryColor & colorSeed
    end
    SettingsUI->>Stores: open color editor (pre-filled)
    SettingsUI->>SettingsUI: pick/validate hex → save to Stores
    SettingsUI->>UIState: update primaryColor & colorSeed (if not following system)
    UIState->>App: apply updated theme
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • fix: code editor tool bar #933: Modifies lib/app.dart dynamic color handling and propagation of UIs.colorSeed, closely related to the ThemeData and color-seed changes here.

Poem

🐰 I found a little hex today,
I nudged the theme to find its way.
System seeds or one I keep,
App bars calm, no shadows creep.
A tiny hop, the colors play.

🚥 Pre-merge checks | ✅ 3
✅ 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 'fix(color-picking): Fix color picking failure and card overflow' accurately describes the main changes: addressing color picking issues and fixing a 2-pixel card overflow problem, aligning with the PR objectives and file modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ffca571 and 7f47852.

📒 Files selected for processing (2)
  • lib/app.dart
  • lib/view/page/setting/entries/app.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/app.dart
  • lib/view/page/setting/entries/app.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). (1)
  • GitHub Check: check

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
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: 0

Caution

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

⚠️ Outside diff range comments (1)
lib/app.dart (1)

65-93: Potential color inconsistency when dynamic colors are unavailable.

If both light and dark are null (on platforms that don't support dynamic colors), the theme will use Flutter's default color scheme, but UIs.primaryColor and UIs.colorSeed won't be updated. This could cause inconsistency between the applied theme and UI elements that directly reference UIs.primaryColor.

Consider adding a fallback to update UIs values when dynamic colors are unavailable:

🔧 Suggested fix
         if (context.isDark && dark != null) {
           UIs.primaryColor = dark.primary;
           UIs.colorSeed = dark.primary;
         } else if (!context.isDark && light != null) {
           UIs.primaryColor = light.primary;
           UIs.colorSeed = light.primary;
+        } else {
+          // Fallback when dynamic colors unavailable
+          final fallback = Color(Stores.setting.colorSeed.fetch());
+          UIs.primaryColor = fallback;
+          UIs.colorSeed = fallback;
         }
🧹 Nitpick comments (2)
lib/app.dart (1)

28-29: Unused fetch result appears to be dead code.

The fetch() call on line 29 is executed but its return value is discarded. If this is intended for cache warming, consider adding a comment. Otherwise, this line can be removed since fetch() is called again inside the ListenableBuilder on line 34.

🔧 Suggested fix
   _setup(context);
-
-   Stores.setting.useSystemPrimaryColor.fetch();

   return ListenableBuilder(
lib/view/page/setting/entries/app.dart (1)

131-144: Consider also updating UIs.primaryColor for consistency.

The _onSaveColor method updates UIs.colorSeed but not UIs.primaryColor. In lib/app.dart, both values are updated together. While the subsequent RNodes.app.notify() will trigger a rebuild that updates both, there's a brief window where these values could be inconsistent.

🔧 Suggested fix
   void _onSaveColor(String s) {
     final color = s.fromColorHex;

     if (color == null) {
       context.showSnackBar(libL10n.fail);
       return;
     }

     UIs.colorSeed = color;
+    UIs.primaryColor = color;
     _setting.colorSeed.put(color.value255);

     RNodes.app.notify();
     context.pop();
   }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ceeaf7 and b0611a8.

📒 Files selected for processing (3)
  • lib/app.dart
  • lib/view/page/server/tab/tab.dart
  • lib/view/page/setting/entries/app.dart
🧰 Additional context used
📓 Path-based instructions (1)
lib/view/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

lib/view/**/*.dart: Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)
Prefer using libL10n strings before adding new ones to project l10n
Split UI into build, actions, and utils; use extension on to separate concerns

Files:

  • lib/view/page/server/tab/tab.dart
  • lib/view/page/setting/entries/app.dart
🔇 Additional comments (3)
lib/view/page/server/tab/tab.dart (1)

347-350: LGTM!

The card height adjustment from 108.0 to 110.0 resolves the 2-pixel overflow issue as described in the PR objectives.

lib/app.dart (1)

43-63: LGTM!

The static color theme implementation correctly reads the color seed from settings, updates the UIs singleton, and constructs consistent light/dark themes with the appBarTheme adjustment.

lib/view/page/setting/entries/app.dart (1)

88-129: LGTM!

The color picker implementation follows fl_lib patterns and correctly:

  • Pre-fills the text field with the current color seed hex value
  • Conditionally shows the color picker based on useSystemPrimaryColor setting
  • Handles iOS platform limitation for the dynamic_color plugin

@GT-610
Copy link
Copy Markdown
Collaborator Author

GT-610 commented Jan 10, 2026

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)

lib/app.dart (1)> 65-93: Potential color inconsistency when dynamic colors are unavailable.

If both light and dark are null (on platforms that don't support dynamic colors), the theme will use Flutter's default color scheme, but UIs.primaryColor and UIs.colorSeed won't be updated. This could cause inconsistency between the applied theme and UI elements that directly reference UIs.primaryColor.
Consider adding a fallback to update UIs values when dynamic colors are unavailable:

🔧 Suggested fix

         if (context.isDark && dark != null) {
           UIs.primaryColor = dark.primary;
           UIs.colorSeed = dark.primary;
         } else if (!context.isDark && light != null) {
           UIs.primaryColor = light.primary;
           UIs.colorSeed = light.primary;
+        } else {
+          // Fallback when dynamic colors unavailable
+          final fallback = Color(Stores.setting.colorSeed.fetch());
+          UIs.primaryColor = fallback;
+          UIs.colorSeed = fallback;
         }

🧹 Nitpick comments (2)

lib/app.dart (1)> 28-29: Unused fetch result appears to be dead code.

The fetch() call on line 29 is executed but its return value is discarded. If this is intended for cache warming, consider adding a comment. Otherwise, this line can be removed since fetch() is called again inside the ListenableBuilder on line 34.

🔧 Suggested fix

   _setup(context);
-
-   Stores.setting.useSystemPrimaryColor.fetch();

   return ListenableBuilder(

lib/view/page/setting/entries/app.dart (1)> 131-144: Consider also updating UIs.primaryColor for consistency.

The _onSaveColor method updates UIs.colorSeed but not UIs.primaryColor. In lib/app.dart, both values are updated together. While the subsequent RNodes.app.notify() will trigger a rebuild that updates both, there's a brief window where these values could be inconsistent.

🔧 Suggested fix

   void _onSaveColor(String s) {
     final color = s.fromColorHex;

     if (color == null) {
       context.showSnackBar(libL10n.fail);
       return;
     }

     UIs.colorSeed = color;
+    UIs.primaryColor = color;
     _setting.colorSeed.put(color.value255);

     RNodes.app.notify();
     context.pop();
   }

📜 Review details

@coderabbitai Noticed this. This might impact systems without dynamic color or light/dark switch (Android 9-, Windows, etc.) I think, but I don't know if it really matters.

But it won't cause any bugs. Investigating.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@GT-610: I can help with the investigation! Let me examine how UIs.primaryColor and UIs.colorSeed are used throughout the codebase to better understand the potential impact.


🏁 Script executed:

#!/bin/bash

# Find usages of UIs.primaryColor and UIs.colorSeed
echo "=== Usages of UIs.primaryColor ==="
rg -nP 'UIs\.primaryColor' -C 2

echo -e "\n\n=== Usages of UIs.colorSeed ==="
rg -nP 'UIs\.colorSeed' -C 2

# Check the UIs class definition to understand these properties
echo -e "\n\n=== UIs class definition ==="
fd -e dart -x grep -l "class UIs" | head -1 | xargs cat

# Check when _buildDynamicColor is called and how dynamic color availability is determined
echo -e "\n\n=== Dynamic color builder usage ==="
rg -nP 'DynamicColorBuilder|_buildDynamicColor' -C 3

Length of output: 6895


Based on the investigation, here's what I found:

Key Findings

The concern is valid. Here's the issue:

  1. Fallback exists for ThemeData but not for UIs values:

    • Line 70 in _buildDynamicColor() has: final colorSeed = lightSeed ?? darkSeed ?? Color(Stores.setting.colorSeed.fetch());
    • This ensures ThemeData gets the correct colorSchemeSeed even when dynamic colors are unavailable
    • However, UIs.primaryColor and UIs.colorSeed are only updated in lines 83-89 when light or dark are not null
  2. Wide usage of UIs.primaryColor:

    • Text styling in multiple pages (SFTP, SSH, Ping)
    • Terminal cursor color
    • Chart colors (CircleChart, LineChart)
    • Progress bars
    • Settings color preview
  3. The scenario where this matters:

    • User enables "Use System Primary Color" on a platform without dynamic color support
    • Both light and dark from DynamicColorBuilder will be null
    • ThemeData will correctly use the stored color seed
    • But UI elements directly referencing UIs.primaryColor will have stale/inconsistent values

Impact

On platforms like Android 9-, Windows, etc., if users toggle the "Use System Primary Color" setting:

  • Theme colors will be correct
  • But direct color references (charts, text highlights, etc.) may show the wrong color until the next full rebuild

The suggested fallback in the review comment would fix this inconsistency. Would you like to implement it?

Add the dynamic_color dependency to support dynamic theme colors

When the system does not support dynamic colors, use the stored default color as a fallback

Optimize the display logic of dynamic color options in the settings page
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
lib/view/page/setting/entries/app.dart (1)

97-127: Fix blank dialog edge case when useSystemPrimaryColor is true but system colors aren't available (or on iOS).

The ColorPicker visibility depends only on _setting.useSystemPrimaryColor.fetch() (line 118). When that flag is true on iOS (where the switch is never shown due to if (!isIOS)) or on platforms where dynamic colors are unsupported (light and dark are null, so the switch shows SizedBox.shrink()), the dialog content becomes empty—no way to change the color.

The proposed fix moves DynamicColorBuilder to the top level and gates the ColorPicker by !followSystemEnabled instead of just the stored flag. This ensures the ColorPicker always appears when system color following is unavailable, preventing the blank dialog.

Proposed adjustment (gate by "supported AND enabled", not just the stored flag)
-            child: StatefulBuilder(
-              builder: (context, setState) {
-                final children = <Widget>[
-                  if (!isIOS)
-                    DynamicColorBuilder(
-                      builder: (light, dark) {
-                        final supported = light != null || dark != null;
-                        if (!supported) return const SizedBox.shrink();
-                        return ListTile(
-                          title: Text(l10n.followSystem),
-                          trailing: StoreSwitch(
-                            prop: _setting.useSystemPrimaryColor,
-                            callback: (_) => setState(() {}),
-                          ),
-                        );
-                      },
-                    ),
-                ];
-                if (!_setting.useSystemPrimaryColor.fetch()) {
-                  children.add(
-                    ColorPicker(
-                      color: Color(_setting.colorSeed.fetch()),
-                      onColorChanged: (c) => ctrl.text = c.toHex,
-                    ),
-                  );
-                }
-                return Column(mainAxisSize: MainAxisSize.min, children: children);
-              },
-            ),
+            child: StatefulBuilder(
+              builder: (context, setState) => DynamicColorBuilder(
+                builder: (light, dark) {
+                  final supported = light != null || dark != null;
+                  final followSystemEnabled =
+                      !isIOS && supported && _setting.useSystemPrimaryColor.fetch();
+
+                  final children = <Widget>[
+                    if (!isIOS && supported)
+                      ListTile(
+                        title: Text(l10n.followSystem),
+                        trailing: StoreSwitch(
+                          prop: _setting.useSystemPrimaryColor,
+                          callback: (_) => setState(() {}),
+                        ),
+                      ),
+                    if (!followSystemEnabled)
+                      ColorPicker(
+                        color: Color(_setting.colorSeed.fetch()),
+                        onColorChanged: (c) => ctrl.text = c.toHex,
+                      ),
+                  ];
+
+                  return Column(mainAxisSize: MainAxisSize.min, children: children);
+                },
+              ),
+            ),
🤖 Fix all issues with AI agents
In @lib/view/page/setting/entries/app.dart:
- Around line 136-149: _inSaveColor currently updates UIs.colorSeed and persists
the value via _setting.colorSeed.put but leaves UIs.primaryColor unchanged,
causing a transient desync; update the method to also set UIs.primaryColor =
color (before calling RNodes.app.notify) so UI reads the new primary color
immediately, and ensure you still persist via _setting.colorSeed.put and then
call RNodes.app.notify() and context.pop() as before.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0611a8 and 6cc16eb.

📒 Files selected for processing (3)
  • lib/app.dart
  • lib/view/page/setting/entries/app.dart
  • lib/view/page/setting/entry.dart
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/app.dart
🧰 Additional context used
📓 Path-based instructions (1)
lib/view/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

lib/view/**/*.dart: Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)
Prefer using libL10n strings before adding new ones to project l10n
Split UI into build, actions, and utils; use extension on to separate concerns

Files:

  • lib/view/page/setting/entry.dart
  • lib/view/page/setting/entries/app.dart
🧠 Learnings (2)
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/view/**/*.dart : Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)

Applied to files:

  • lib/view/page/setting/entry.dart
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/view/**/*.dart : Split UI into build, actions, and utils; use extension on to separate concerns

Applied to files:

  • lib/view/page/setting/entry.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). (1)
  • GitHub Check: check
🔇 Additional comments (2)
lib/view/page/setting/entry.dart (2)

31-34: Part reorder looks safe; just ensure no top-level side effects depend on part order.


4-4: No action needed. The dynamic_color v1.6.6 API is correctly used. The DynamicColorBuilder signature (builder receives nullable ColorScheme? for light/dark) matches the documented API, and the codebase already properly handles the null values on unsupported platforms (e.g., desktop, older Android) with explicit checks and fallbacks in entries/app.dart. The library-level import is appropriate for the part-based file structure.

…n updating the application theme color

When modifying the application theme color, in addition to updating the colorSeed, the primaryColor is now also set synchronously to maintain UI consistency
@GT-610
Copy link
Copy Markdown
Collaborator Author

GT-610 commented Jan 10, 2026

Screenshot_1768046742

I added a logic that directly hide "Follow system" feature when the device does not support this feature.

This screenshot is taken from Android 9, which does not have dynamic color support.

@coderabbitai Please review.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Check the current implementation in lib/view/page/setting/entries/app.dart
# to see how the "Follow system" option is conditionally displayed
echo "=== lib/view/page/setting/entries/app.dart implementation ==="
cat lib/view/page/setting/entries/app.dart

echo -e "\n\n=== lib/app.dart implementation ==="
cat lib/app.dart

Length of output: 17941


@GT-610, excellent work! 🎉 Your implementation looks great. Let me break down what I found:

✅ All Major Concerns Addressed

1. Dynamic Color UI Hiding (lib/view/page/setting/entries/app.dart, lines 103-120)

Perfect implementation! The DynamicColorBuilder wrapping with the supported check elegantly hides the "Follow System" option when light and dark are both null. This prevents users from enabling a feature their device can't support.

final supported = light != null || dark != null;
if (!supported) return const SizedBox.shrink();

2. Fallback Logic (lib/app.dart, lines 91-95)

You've added exactly the fallback I suggested! When dynamic colors are unavailable, it now properly updates UIs.primaryColor and UIs.colorSeed with the stored seed:

} else {
  final fallbackColor = Color(Stores.setting.colorSeed.fetch());
  UIs.primaryColor = fallbackColor;
  UIs.colorSeed = fallbackColor;
}

This ensures consistency across the app even on platforms without dynamic color support.

3. Color Consistency (lib/view/page/setting/entries/app.dart, lines 137-138)

The _onSaveColor method now correctly updates both values:

UIs.primaryColor = color;
UIs.colorSeed = color;

🧹 Minor Remaining Nitpick

Line 29 in lib/app.dart still has an unused fetch() call:

Stores.setting.useSystemPrimaryColor.fetch();

The return value is discarded, and fetch() is called again on line 34 inside the ListenableBuilder. Unless this is intentional cache warming (in which case a comment would be helpful), this line can be removed.

Summary

Your changes comprehensively address the color inconsistency concerns on platforms without dynamic color support (Android 9-, Windows, etc.). The implementation is clean, defensive, and user-friendly. Great job! 👍

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Fetch the current state of lib/app.dart to check if the fallback logic was added
echo "=== lib/app.dart (focusing on _buildDynamicColor method) ==="
cat lib/app.dart

echo -e "\n\n=== lib/view/page/setting/entries/app.dart (focusing on color setting UI) ==="
cat lib/view/page/setting/entries/app.dart

Length of output: 17982


@GT-610: Excellent work! 🎉 Your implementation properly addresses the main concern:

✅ Issues Resolved

  1. Color consistency fallback (lines 89-93 in lib/app.dart):

    } else {
      final fallbackColor = Color(Stores.setting.colorSeed.fetch());
      UIs.primaryColor = fallbackColor;
      UIs.colorSeed = fallbackColor;
    }

    This ensures UIs.primaryColor and UIs.colorSeed stay consistent with the theme even on platforms without dynamic color support.

  2. UX improvement (lines 106-114 in lib/view/page/setting/entries/app.dart):
    The conditional rendering with DynamicColorBuilder elegantly hides the "Follow system" option when light and dark are both null, preventing users on Android 9-, Windows, etc. from enabling a feature their device doesn't support.

  3. Color sync in manual picker (lines 133-135 in lib/view/page/setting/entries/app.dart):
    Both UIs.primaryColor and UIs.colorSeed are now updated together, maintaining consistency.

🧹 One minor nitpick remains

Line 29 in lib/app.dart still has an unused fetch() call:

Stores.setting.useSystemPrimaryColor.fetch();

The return value is discarded, and it's called again inside the ListenableBuilder on line 34. Consider removing it unless it's intentionally warming the cache (in which case, a comment would clarify intent).

The core functionality is now solid! The combination of hiding the UI option and providing a proper fallback ensures correct behavior across all platforms. 👍

@GT-610
Copy link
Copy Markdown
Collaborator Author

GT-610 commented Jan 10, 2026

Unused call problem is being fixed.

Copy link
Copy Markdown
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: 0

Caution

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

⚠️ Outside diff range comments (1)
lib/view/page/setting/entries/app.dart (1)

100-130: Handle "Follow System" edge-cases: (1) unsupported dynamic colors, (2) OK overwriting manual seed while system mode is on.

Both issues are real:

  1. Unsupported platforms: If dynamic colors are unsupported (DynamicColorBuilder returns null for both light/dark) and useSystemPrimaryColor is already enabled, the dialog renders neither the switch nor the color picker. User is trapped with no way to change settings.

  2. Seed overwrite on system mode: When the user enables "Follow System" and taps OK, _onSaveColor(ctrl.text) runs unconditionally, overwriting UIs.primaryColor/UIs.colorSeed with the manual seed value—defeating the purpose of system color mode (lib/app.dart checks useSystemPrimaryColor to decide which colors to apply).

Proposed minimal fix (keep current structure)
@@
                     DynamicColorBuilder(
                       builder: (light, dark) {
                         final supported = light != null || dark != null;
-                        if (!supported) return const SizedBox.shrink();
+                        if (!supported) {
+                          // If the platform can't provide dynamic colors, ensure the UI doesn't get stuck
+                          // with "Follow System" enabled (which would also hide the manual picker).
+                          if (_setting.useSystemPrimaryColor.fetch()) {
+                            WidgetsBinding.instance.addPostFrameCallback((_) {
+                              _setting.useSystemPrimaryColor.put(false);
+                              setState(() {});
+                            });
+                          }
+                          return const SizedBox.shrink();
+                        }
                         return ListTile(
                           title: Text(l10n.followSystem),
                           trailing: StoreSwitch(
                             prop: _setting.useSystemPrimaryColor,
                             callback: (_) => setState(() {}),
                           ),
                         );
                       },
                     ),
@@
-            actions: Btn.ok(onTap: () => _onSaveColor(ctrl.text)).toList,
+            actions: Btn.ok(
+              onTap: () {
+                // If following system, don't overwrite the manual seed / UIs.* here.
+                if (_setting.useSystemPrimaryColor.fetch()) {
+                  RNodes.app.notify();
+                  context.pop();
+                  return;
+                }
+                _onSaveColor(ctrl.text);
+              },
+            ).toList,
           );
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cc16eb and ffca571.

📒 Files selected for processing (1)
  • lib/view/page/setting/entries/app.dart
🧰 Additional context used
📓 Path-based instructions (1)
lib/view/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

lib/view/**/*.dart: Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)
Prefer using libL10n strings before adding new ones to project l10n
Split UI into build, actions, and utils; use extension on to separate concerns

Files:

  • lib/view/page/setting/entries/app.dart
🧠 Learnings (1)
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/view/**/*.dart : Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)

Applied to files:

  • lib/view/page/setting/entries/app.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). (1)
  • GitHub Check: check
🔇 Additional comments (2)
lib/view/page/setting/entries/app.dart (2)

96-99: Prefill seed editor is a good UX improvement.
Pre-filling ctrl.text from the persisted seed avoids accidental “empty save” and makes the edit flow clearer.


136-150: Immediate apply looks correct (primaryColor + colorSeed + notify).
Setting UIs.primaryColor alongside UIs.colorSeed, persisting, then RNodes.app.notify() should eliminate the “saved but not applied” behavior.

One thing to confirm: color.value255 is the intended persisted format (alpha clamping/normalization).

…me colors

Ensure that the UI color is updated correctly when the system theme color is disabled, and maintain consistent settings when dynamic colors are not supported
@lollipopkit lollipopkit merged commit 06070c2 into lollipopkit:main Jan 10, 2026
3 checks passed
@GT-610 GT-610 deleted the fix/color-picking branch January 10, 2026 17:21
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