Skip to content

full getx migration#616

Open
inderjeet20 wants to merge 2 commits intoCCExtractor:mainfrom
inderjeet20:getxMigration
Open

full getx migration#616
inderjeet20 wants to merge 2 commits intoCCExtractor:mainfrom
inderjeet20:getxMigration

Conversation

@inderjeet20
Copy link
Contributor

@inderjeet20 inderjeet20 commented Mar 7, 2026

Refactor: Complete GetX Migration — Eliminate setState, StatefulBuilder, and GetBuilder

Closes #615

Overview

This PR completes the GetX migration across the app by converting all remaining setState/StatefulBuilder usages to reactive .obs variables and Obx widgets. It also removes orphaned update() calls and replaces the last GetBuilder instance with Obx.


Changes

New File

  • lib/app/modules/detailRoute/controllers/tags_controller.dart
    • New TagsController extends GetxController extracted from TagsRouteState
    • Holds draftTags as Rxn<ListBuilder<String>>
    • Exposes addTags(), removeTag(), parseTags(), and init() for callback injection at navigation time

Modified Files

File Change
tags_widget.dart TagsRoute converted from StatefulWidgetGetView<TagsController>; 3 setState removed; BindingsBuilder used for scoped controller injection at Get.to()
date_picker_input.dart currentIndex0.obs; _selectedDates<DateTime?>[].obs; 3 setState replaced with direct .value assignments; build() wrapped in Obx
profile_controller.dart Added final selectedProfileMode = RxnString()
profile_view.dart StatefulBuilder dialog wrapper removed; 2 setState replaced with controller.selectedProfileMode.value = value; dialog content wrapped in Obx
manage_task_server_controller.dart Added final taskrcVersion = 0.obs as a refresh trigger
manage_task_server_page_body.dart StatefulBuilder modal wrapper removed; setState(() {})controller.taskrcVersion.value++; TASKRC status row wrapped in Obx; GetBuilder<ManageTaskServerController>Obx
home_controller.dart Added void refreshTaskList() => _refreshTasks() to expose private method publicly
add_task_bottom_sheet_new.dart Removed 4 orphaned homeController.update() NOP calls
tasks_builder.dart storageWidget._refreshTasks()storageWidget.refreshTaskList()

Verification

  • flutter analyze — 0 new issues introduced (72 pre-existing infos/warnings unrelated to this PR)
  • get_errors on all 10 modified files — 0 errors
  • grep "setState" lib/app/**/*.dart — 0 active hits (only commented-out lines in pem_widget.dart)
  • grep "GetBuilder" lib/app/**/*.dart — 0 hits (only code-gen file references)

Notes

  • tags_input.dart was intentionally left as StatefulWidget — it owns a StringTagController lifecycle with no setState, making conversion unnecessary.
  • _SpinningIcon in home_page_app_bar.dart was left as-is — it uses AnimationController only, which is a legitimate lifecycle use case.

Type of Change

  • Refactor (no functional change, improves code quality)

Testing

  • Manually tested tag editing, date picker, profile mode dialog, task server config modal, task list undo
  • No regressions observed

Summary by CodeRabbit

  • New Features

    • Controller-driven tag editor with improved add/remove and parsing behavior
    • Added explicit task-list refresh action
    • Cross-platform plugin support expanded (Linux GTK, macOS AppLinks, Windows AppLinks)
  • Bug Fixes

    • Improved UI responsiveness and reactive updates for tags, profile mode, date picker, and server/PEM sections
    • Undo flow now reliably refreshes the task list instead of manual update calls

@coderabbitai
Copy link

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

Completes GetX migration by replacing remaining setState/StatefulBuilder usage with reactive observables and Obx; adds a new TagsController for tag state and operations; exposes HomeController.refreshTaskList; introduces observable version counters and profile mode observables; and registers GTK/AppLinks plugins across desktop platforms.

Changes

