Improve directory buttons UI in settings screen #623
Improve directory buttons UI in settings screen #623srykaran wants to merge 4 commits intoCCExtractor:mainfrom
Conversation
📝 WalkthroughWalkthroughThis PR adds support for filtering tasks with no project assigned. It introduces a sentinel constant in HomeController, updates project column UI to display and handle a "No Project" filter option, adds translations across 8 supported languages, and refines button styling in the settings page. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip You can enable review details to help with troubleshooting, context usage and more.Enable the |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
lib/app/modules/settings/views/settings_page_select_directory_list_tile.dart (1)
60-67: Consider providing a fallback color to avoid potential null crash.Line 62 uses force-unwrap (
tColors.purpleShade!) forBorderSide.colorwhich requires a non-null value. IfpurpleShadeis ever null in the theme extension, this will cause a runtime crash.💡 Suggested safer approach
child: OutlinedButton.icon( style: OutlinedButton.styleFrom( - side: BorderSide(color: tColors.purpleShade!), + side: BorderSide(color: tColors.purpleShade ?? TaskWarriorColors.purple), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/app/modules/settings/views/settings_page_select_directory_list_tile.dart` around lines 60 - 67, The BorderSide color currently force-unwraps the theme extension (tColors.purpleShade!) which can crash if null; update the OutlinedButton.styleFrom BorderSide(color: ...) in settings_page_select_directory_list_tile.dart (the OutlinedButton.icon block / BorderSide usage) to use a safe fallback instead of ! — e.g., use a null-coalescing fallback from tColors.purpleShade to a sensible default (or Theme.of(context).colorScheme.primary) so the BorderSide always receives a non-null Color.lib/app/utils/language/hindi_sentences.dart (1)
409-410: Consider aligning wording with existing Hindi project terminology.At Line 409,
प्रोजेक्टis understandable, but the file mostly usesपरियोजना. Aligning terminology improves consistency.♻️ Suggested tweak
- String get noProject => 'कोई प्रोजेक्ट नहीं'; + String get noProject => 'कोई परियोजना नहीं';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/app/utils/language/hindi_sentences.dart` around lines 409 - 410, The Hindi string in the getter noProject uses "प्रोजेक्ट" but the codebase prefers "परियोजना"; update the return value of the noProject getter to use "कोई परियोजना नहीं" so terminology matches other translations (search for the noProject getter to locate and modify the string).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/app/modules/home/controllers/home_controller.dart`:
- Line 44: The controller uses a UI string as an internal sentinel (static const
String noProjectValue = " (No Project) "), which is fragile; change
noProjectValue to a stable internal key (e.g. "__NO_PROJECT__") and update all
controller logic that checks or sets noProjectValue (references in this file,
including the filter/comparison logic around the current usage at lines
~266-268) to use that internal key; move any user-facing label (the localized "
(No Project) " display text) into the view layer where the project list /
dropdown is rendered so the UI shows the friendly text while the
controller/state uses the stable "__NO_PROJECT__" sentinel. Ensure equality
checks, filter construction, and any serialization still use the new internal
constant name noProjectValue.
In `@lib/app/modules/home/views/project_column_home_page.dart`:
- Around line 91-107: The header is rendering projectFilter directly which can
show the internal token HomeController.noProjectValue; instead, when
projectFilter == HomeController.noProjectValue map it to the localized label
from SentenceManager(currentLanguage:
AppSettings.selectedLanguage).sentences.noProject before rendering. Update the
selected-project header rendering logic to check projectFilter (or the getter
used there) and replace the token with the SentenceManager noProject string so
the UI displays a localized "No Project" label.
In `@lib/app/modules/home/views/project_column_taskc.dart`:
- Around line 76-81: The header currently displays the raw projectFilter value
instead of translating the sentinel; update the header rendering logic to detect
when projectFilter == HomeController.noProjectValue and substitute it with the
translated label from SentenceManager(currentLanguage:
AppSettings.selectedLanguage).sentences.noProject; otherwise continue displaying
projectFilter. Locate the header code that uses projectFilter (the component
that also uses the callback and project props) and implement this conditional
replacement so the UI shows the localized "no project" text rather than the
internal sentinel.
---
Nitpick comments:
In
`@lib/app/modules/settings/views/settings_page_select_directory_list_tile.dart`:
- Around line 60-67: The BorderSide color currently force-unwraps the theme
extension (tColors.purpleShade!) which can crash if null; update the
OutlinedButton.styleFrom BorderSide(color: ...) in
settings_page_select_directory_list_tile.dart (the OutlinedButton.icon block /
BorderSide usage) to use a safe fallback instead of ! — e.g., use a
null-coalescing fallback from tColors.purpleShade to a sensible default (or
Theme.of(context).colorScheme.primary) so the BorderSide always receives a
non-null Color.
In `@lib/app/utils/language/hindi_sentences.dart`:
- Around line 409-410: The Hindi string in the getter noProject uses "प्रोजेक्ट"
but the codebase prefers "परियोजना"; update the return value of the noProject
getter to use "कोई परियोजना नहीं" so terminology matches other translations
(search for the noProject getter to locate and modify the string).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0f84d19a-99d9-4727-84d2-f6a627dc92db
📒 Files selected for processing (13)
lib/app/modules/home/controllers/home_controller.dartlib/app/modules/home/views/project_column_home_page.dartlib/app/modules/home/views/project_column_taskc.dartlib/app/modules/settings/views/settings_page_select_directory_list_tile.dartlib/app/utils/language/bengali_sentences.dartlib/app/utils/language/english_sentences.dartlib/app/utils/language/french_sentences.dartlib/app/utils/language/german_sentences.dartlib/app/utils/language/hindi_sentences.dartlib/app/utils/language/marathi_sentences.dartlib/app/utils/language/sentences.dartlib/app/utils/language/spanish_sentences.dartlib/app/utils/language/urdu_sentences.dart
| import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; | ||
|
|
||
| class HomeController extends GetxController { | ||
| static const String noProjectValue = " (No Project) "; |
There was a problem hiding this comment.
Use a stable internal key instead of display text for the no-project sentinel.
Line 44 currently uses a UI string (" (No Project) ") as internal filter state. That makes filtering fragile (collision with real project names and whitespace sensitivity), and Line 266 depends on that exact formatted text.
♻️ Proposed refactor
- static const String noProjectValue = " (No Project) ";
+ static const String noProjectFilterKey = '__NO_PROJECT__';
@@
- if (projectFilter.value == noProjectValue) {
- return task.project == null || task.project!.isEmpty;
+ if (projectFilter.value == noProjectFilterKey) {
+ return task.project == null || task.project!.trim().isEmpty;
}Keep localized display labels in the view layer, and keep this controller value purely internal.
Also applies to: 266-268
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/app/modules/home/controllers/home_controller.dart` at line 44, The
controller uses a UI string as an internal sentinel (static const String
noProjectValue = " (No Project) "), which is fragile; change noProjectValue to a
stable internal key (e.g. "__NO_PROJECT__") and update all controller logic that
checks or sets noProjectValue (references in this file, including the
filter/comparison logic around the current usage at lines ~266-268) to use that
internal key; move any user-facing label (the localized " (No Project) " display
text) into the view layer where the project list / dropdown is rendered so the
UI shows the friendly text while the controller/state uses the stable
"__NO_PROJECT__" sentinel. Ensure equality checks, filter construction, and any
serialization still use the new internal constant name noProjectValue.
| GestureDetector( | ||
| onTap: () => callback(HomeController.noProjectValue), | ||
| child: Row( | ||
| mainAxisAlignment: MainAxisAlignment.start, | ||
| children: [ | ||
| Radio( | ||
| activeColor: tColors.primaryTextColor, | ||
| focusColor: tColors.secondaryTextColor, | ||
| toggleable: true, | ||
| value: HomeController.noProjectValue, | ||
| groupValue: projectFilter, | ||
| onChanged: (_) => callback(HomeController.noProjectValue), | ||
| ), | ||
| Text( | ||
| SentenceManager(currentLanguage: AppSettings.selectedLanguage) | ||
| .sentences | ||
| .noProject, |
There was a problem hiding this comment.
Map noProjectValue to a localized display label in the selected-project header.
Line 92/Line 100 sets projectFilter to HomeController.noProjectValue, but Line 53 renders projectFilter directly. This can show an internal token instead of localized “No Project”.
🐛 Suggested fix
`@override`
Widget build(BuildContext context) {
TaskwarriorColorTheme tColors = Theme.of(context).extension<TaskwarriorColorTheme>()!;
+ final sentences =
+ SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences;
+ final selectedProjectLabel = projectFilter.isEmpty
+ ? sentences.notSelected
+ : projectFilter == HomeController.noProjectValue
+ ? sentences.noProject
+ : projectFilter;
return Column(
children: [
@@
Text(
- "${SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.project} : ",
+ "${sentences.project} : ",
@@
Text(
- projectFilter == "" ? SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences.notSelected : projectFilter,
+ selectedProjectLabel,
style: TextStyle(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/app/modules/home/views/project_column_home_page.dart` around lines 91 -
107, The header is rendering projectFilter directly which can show the internal
token HomeController.noProjectValue; instead, when projectFilter ==
HomeController.noProjectValue map it to the localized label from
SentenceManager(currentLanguage:
AppSettings.selectedLanguage).sentences.noProject before rendering. Update the
selected-project header rendering logic to check projectFilter (or the getter
used there) and replace the token with the SentenceManager noProject string so
the UI displays a localized "No Project" label.
| project: HomeController.noProjectValue, | ||
| projectFilter: projectFilter, | ||
| callback: callback), | ||
| callback: (val) => callback(val), | ||
| displayName: SentenceManager( | ||
| currentLanguage: AppSettings.selectedLanguage, | ||
| ).sentences.noProject), |
There was a problem hiding this comment.
Translate the selected noProjectValue in the header instead of showing raw filter value.
Line 76 sets the sentinel HomeController.noProjectValue, but the header (Line 51-Line 56) prints projectFilter directly. This may expose internal value text in UI.
🐛 Suggested fix
`@override`
Widget build(BuildContext context) {
TaskwarriorColorTheme tColors =
Theme.of(context).extension<TaskwarriorColorTheme>()!;
+ final sentences =
+ SentenceManager(currentLanguage: AppSettings.selectedLanguage).sentences;
+ final selectedProjectLabel = projectFilter.isEmpty
+ ? sentences.notSelected
+ : projectFilter == HomeController.noProjectValue
+ ? sentences.noProject
+ : projectFilter;
return Column(
@@
child: Text(
- projectFilter.isEmpty
- ? SentenceManager(
- currentLanguage: AppSettings.selectedLanguage)
- .sentences
- .notSelected
- : projectFilter,
+ selectedProjectLabel,
style: TextStyle(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/app/modules/home/views/project_column_taskc.dart` around lines 76 - 81,
The header currently displays the raw projectFilter value instead of translating
the sentinel; update the header rendering logic to detect when projectFilter ==
HomeController.noProjectValue and substitute it with the translated label from
SentenceManager(currentLanguage:
AppSettings.selectedLanguage).sentences.noProject; otherwise continue displaying
projectFilter. Locate the header code that uses projectFilter (the component
that also uses the callback and project props) and implement this conditional
replacement so the UI shows the localized "no project" text rather than the
internal sentinel.
Description
This PR improves the UI consistency of the "Set To Default" and "Change Directory" buttons in the Settings → Storage and Data section.
Previously these buttons appeared visually inconsistent with the rest of the settings UI.
Changes
Screenshots
Before
After
Type of Change
UI improvement / UX consistency
Summary by CodeRabbit
New Features
UI Improvements
Localization