Cohort / File(s) Summary
DetailRoute: Tags controller & view
lib/app/modules/detailRoute/controllers/tags_controller.dart, lib/app/modules/detailRoute/views/tags_widget.dart
Added new TagsController (draftTags Rxn<ListBuilder>, callback, init, parseTags, addTags, removeTag, pendingTags getter). Migrated TagsRoute from StatefulWidget to GetView<TagsController> and moved tag state/logic to controller; route now initialized via Get bindings.
GetX state migration — UI files
lib/app/modules/profile/views/profile_view.dart, lib/app/utils/add_task_dialogue/date_picker_input.dart, lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart
Replaced local setState/StatefulBuilder/GetBuilder usages with Rx observables and Obx widgets; local state moved to controllers or obs fields; UI rebuilds now reactive.
Home controller & views
lib/app/modules/home/controllers/home_controller.dart, lib/app/modules/home/views/add_task_bottom_sheet_new.dart, lib/app/modules/home/views/tasks_builder.dart
Added HomeController.refreshTaskList() public method. Removed three orphaned homeController.update() calls. Updated undo flow to call refreshTaskList() instead of update().
ManageTaskServer controller observables
lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart
Added taskrcVersion and pemVersion observables and replaced several update() calls with increments of these version counters to trigger reactive updates.
Profile controller observable
lib/app/modules/profile/controllers/profile_controller.dart
Added selectedProfileMode observable (RxnString) used by profile dialog.
Platform plugin registrations (desktop)
linux/flutter/generated_plugin_registrant.cc, linux/flutter/generated_plugins.cmake, macos/Flutter/GeneratedPluginRegistrant.swift, windows/flutter/generated_plugin_registrant.cc, windows/flutter/generated_plugins.cmake
Registered GTK plugin for Linux and AppLinks for macOS/Windows; updated generated plugin lists and registrant calls accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant UI as TagsRoute (View)
    participant TC as TagsController
    participant HC as HomeController
    UI->>TC: init(value?, callback)
    UI->>TC: user enters comma-separated tags
    TC->>TC: parseTags(input)
    TC->>TC: addTags(parsedList) / removeTag(tag)
    TC->>HC: read pendingTags (getter)
    TC->>TC: draftTags.value = updated ListBuilder
    TC->>UI: callback(draftTags.value) (via provided callback)
    TC->>UI: Obx triggers UI rebuild (draftTags / pendingTags observed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Poem

🐰 I hopped from setState to Obx so bright,

Draft tags now nestle in controllers at night,
Desktop plugins join the parade,
Observables dance, no more cascade,
A little rabbit cheers: code migrated just right! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Title 'full getx migration' is vague and overly generic, using non-descriptive language that doesn't convey meaningful information about the specific changes in the changeset. Provide a more specific title that describes the main changes, e.g., 'Migrate remaining state management to GetX: remove setState, StatefulBuilder, and GetBuilder'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed Description is comprehensive and well-structured, covering overview, file-by-file changes, verification steps, notes, and testing. Properly addresses the linked issue #615 with detailed information.
Linked Issues check ✅ Passed All coding requirements from issue #615 are addressed: setState/StatefulBuilder usages eliminated via .obs and Obx migration [#615], GetBuilder replaced with Obx [#615], orphaned update() calls removed [#615], and private method access replaced with public API [#615].
Out of Scope Changes check ✅ Passed All changes align with the GetX migration objectives in #615. Plugin registrations (GTK, AppLinks) appear to be regenerated files from Flutter dependencies, not manual code changes outside the stated scope.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

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

Caution

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

⚠️ Outside diff range comments (1)
lib/app/modules/profile/views/profile_view.dart (1)

306-323: ⚠️ Potential issue | 🟡 Minor

Fix the success message for TW3C.

Line 321 still treats only TW3 as the v3 branch, but this dialog now exposes TW3C. Changing a profile to Taskchampion will currently show “Taskserver” in the snackbar.

✏️ Proposed fix
                           final selectedMode =
                               controller.selectedProfileMode.value;
                           if (selectedMode != null &&
                               selectedMode != currentMode) {
+                            final modeLabel = selectedMode == "TW3C"
+                                ? "Taskchampion"
+                                : selectedMode == "TW3"
+                                    ? "CCSync"
+                                    : "TaskServer";
                             controller.profilesWidget.changeModeTo(
                               profile,
                               selectedMode,
                             );
                             ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                                 content: Text(
                                   SentenceManager(
                                               currentLanguage:
                                                   AppSettings.selectedLanguage)
                                           .sentences
                                           .profilePageSuccessfullyChangedProfileModeTo +
-                                      (selectedMode == "TW3"
-                                          ? "CCSync"
-                                          : "Taskserver"),
+                                      modeLabel,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/app/modules/profile/views/profile_view.dart` around lines 306 - 323, The
success Snackbar message incorrectly maps only "TW3" to the v3 label; update the
logic around controller.selectedProfileMode.value (used before calling
controller.profilesWidget.changeModeTo) so that it treats "TW3C" as the v3
branch and shows "Taskchampion" (or otherwise map "TW3C" -> "Taskchampion")
instead of "Taskserver"; adjust the conditional that currently checks
selectedMode == "TW3" and/or the string mapping used when building the
SentenceManager/profilePageSuccessfullyChangedProfileModeTo message so both
"TW3" and "TW3C" produce the correct v3 label.
🧹 Nitpick comments (1)
lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart (1)

192-235: Fragile trigger pattern — consider making the underlying state reactive.

Reading taskrcVersion.value (line 193) without using it just to register an Obx subscription is a workaround. The actual state (taskrcContentController.text) isn't reactive. This pattern is fragile because any code path that modifies the text must remember to increment taskrcVersion.

For long-term maintainability, consider making the taskrc content itself reactive (e.g., RxString taskrcContent) instead of relying on a manual version counter.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`
around lines 192 - 235, The current Obx is relying on reading
controller.taskrcVersion.value to trigger rebuilds while the actual text lives
in taskrcContentController.text, which is fragile; change the controller to
expose a reactive RxString (e.g., taskrcContent) and keep it in sync with the
TextEditingController (add a listener to update taskrcContent when the
controller.text changes and initialize controller.text from taskrcContent), then
update the view to observe taskrcContent (use controller.taskrcContent.value /
controller.taskrcContent.isNotEmpty) instead of reading taskrcVersion; ensure
all places that modify the taskrc text update the reactive taskrcContent rather
than manipulating a separate version counter.
🤖 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/detailRoute/controllers/tags_controller.dart`:
- Around line 45-54: The removeTag method currently force-unwraps
draftTags.value and then sends an empty ListBuilder to callback when last tag is
removed, causing a potential NPE and inconsistent semantics with addTags; update
removeTag to first check if draftTags.value is null and return early (no-op) if
so, otherwise operate on the non-null ListBuilder (avoid using the ! operator),
remove the tag, and if the resulting list is empty set draftTags.value = null
and call callback(null) to preserve the "no tags" semantic; if not empty,
refresh draftTags and call callback(draftTags.value) — reference removeTag,
draftTags, and callback to locate changes.

In
`@lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart`:
- Line 30: The Obx-based UI listens to the observable taskrcVersion but
setContent() currently calls update() (GetBuilder) so the view doesn't rebuild;
modify setContent() in manage_task_server_controller.dart to increment
taskrcVersion (e.g., taskrcVersion.value++) after changing the content instead
of—or in addition to—calling update(), ensuring the Obx reactive widget sees the
change and rebuilds when content is pasted.

In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`:
- Around line 418-482: The Obx only depends on serverCertExists so changes from
controller.update() in onTapPEMWidget/onLongPressPEMWidget don't rebuild; add a
reactive counter pemVersion (e.g., RxInt pemVersion = 0.obs) to the controller,
increment it at the end of onTapPEMWidget and onLongPressPEMWidget, and ensure
the Obx reads controller.pemVersion.value (for example reference
controller.pemVersion.value at top of the Obx) so the PEM list (created with
PemWidget) will rebuild when pemVersion changes; alternatively replace this Obx
with a GetBuilder for that section if you prefer controller.update() semantics.

In `@lib/app/utils/add_task_dialogue/date_picker_input.dart`:
- Line 27: The _currentIndex observable is incorrectly initialized to 0
regardless of widget.allowedIndexes, causing DropdownButton.value mismatches;
change the initialization of _currentIndex to seed from widget.allowedIndexes
(e.g., use the first element of widget.allowedIndexes if non-empty) and ensure
you handle the empty/nullable case (fallback to a safe default or disable the
dropdown). Update any code that constructs DropdownButton.value and the items
loop that references widget.allowedIndexes so they use the same source and never
pass a value not present in the items.
- Around line 119-123: Replace using picked.add(Duration(...)) with an explicit
wall-clock DateTime built from picked's Y/M/D and desired time to avoid DST
arithmetic: set _selectedDates[forIndex] = DateTime(picked.year, picked.month,
picked.day, 23, 59); then continue to call widget.onDateChanges! with
List<DateTime?>.from(_selectedDates) (preserve nullability/UTC handling if
needed by checking picked.isUtc and using DateTime.utc(...) when appropriate).

In `@linux/flutter/generated_plugins.cmake`:
- Around line 5-10: The generated FLUTTER_PLUGIN_LIST includes the plugin
identifier "gtk" but your pubspec.yaml/pubspec.lock do not, causing the
generated file to diverge on the next flutter pub get; fix by adding the gtk
dependency to your pubspec.yaml (or run flutter pub add gtk) so the plugin is
declared and flutter pub get regenerates linux/flutter/generated_plugins.cmake
consistently, then commit the updated pubspec.yaml and pubspec.lock;
alternatively, if gtk is not needed, remove the gtk entry from the generated
list and ensure the source of generation no longer declares it.

---

Outside diff comments:
In `@lib/app/modules/profile/views/profile_view.dart`:
- Around line 306-323: The success Snackbar message incorrectly maps only "TW3"
to the v3 label; update the logic around controller.selectedProfileMode.value
(used before calling controller.profilesWidget.changeModeTo) so that it treats
"TW3C" as the v3 branch and shows "Taskchampion" (or otherwise map "TW3C" ->
"Taskchampion") instead of "Taskserver"; adjust the conditional that currently
checks selectedMode == "TW3" and/or the string mapping used when building the
SentenceManager/profilePageSuccessfullyChangedProfileModeTo message so both
"TW3" and "TW3C" produce the correct v3 label.

---

Nitpick comments:
In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`:
- Around line 192-235: The current Obx is relying on reading
controller.taskrcVersion.value to trigger rebuilds while the actual text lives
in taskrcContentController.text, which is fragile; change the controller to
expose a reactive RxString (e.g., taskrcContent) and keep it in sync with the
TextEditingController (add a listener to update taskrcContent when the
controller.text changes and initialize controller.text from taskrcContent), then
update the view to observe taskrcContent (use controller.taskrcContent.value /
controller.taskrcContent.isNotEmpty) instead of reading taskrcVersion; ensure
all places that modify the taskrc text update the reactive taskrcContent rather
than manipulating a separate version counter.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 39dd2ffe-4caa-4caf-b928-adee9997a76b

📥 Commits

Reviewing files that changed from the base of the PR and between 66aef29 and 830cdad.

📒 Files selected for processing (15)
  • lib/app/modules/detailRoute/controllers/tags_controller.dart
  • lib/app/modules/detailRoute/views/tags_widget.dart
  • lib/app/modules/home/controllers/home_controller.dart
  • lib/app/modules/home/views/add_task_bottom_sheet_new.dart
  • lib/app/modules/home/views/tasks_builder.dart
  • lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart
  • lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart
  • lib/app/modules/profile/controllers/profile_controller.dart
  • lib/app/modules/profile/views/profile_view.dart
  • lib/app/utils/add_task_dialogue/date_picker_input.dart
  • linux/flutter/generated_plugin_registrant.cc
  • linux/flutter/generated_plugins.cmake
  • macos/Flutter/GeneratedPluginRegistrant.swift
  • windows/flutter/generated_plugin_registrant.cc
  • windows/flutter/generated_plugins.cmake
💤 Files with no reviewable changes (1)
  • lib/app/modules/home/views/add_task_bottom_sheet_new.dart

Comment on lines +418 to +482
Obx(() {
List<Widget> pemWidgets = [];
for (var pem in [
'taskd.certificate',
'taskd.key',
'taskd.ca',
if (controller.homeController.serverCertExists.value)
'server.cert',
]) {
pemWidgets.add(
PemWidget(
storage: controller.storage,
pem: pem,
optionString: pem == "taskd.certificate"
? SentenceManager(
currentLanguage: AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageConfigureYourCertificate
: pem == "taskd.key"
? SentenceManager(
currentLanguage: AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageConfigureTaskserverKey
: pem == "taskd.ca"
? SentenceManager(
currentLanguage:
AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageConfigureServerCertificate
: SentenceManager(
currentLanguage:
AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageConfigureServerCertificate,
listTileTitle: pem == "taskd.certificate"
? SentenceManager(
currentLanguage: AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageSelectCertificate
: pem == "taskd.key"
? SentenceManager(
currentLanguage: AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageSelectKey
: pem == "taskd.ca"
? SentenceManager(
currentLanguage:
AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageSelectCertificate
: SentenceManager(
currentLanguage:
AppSettings.selectedLanguage)
.sentences
.manageTaskServerPageSelectCertificate,
onTapCallBack: controller.onTapPEMWidget,
onLongPressCallBack: controller.onLongPressPEMWidget,
globalKey: controller.getGlobalKey(pem),
),
);
},
)
}
return Column(
children: pemWidgets,
);
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

PEM widgets won't update after file changes — update() calls in controller don't trigger Obx.

This Obx only reacts to serverCertExists.value (line 424). When PEM files are added/removed via onTapPEMWidget or onLongPressPEMWidget, the controller calls update(), which doesn't trigger Obx rebuilds.

To fix, either:

  1. Add a reactive counter (similar to taskrcVersion) and increment it in onTapPEMWidget/onLongPressPEMWidget
  2. Use GetBuilder for this section (reverting this specific change)
🐛 Proposed fix: add pemVersion trigger

In controller:

  final taskrcVersion = 0.obs;
+ final pemVersion = 0.obs;

In onTapPEMWidget:

      await setConfig(
        storage: storagePem,
        key: pem,
      );
-     update();
+     pemVersion.value++;

In onLongPressPEMWidget:

      storage.guiPemFiles.removePemFile(pem);
-     update();
+     pemVersion.value++;

In view (line 418):

  Obx(() {
+   controller.pemVersion.value; // trigger rebuild
    List<Widget> pemWidgets = [];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`
around lines 418 - 482, The Obx only depends on serverCertExists so changes from
controller.update() in onTapPEMWidget/onLongPressPEMWidget don't rebuild; add a
reactive counter pemVersion (e.g., RxInt pemVersion = 0.obs) to the controller,
increment it at the end of onTapPEMWidget and onLongPressPEMWidget, and ensure
the Obx reads controller.pemVersion.value (for example reference
controller.pemVersion.value at top of the Obx) so the PEM list (created with
PemWidget) will rebuild when pemVersion changes; alternatively replace this Obx
with a GetBuilder for that section if you prefer controller.update() semantics.

List.generate(4, (index) => TextEditingController());
final int length = 4;
int currentIndex = 0;
final _currentIndex = 0.obs;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Seed _currentIndex from allowedIndexes.

Line 27 hard-codes 0, but Lines 48-53 only build items for widget.allowedIndexes. If a caller passes something like [1, 2], DropdownButton gets value: 0 with no matching item and asserts during build.

Suggested fix
 class _AddTaskDatePickerInputState extends State<AddTaskDatePickerInput> {
   final _selectedDates = <DateTime?>[null, null, null, null].obs;
   final List<String> dateLabels = ['Due', 'Wait', 'Sched', 'Until'];
   final List<TextEditingController> _controllers =
       List.generate(4, (index) => TextEditingController());
   final int length = 4;
-  final _currentIndex = 0.obs;
+  late final RxInt _currentIndex;
+
+  `@override`
+  void initState() {
+    super.initState();
+    _currentIndex = _initialIndexFor(widget).obs;
+  }
+
+  `@override`
+  void didUpdateWidget(covariant AddTaskDatePickerInput oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    if (!widget.allowedIndexes.contains(_currentIndex.value)) {
+      _currentIndex.value = _initialIndexFor(widget);
+    }
+  }
+
+  int _initialIndexFor(AddTaskDatePickerInput widget) {
+    if (widget.onlyDueDate) return 0;
+    return widget.allowedIndexes.contains(0)
+        ? 0
+        : widget.allowedIndexes.first;
+  }

Also applies to: 48-53

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/app/utils/add_task_dialogue/date_picker_input.dart` at line 27, The
_currentIndex observable is incorrectly initialized to 0 regardless of
widget.allowedIndexes, causing DropdownButton.value mismatches; change the
initialization of _currentIndex to seed from widget.allowedIndexes (e.g., use
the first element of widget.allowedIndexes if non-empty) and ensure you handle
the empty/nullable case (fallback to a safe default or disable the dropdown).
Update any code that constructs DropdownButton.value and the items loop that
references widget.allowedIndexes so they use the same source and never pass a
value not present in the items.

Comment on lines 5 to 10
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
flutter_timezone
gtk
url_launcher_linux
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -t f 'pubspec\.(yaml|lock)$' | while read -r f; do
  echo "## $f"
  rg -n -C2 '^\s*gtk:' "$f" || true
done

Repository: CCExtractor/taskwarrior-flutter

Length of output: 106


Add gtk to pubspec.yaml to sync with generated plugins.

This file is generated and currently includes gtk in FLUTTER_PLUGIN_LIST, but gtk is not declared in pubspec.yaml or pubspec.lock. On the next flutter pub get, the generated file will be regenerated without gtk, causing CI and local builds to diverge. Either add gtk to pubspec.yaml or remove it from the generated output.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@linux/flutter/generated_plugins.cmake` around lines 5 - 10, The generated
FLUTTER_PLUGIN_LIST includes the plugin identifier "gtk" but your
pubspec.yaml/pubspec.lock do not, causing the generated file to diverge on the
next flutter pub get; fix by adding the gtk dependency to your pubspec.yaml (or
run flutter pub add gtk) so the plugin is declared and flutter pub get
regenerates linux/flutter/generated_plugins.cmake consistently, then commit the
updated pubspec.yaml and pubspec.lock; alternatively, if gtk is not needed,
remove the gtk entry from the generated list and ensure the source of generation
no longer declares it.

- tags_controller: guard removeTag against null draftTags; fix callback
  to pass null (not empty ListBuilder) when last tag is removed, consistent
  with addTags semantics
- manage_task_server_controller: replace update() in setContent() with
  taskrcVersion.value++ so Obx rebuilds correctly on paste
- manage_task_server_controller: add pemVersion.obs trigger; replace
  update() in onTapPEMWidget/onLongPressPEMWidget with pemVersion.value++
- manage_task_server_page_body: read pemVersion.value in PEM Obx so widget
  list reacts to file add/remove operations
- date_picker_input: initialise _currentIndex from allowedIndexes.first to
  prevent DropdownButton assert when 0 is not in the allowed set
- date_picker_input: replace picked.add(Duration(...)) with explicit
  DateTime construction to avoid DST-related date/time errors
Copy link

@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.

🧹 Nitpick comments (1)
lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart (1)

432-473: Consider extracting PEM widget labels into a helper or map.

The 4-level nested ternaries for optionString and listTileTitle are hard to read and duplicate the same conditional structure.

♻️ Suggested refactor using a map
// Define at class level or as a static method
Map<String, (String optionString, String listTileTitle)> _getPemLabels(SentenceManager sm) => {
  'taskd.certificate': (
    sm.sentences.manageTaskServerPageConfigureYourCertificate,
    sm.sentences.manageTaskServerPageSelectCertificate,
  ),
  'taskd.key': (
    sm.sentences.manageTaskServerPageConfigureTaskserverKey,
    sm.sentences.manageTaskServerPageSelectKey,
  ),
  'taskd.ca': (
    sm.sentences.manageTaskServerPageConfigureServerCertificate,
    sm.sentences.manageTaskServerPageSelectCertificate,
  ),
  'server.cert': (
    sm.sentences.manageTaskServerPageConfigureServerCertificate,
    sm.sentences.manageTaskServerPageSelectCertificate,
  ),
};

// Then in the loop:
final sm = SentenceManager(currentLanguage: AppSettings.selectedLanguage);
final labels = _getPemLabels(sm);
for (var pem in [...]) {
  final (optionStr, titleStr) = labels[pem]!;
  pemWidgets.add(
    PemWidget(
      // ...
      optionString: optionStr,
      listTileTitle: titleStr,
      // ...
    ),
  );
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`
around lines 432 - 473, The nested ternary logic setting optionString and
listTileTitle is hard to read and duplicated; replace it by creating a helper
(e.g. a private method or map like _getPemLabels) that accepts a SentenceManager
instance (SentenceManager(currentLanguage: AppSettings.selectedLanguage)) and
returns the pair of strings for a given pem key, then use that helper inside the
loop that builds PemWidget so you set optionString and listTileTitle from the
returned values instead of repeated nested ternaries; ensure keys include
"taskd.certificate", "taskd.key", "taskd.ca" (and the default/other key) and
that callers use the single SentenceManager instance to avoid reconstructing it
repeatedly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart`:
- Around line 432-473: The nested ternary logic setting optionString and
listTileTitle is hard to read and duplicated; replace it by creating a helper
(e.g. a private method or map like _getPemLabels) that accepts a SentenceManager
instance (SentenceManager(currentLanguage: AppSettings.selectedLanguage)) and
returns the pair of strings for a given pem key, then use that helper inside the
loop that builds PemWidget so you set optionString and listTileTitle from the
returned values instead of repeated nested ternaries; ensure keys include
"taskd.certificate", "taskd.key", "taskd.ca" (and the default/other key) and
that callers use the single SentenceManager instance to avoid reconstructing it
repeatedly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8c07d23-0bb8-4fec-88fa-f4f8262df1ef

📥 Commits

Reviewing files that changed from the base of the PR and between 830cdad and 2b769e9.

📒 Files selected for processing (4)
  • lib/app/modules/detailRoute/controllers/tags_controller.dart
  • lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart
  • lib/app/modules/manageTaskServer/views/manage_task_server_page_body.dart
  • lib/app/utils/add_task_dialogue/date_picker_input.dart
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/app/modules/manageTaskServer/controllers/manage_task_server_controller.dart

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.

[Refactor] Complete GetX Migration — Remove All Remaining setState and GetBuilder Usage

1 participant