Skip to content

feat(ui): add skip quick add setting and enhance task creation flow#235

Merged
ahmet-cetinkaya merged 11 commits into
mainfrom
feat/task-creation-enhancements
Feb 9, 2026
Merged

feat(ui): add skip quick add setting and enhance task creation flow#235
ahmet-cetinkaya merged 11 commits into
mainfrom
feat/task-creation-enhancements

Conversation

@ahmet-cetinkaya

@ahmet-cetinkaya ahmet-cetinkaya commented Feb 9, 2026

Copy link
Copy Markdown
Owner

🚀 Motivation and Context

This PR introduces a new user setting to skip the quick add dialog and directly navigate to the full task creation dialog. It also enhances the task creation flow with better state management and improved UI consistency.

⚙️ Implementation Details

  • New Setting: Added skipQuickAdd boolean setting to task preferences
  • UI Components: Created SkipQuickAddSetting widget for user control
  • Enhanced Flow: Refactored QuickAddTaskDialog to support direct navigation based on user preference
  • Helper Utility: Introduced TaskCreationHelper for centralized task creation logic
  • State Management: Improved with cleaner controller separation and removed redundant lock settings state
  • Localization: Added translations for all supported languages (22 locales)
  • Removed Files: Cleaned up obsolete lock_settings_dialog_content.dart and lock_settings_state.dart

📋 Checklist for Reviewer

  • Tests passed locally.
  • Commit history is clean and descriptive.
  • Documentation updated (if applicable).
  • Code quality standards were met (e.g., linter passed).

🔗 Related [optional]

N/A

Summary by Sourcery

Add a configurable option to skip the quick add dialog and improve the task creation experience across quick add, task details, and settings.

New Features:

  • Introduce a skip-quick-add task setting with UI toggle in task settings and persistence via app settings.
  • Allow creating a task directly from quick add and automatically opening its details view, including a dedicated create-and-open action and default title handling.
  • Add inline lock/unlock controls for priority, estimated time, planned date, deadline, and tags in their respective dialogs and pickers.

Enhancements:

  • Refine the quick add dialog UX with disabled send/open actions when the title is empty and adjusted dialog sizing on desktop.
  • Centralize task creation logic in a new TaskCreationHelper to respect user preferences and reuse default reminder/estimated time settings.
  • Simplify lock state management in the quick add controller by replacing the lock settings dialog and model with per-field toggles.
  • Improve task details title input with a localized placeholder label.
  • Extend date picker, tag selector, priority, and estimated time dialogs to support optional header actions, such as lock toggles.

- Add skip quick add dialog setting in task settings with localization
- Implement TaskCreationHelper to handle immediate vs dialog-based task creation
- Add lock/unlock functionality for task properties in quick add dialog
- Enhance quick add dialog with open in new button and improved layout
- Add header action support to various dialog components
- Update task creation buttons to use new helper
- Add new task default title and lock/unlock translations
- Increase dialog max width for better mobile experience
@ahmet-cetinkaya ahmet-cetinkaya added the enhancement New feature or request label Feb 9, 2026
@ahmet-cetinkaya ahmet-cetinkaya self-assigned this Feb 9, 2026
@ahmet-cetinkaya ahmet-cetinkaya added the enhancement New feature or request label Feb 9, 2026
@sourcery-ai

sourcery-ai Bot commented Feb 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a new "Skip Quick Add" task setting and central TaskCreationHelper to optionally bypass the quick-add dialog, refactors quick-add task creation and lock handling, and wires the new flow into task add entry points with corresponding UI, behavior, and localization updates.

Sequence diagram for task creation with optional quick add skip

sequenceDiagram
  actor User
  participant TaskAddButton
  participant TaskCreationHelper
  participant Mediator
  participant Setting
  participant QuickAddTaskDialog
  participant QuickAddTaskController
  participant TasksService
  participant TaskDetailsPage

  User->>TaskAddButton: tap add task
  TaskAddButton->>TaskCreationHelper: createTask(context, initialData)

  TaskCreationHelper->>Mediator: send(GetSettingQuery(taskSkipQuickAdd))
  Mediator-->>TaskCreationHelper: Setting or null
  TaskCreationHelper->>TaskCreationHelper: determine skipQuickAdd (defaultSkipQuickAdd if missing)

  alt skipQuickAdd == true
    TaskCreationHelper->>Mediator: send(GetSettingQuery(taskDefaultEstimatedTime))
    Mediator-->>TaskCreationHelper: Setting or null
    TaskCreationHelper->>Mediator: send(GetSettingQuery(taskDefaultPlannedDateReminder))
    Mediator-->>TaskCreationHelper: Setting or null
    TaskCreationHelper->>TaskCreationHelper: build SaveTaskCommand
    TaskCreationHelper->>Mediator: send(SaveTaskCommand)
    Mediator-->>TaskCreationHelper: SaveTaskCommandResponse(id)
    TaskCreationHelper->>TasksService: notifyTaskCreated(id)
    TaskCreationHelper->>TaskDetailsPage: open in ResponsiveDialog(taskId=id)
  else skipQuickAdd == false
    TaskCreationHelper->>QuickAddTaskDialog: show(context, initialData)
    activate QuickAddTaskDialog
    QuickAddTaskDialog->>QuickAddTaskController: createTask(context, title, description, focusNode, onClearFields, isMobile, onSuccess)
    activate QuickAddTaskController
    QuickAddTaskController->>Mediator: send(SaveTaskCommand)
    Mediator-->>QuickAddTaskController: SaveTaskCommandResponse(id)
    QuickAddTaskController->>TasksService: notifyTaskCreated(id)
    QuickAddTaskController-->>QuickAddTaskDialog: onSuccess(id)
    deactivate QuickAddTaskController
    QuickAddTaskDialog-->>TaskAddButton: Navigator.pop(result=id)
    QuickAddTaskDialog->>TaskDetailsPage: open in ResponsiveDialog(taskId=id)
    deactivate QuickAddTaskDialog
  end
Loading

Class diagram for task creation flow and skip quick add setting

classDiagram
  class TaskCreationHelper {
    <<static>> createTask(context, initialTagIds, initialPlannedDate, initialDeadlineDate, initialPriority, initialEstimatedTime, initialTitle, initialCompleted, initialParentTaskId, onTaskCreated)
    <<static>> _createTaskImmediately(context, mediator, translationService, tasksService, initialTagIds, initialPlannedDate, initialDeadlineDate, initialPriority, initialEstimatedTime, initialTitle, initialCompleted, initialParentTaskId, onTaskCreated)
  }

  class QuickAddTaskDialog {
    +List~String~ initialTagIds
    +DateTime initialPlannedDate
    +DateTime initialDeadlineDate
    +EisenhowerPriority initialPriority
    +int initialEstimatedTime
    +String initialTitle
    +bool initialCompleted
    +String initialParentTaskId
    +static show(context, initialTagIds, initialPlannedDate, initialDeadlineDate, initialPriority, initialEstimatedTime, initialTitle, initialCompleted, initialParentTaskId, onTaskCreated)
  }

  class _QuickAddTaskDialogState {
    -QuickAddTaskController _controller
    -TextEditingController _titleController
    -TextEditingController _descriptionController
    -TextEditingController _plannedDateController
    -TextEditingController _deadlineDateController
    -FocusNode _focusNode
    +void _onControllerUpdate()
    +void _toggleLock(lockType)
    +Widget _buildLockAction(isLockedGetter, onToggle)
    +Future~void~ _selectPlannedDate()
    +Future~void~ _selectDeadlineDate()
    +Future~void~ _showPrioritySelectionDialog()
    +Future~void~ _showEstimatedTimeDialog()
    +Future~void~ _showDescriptionDialog()
    +Future~void~ _onClearAllFields()
    +void _createTask()
    +void _createAndOpenTask()
    +Widget _buildSendButton(theme, isMobile)
    +Widget _buildOpenTaskButton(theme, isMobile)
  }

  class QuickAddTaskController {
    -bool _lockTags
    -bool _lockPriority
    -bool _lockEstimatedTime
    -bool _lockPlannedDate
    -bool _lockDeadlineDate
    +bool get lockTags
    +bool get lockPriority
    +bool get lockEstimatedTime
    +bool get lockPlannedDate
    +bool get lockDeadlineDate
    +void toggleTagsLock()
    +void togglePriorityLock()
    +void toggleEstimatedTimeLock()
    +void togglePlannedDateLock()
    +void toggleDeadlineDateLock()
    +Future~void~ createTask(context, title, description, focusNode, onClearFields, isMobile, onSuccess)
  }

  class QuickActionButtonsBar {
    +QuickAddTaskController controller
    +TextEditingController descriptionController
    +VoidCallback onShowPriorityDialog
    +VoidCallback onShowEstimatedTimeDialog
    +VoidCallback onShowDescriptionDialog
    +VoidCallback onSelectPlannedDate
    +VoidCallback onSelectDeadlineDate
    +VoidCallback onClearAllFields
    +Widget tagLockAction
  }

  class TaskDatePickerConfig {
    +DateTime initialDate
    +DateTime firstDate
    +DateTime lastDate
    +DateTime rangeStart
    +DateTime rangeEnd
    +DialogSize dialogSize
    +acore.DateFormatType formatType
    +BuildContext context
    +List~Widget~ headerActions
    +TaskDatePickerConfig copyWith(initialDate, firstDate, lastDate, rangeStart, rangeEnd, dialogSize, formatType, context, headerActions)
  }

  class TagSelectDialog {
    +List~String~ initialSelectedTags
    +bool showNoneOption
    +bool initialNoneSelected
    +bool initialShowNoTagsFilter
    +int limit
    +bool showArchived
    +Widget headerAction
  }

  class TagSelectDropdown {
    +List~DropdownOption~ options
    +List~String~ initialSelectedValues
    +bool showNoneOption
    +bool initialNoneSelected
    +bool initialShowNoTagsFilter
    +Function onTagsSelected
    +Widget headerAction
    +ButtonStyle buttonStyle
  }

  class PrioritySelectionDialog {
    +EisenhowerPriority selectedPriority
    +ValueChanged~EisenhowerPriority?~ onPrioritySelected
    +ITranslationService translationService
    +ThemeData theme
    +Widget headerAction
  }

  class EstimatedTimeDialogContent {
    +Duration estimatedTime
    +ValueChanged~Duration~ onEstimatedTimeChanged
    +VoidCallback onConfirm
    +ITranslationService translationService
    +ThemeData theme
    +Widget headerAction
  }

  class TaskAddButton {
    +Future~void~ _showTaskCreationDialog()
  }

  class TaskAddFloatingButton {
    +Future~void~ _showTaskCreationDialog(context)
  }

  class SkipQuickAddSetting {
    +bool initialValue
  }

  class _SkipQuickAddSettingState {
    -Mediator _mediator
    -ITranslationService _translationService
    -bool _isEnabled
    -bool _isLoading
    +Future~void~ _loadSetting()
    +Future~void~ _onChanged(value)
    +Widget build(context)
  }

  class TaskSettings {
    +Widget build(context)
  }

  class TaskConstants {
    +int defaultEstimatedTime
    +ReminderTime defaultReminderTime
    +bool defaultSkipQuickAdd
  }

  class SettingKeys {
    +String taskSkipQuickAdd
  }

  class TaskDetailsPage {
    +String taskId
    +bool hideSidebar
  }

  class TasksService {
    +void notifyTaskCreated(taskId)
  }

  class Mediator {
    +Future send(request)
  }

  class ITranslationService {
    <<interface>>
    +String translate(key)
    +String translate(key, namedArgs)
  }

  class TaskData {
    +String title
    +EisenhowerPriority priority
    +int estimatedTime
    +DateTime plannedDate
    +DateTime deadlineDate
    +List tags
    +bool isCompleted
    +String parentTaskId
    +DateTime createdDate
  }

  TaskAddButton ..> TaskCreationHelper : uses
  TaskAddFloatingButton ..> TaskCreationHelper : uses
  TaskCreationHelper ..> Mediator : queriesSettings
  TaskCreationHelper ..> ITranslationService : uses
  TaskCreationHelper ..> TasksService : uses
  TaskCreationHelper ..> QuickAddTaskDialog : showsDialog
  TaskCreationHelper ..> TaskDetailsPage : opensOnImmediateCreate
  TaskCreationHelper ..> TaskConstants : readsDefaults
  TaskCreationHelper ..> SettingKeys : readsKeys
  TaskCreationHelper ..> TaskData : builds

  QuickAddTaskDialog --> _QuickAddTaskDialogState : createsState
  _QuickAddTaskDialogState ..> QuickAddTaskController : controls
  _QuickAddTaskDialogState ..> QuickActionButtonsBar : builds
  _QuickAddTaskDialogState ..> TaskDatePickerConfig : configures
  _QuickAddTaskDialogState ..> TaskDetailsPage : opensAfterCreate

  QuickActionButtonsBar ..> TagSelectDropdown : uses
  TagSelectDropdown ..> TagSelectDialog : shows

  QuickAddTaskController ..> Mediator : sendsSaveTaskCommand

  PrioritySelectionDialog ..> ITranslationService : uses
  EstimatedTimeDialogContent ..> ITranslationService : uses

  TaskSettings ..> SkipQuickAddSetting : contains
  SkipQuickAddSetting --> _SkipQuickAddSettingState : createsState
  _SkipQuickAddSettingState ..> Mediator : getSaveSetting
  _SkipQuickAddSettingState ..> TaskConstants : readsDefault
  _SkipQuickAddSettingState ..> SettingKeys : uses

  TaskConstants ..> ReminderTime : uses
Loading

File-Level Changes

Change Details Files
Refactor quick-add dialog to support creating-and-opening tasks, inline lock toggles, and improved button/validation behavior.
  • Wraps QuickAddTaskDialog.show dialog futures to, on successful task creation, open TaskDetailsPage in a responsive dialog when a non-empty taskId is returned.
  • Adds _createAndOpenTask using QuickAddTaskController.createTask with onSuccess callback that pops the dialog with taskId.
  • Extends QuickAddTaskController.createTask to accept an optional onSuccess callback and avoid refocusing the title field when provided.
  • Replaces global lock-settings dialog with per-field lock toggle buttons wired through new controller toggle*Lock methods and shared _buildLockAction helper, passing headerActions into date, priority, estimated-time, and tag dialogs.
  • Adds an "open task" icon next to the send button, and disables both actions when the title is empty or the controller is loading.
  • Adjusts desktop dialog sizing using AppTheme.dialogMaxWidthMedium and 80% viewport height, and ensures correct controller/listener disposal ordering.
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/quick_add_task_dialog.dart
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/controllers/quick_add_task_controller.dart
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/components/quick_action_buttons_bar.dart
src/lib/presentation/ui/features/tasks/components/task_date_picker_dialog.dart
src/lib/presentation/ui/shared/constants/app_theme.dart
src/lib/presentation/ui/features/tasks/components/dialogs/priority_selection_dialog.dart
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/builders/estimated_time_dialog_content.dart
src/lib/presentation/ui/features/tags/components/tag_select_dialog.dart
src/lib/presentation/ui/features/tags/components/tag_select_dropdown.dart
src/lib/presentation/ui/features/tasks/constants/task_translation_keys.dart
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/dialogs/lock_settings_dialog_content.dart
src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/models/lock_settings_state.dart
Introduce TaskCreationHelper and a new skipQuickAdd task preference, and integrate them into task creation entry points.
  • Adds TaskCreationHelper.createTask utility that checks TASK_SKIP_QUICK_ADD setting, then either opens QuickAddTaskDialog or immediately creates a task via SaveTaskCommand and opens TaskDetailsPage.
  • Loads and applies default estimated time and planned-date reminder settings when doing immediate creation; suppresses reminders when no planned date is provided.
  • Replaces direct QuickAddTaskDialog.show calls in TaskAddButton and TaskAddFloatingButton with TaskCreationHelper.createTask while preserving initial data wiring and onTaskCreated callbacks.
  • Introduces TaskConstants.defaultSkipQuickAdd and a new SettingKeys.taskSkipQuickAdd key for persistent storage.
src/lib/presentation/ui/features/tasks/utils/task_creation_helper.dart
src/lib/presentation/ui/features/tasks/components/task_add_button.dart
src/lib/presentation/ui/features/tasks/components/task_add_floating_button.dart
src/lib/core/domain/features/tasks/task_constants.dart
src/lib/presentation/ui/shared/constants/setting_keys.dart
Add SkipQuickAddSetting UI and wire it into task settings with localization support.
  • Implements SkipQuickAddSetting widget that loads/saves TASK_SKIP_QUICK_ADD via Mediator and SaveSettingCommand/GetSettingQuery, with optimistic switch toggling and error rollback.
  • Inserts SkipQuickAddSetting into TaskSettings page below default reminder configuration.
  • Defines SettingsTranslationKeys entries for skipQuickAdd title/description and adds localized strings for this setting across all supported locales.
src/lib/presentation/ui/features/settings/components/task_settings/skip_quick_add_setting.dart
src/lib/presentation/ui/features/settings/components/task_settings.dart
src/lib/presentation/ui/features/settings/constants/settings_translation_keys.dart
src/lib/presentation/ui/features/settings/assets/locales/en.yaml
src/lib/presentation/ui/features/settings/assets/locales/da.yaml
src/lib/presentation/ui/features/settings/assets/locales/fi.yaml
src/lib/presentation/ui/features/settings/assets/locales/ja.yaml
src/lib/presentation/ui/features/settings/assets/locales/ko.yaml
src/lib/presentation/ui/features/settings/assets/locales/no.yaml
src/lib/presentation/ui/features/settings/assets/locales/zh.yaml
src/lib/presentation/ui/features/settings/assets/locales/cs.yaml
src/lib/presentation/ui/features/settings/assets/locales/de.yaml
src/lib/presentation/ui/features/settings/assets/locales/el.yaml
src/lib/presentation/ui/features/settings/assets/locales/es.yaml
src/lib/presentation/ui/features/settings/assets/locales/fr.yaml
src/lib/presentation/ui/features/settings/assets/locales/it.yaml
src/lib/presentation/ui/features/settings/assets/locales/nl.yaml
src/lib/presentation/ui/features/settings/assets/locales/pl.yaml
src/lib/presentation/ui/features/settings/assets/locales/pt.yaml
src/lib/presentation/ui/features/settings/assets/locales/ro.yaml
src/lib/presentation/ui/features/settings/assets/locales/ru.yaml
src/lib/presentation/ui/features/settings/assets/locales/sl.yaml
src/lib/presentation/ui/features/settings/assets/locales/sv.yaml
src/lib/presentation/ui/features/settings/assets/locales/tr.yaml
src/lib/presentation/ui/features/settings/assets/locales/uk.yaml
Extend task UI and localization for better consistency (titles, hints, tooltips, lock labels).
  • Adds create_and_open_tooltip for the new "open task" button and new_task_default_title entries under tasks.quick_task or tasks root across locales.
  • Introduces quickTaskLock and quickTaskUnlock translation keys and corresponding localized strings ("Lock"/"Unlock" etc.) used by lock toggle tooltips.
  • Updates TaskDetailsContent title TextField decoration to include localized hint text using TaskTranslationKeys.titleLabel for consistency with quick-add dialog.
src/lib/presentation/ui/features/tasks/assets/locales/en.yaml
src/lib/presentation/ui/features/tasks/assets/locales/cs.yaml
src/lib/presentation/ui/features/tasks/assets/locales/da.yaml
src/lib/presentation/ui/features/tasks/assets/locales/de.yaml
src/lib/presentation/ui/features/tasks/assets/locales/el.yaml
src/lib/presentation/ui/features/tasks/assets/locales/es.yaml
src/lib/presentation/ui/features/tasks/assets/locales/fi.yaml
src/lib/presentation/ui/features/tasks/assets/locales/fr.yaml
src/lib/presentation/ui/features/tasks/assets/locales/it.yaml
src/lib/presentation/ui/features/tasks/assets/locales/ja.yaml
src/lib/presentation/ui/features/tasks/assets/locales/ko.yaml
src/lib/presentation/ui/features/tasks/assets/locales/nl.yaml
src/lib/presentation/ui/features/tasks/assets/locales/no.yaml
src/lib/presentation/ui/features/tasks/assets/locales/pl.yaml
src/lib/presentation/ui/features/tasks/assets/locales/pt.yaml
src/lib/presentation/ui/features/tasks/assets/locales/ro.yaml
src/lib/presentation/ui/features/tasks/assets/locales/ru.yaml
src/lib/presentation/ui/features/tasks/assets/locales/sl.yaml
src/lib/presentation/ui/features/tasks/assets/locales/sv.yaml
src/lib/presentation/ui/features/tasks/assets/locales/tr.yaml
src/lib/presentation/ui/features/tasks/assets/locales/uk.yaml
src/lib/presentation/ui/features/tasks/assets/locales/zh.yaml
src/lib/presentation/ui/features/tasks/components/task_details_content/task_details_content.dart

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @ahmet-cetinkaya, 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 enhances the task creation experience by offering users more control and flexibility. It introduces a new setting that allows users to streamline their workflow by optionally skipping the quick add dialog and directly accessing the comprehensive task details page. Furthermore, the quick add dialog itself has been refined with more intuitive state management for locking task properties, ensuring a smoother and more consistent user interface.

Highlights

  • New User Setting: Skip Quick Add Dialog: Introduced a new user setting that allows users to bypass the quick task creation dialog and directly navigate to the full task details page, streamlining the task creation workflow.
  • Enhanced Task Creation Flow: Refactored the task creation process by introducing a TaskCreationHelper utility, centralizing logic and improving consistency. This helper intelligently decides whether to show the quick add dialog or immediately create a task based on user preferences.
  • Improved Quick Add Dialog State Management: The Quick Add Task dialog has been enhanced with individual lock toggles for task properties (tags, priority, estimated time, planned date, deadline) directly within their respective sub-dialogs. This replaces the previous dedicated 'Lock Settings' dialog, simplifying the UI and improving user experience.
  • Direct Navigation to Task Details: A new 'Create and Open Task Details' button has been added to the Quick Add dialog, providing a direct path for users to create a task and immediately proceed to its detailed editing page.
  • Localization Updates: All new settings and UI enhancements, including tooltips and labels, have been localized across 22 supported languages to ensure a consistent experience for all users.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/lib/core/domain/features/tasks/task_constants.dart
    • Added defaultSkipQuickAdd constant to define the default behavior for skipping the quick add dialog.
  • src/lib/corePackages/acore
    • Updated the subproject commit to a newer version (eb7cf95fda65554f8d9e576891f5a9ffc884386f2 -> 00d826e7e7c46e768b560fb5e2368320a209b58d).
  • src/lib/presentation/ui/features/settings/assets/locales/*.yaml
    • Added new translation keys for the 'Skip Quick Add Dialog' setting (title and description) across all supported locales (e.g., cs, da, de, el, en, es, fi, fr, it, ja, ko, nl, no, pl, pt, ro, ru, sl, sv, tr, uk, zh).
  • src/lib/presentation/ui/features/settings/components/task_settings.dart
    • Integrated the new SkipQuickAddSetting widget into the task settings UI, allowing users to configure the quick add behavior.
  • src/lib/presentation/ui/features/settings/components/task_settings/skip_quick_add_setting.dart
    • Added a new widget responsible for managing the 'Skip Quick Add Dialog' user setting, including loading its current state and saving user preferences.
  • src/lib/presentation/ui/features/settings/constants/settings_translation_keys.dart
    • Added new translation keys (taskSkipQuickAddTitle, taskSkipQuickAddDescription) for the 'Skip Quick Add Dialog' setting.
  • src/lib/presentation/ui/features/tags/components/tag_select_dialog.dart
    • Introduced a headerAction parameter to allow custom widgets (like lock buttons) to be displayed in the app bar of the tag selection dialog.
  • src/lib/presentation/ui/features/tags/components/tag_select_dropdown.dart
    • Propagated the new headerAction parameter to the TagSelectDialog when it is opened from the dropdown.
  • src/lib/presentation/ui/features/tasks/assets/locales/*.yaml
    • Added new translation keys for 'Create and open task details' tooltip, 'Lock' and 'Unlock' tooltips, and a default title for new tasks across all supported locales.
  • src/lib/presentation/ui/features/tasks/components/dialogs/priority_selection_dialog.dart
    • Added a headerAction parameter to allow custom widgets (like a lock button) in the app bar of the priority selection dialog.
  • src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/builders/estimated_time_dialog_content.dart
    • Added a headerAction parameter to allow custom widgets (like a lock button) in the app bar of the estimated time dialog.
  • src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/components/quick_action_buttons_bar.dart
    • Removed the dedicated 'Lock Settings' button and its associated callback.
    • Added a tagLockAction parameter to allow a lock toggle for tags directly within the quick action bar.
  • src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/dialogs/lock_settings_dialog_content.dart
    • Removed this file, as its functionality has been integrated directly into the quick add dialog and its sub-dialogs.
  • src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/models/lock_settings_state.dart
    • Removed this file, simplifying state management for lock settings within the quick add task controller.
  • src/lib/presentation/ui/features/tasks/components/quick_add_task_dialog/quick_add_task_dialog.dart
    • Refactored lock state management to use individual toggle*Lock methods within the controller, replacing the LockSettingsState model.
    • Implemented _buildLockAction to create dynamic lock/unlock buttons for various task properties (priority, estimated time, planned date, deadline date, tags) directly within their respective dialogs.
    • Added a 'Create and Open Task Details' button (_buildOpenTaskButton) to the quick add input field, enabling immediate navigation to the full task details page upon creation.
    • Modified the show method to handle navigation to TaskDetailsPage if a task is created and the 'Create and Open' option is used.
    • Updated QuickActionButtonsBar and the main input field's suffix icons to reflect the new lock button integration and 'Create and Open' functionality.
    • Adjusted dialog constraints for better responsiveness on larger screens.
  • src/lib/presentation/ui/features/tasks/components/task_add_button.dart
    • Updated to use the new TaskCreationHelper.createTask for initiating task creation, centralizing the logic.
  • src/lib/presentation/ui/features/tasks/components/task_add_floating_button.dart
    • Updated to use the new TaskCreationHelper.createTask for initiating task creation, centralizing the logic.
  • src/lib/presentation/ui/features/tasks/components/task_date_picker_dialog.dart
    • Added a headerActions parameter to TaskDatePickerConfig to support custom actions (like a lock button) in the date picker dialog's app bar.
  • src/lib/presentation/ui/features/tasks/components/task_details_content/task_details_content.dart
    • Added a hint text to the task title input field for better user guidance.
  • src/lib/presentation/ui/features/tasks/constants/task_translation_keys.dart
    • Added new translation keys for lock/unlock tooltips (quickTaskLock, quickTaskUnlock), a default new task title (newTaskDefaultTitle), and the 'create and open task details' tooltip (createAndOpenTaskTooltip).
  • src/lib/presentation/ui/features/tasks/utils/task_creation_helper.dart
    • Added a new utility class to centralize task creation logic. This helper checks the skipQuickAdd setting and either directly creates a task (and opens its details) or invokes the QuickAddTaskDialog.
  • src/lib/presentation/ui/shared/constants/app_theme.dart
    • Added dialogMaxWidthMedium for consistent dialog sizing across the application.
  • src/lib/presentation/ui/shared/constants/setting_keys.dart
    • Added taskSkipQuickAdd as a new setting key to store the user's preference for skipping the quick add dialog.
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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In _QuickAddTaskDialogState._toggleLock you dispatch on string literals like 'priority'/'tags'; consider using an enum or passing explicit callbacks to avoid typo-prone magic strings and make the lock toggling easier to maintain.
  • In TaskCreationHelper._createTaskImmediately you fall back to finalTitle = initialTitle ?? '', which will create tasks with an empty title when called from the add buttons; consider using the new new_task_default_title translation as a default or preventing creation without a meaningful title.
  • In SkipQuickAddSetting._onChanged the error message key 'settings.task.skip_quick_add.save_error' is hard-coded and not defined in SettingsTranslationKeys or the locales like other settings; it would be more consistent and safer to add explicit translation keys/constants (including load/save errors) and use those instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `_QuickAddTaskDialogState._toggleLock` you dispatch on string literals like `'priority'`/`'tags'`; consider using an enum or passing explicit callbacks to avoid typo-prone magic strings and make the lock toggling easier to maintain.
- In `TaskCreationHelper._createTaskImmediately` you fall back to `finalTitle = initialTitle ?? ''`, which will create tasks with an empty title when called from the add buttons; consider using the new `new_task_default_title` translation as a default or preventing creation without a meaningful title.
- In `SkipQuickAddSetting._onChanged` the error message key `'settings.task.skip_quick_add.save_error'` is hard-coded and not defined in `SettingsTranslationKeys` or the locales like other settings; it would be more consistent and safer to add explicit translation keys/constants (including load/save errors) and use those instead.

## Individual Comments

### Comment 1
<location> `src/lib/presentation/ui/features/tasks/utils/task_creation_helper.dart:154` </location>
<code_context>
+      context: context,
+      errorMessage: translationService.translate(TaskTranslationKeys.saveTaskError),
+      operation: () async {
+        final finalTitle = initialTitle ?? ''; // Empty title by default
+
+        final command = SaveTaskCommand(
+          title: finalTitle,
+          description: '',
+          tagIdsToAdd: initialTagIds,
</code_context>

<issue_to_address>
**suggestion:** Creating tasks with an empty title by default may be undesirable given the new `new_task_default_title` translations.

Since `initialTitle` can be null, consider falling back to the localized default instead of an empty string, e.g.:
```dart
final finalTitle = (initialTitle?.trim().isNotEmpty == true)
    ? initialTitle!.trim()
    : translationService.translate(TaskTranslationKeys.newTaskDefaultTitle);
```
This both prevents visually empty tasks and uses the new localization key.

```suggestion
        final finalTitle = (initialTitle?.trim().isNotEmpty == true)
            ? initialTitle!.trim()
            : translationService.translate(TaskTranslationKeys.newTaskDefaultTitle);
```
</issue_to_address>

### Comment 2
<location> `src/lib/presentation/ui/features/settings/components/task_settings/skip_quick_add_setting.dart:74-75` </location>
<code_context>
+    await AsyncErrorHandler.executeWithLoading(
+      context: context,
+      setLoading: (_) {}, // No loading overlay for switch toggle
+      errorMessage: _translationService
+          .translate('settings.task.skip_quick_add.save_error'), // Fallback error message if key doesn't exist
+      operation: () async {
+        await _mediator.send<SaveSettingCommand, SaveSettingCommandResponse>(
</code_context>

<issue_to_address>
**issue (bug_risk):** The skip‑quick‑add save error message uses a hard‑coded key that does not appear to be localized, and bypasses the new translation constants.

This uses the literal key `'settings.task.skip_quick_add.save_error'`, but in most locales `skip_quick_add` only defines `title` and `description`, so users will likely see the raw key string.

You’ve added `SettingsTranslationKeys.taskSkipQuickAddTitle`/`Description` but not a constant for `save_error`.

Please either:
- Add `save_error` (and optionally `load_error`) under `skip_quick_add` in the settings locale files and introduce a matching `SettingsTranslationKeys` constant for the error, then use that here; or
- Reuse an existing generic settings save‑error key if you don’t want a dedicated one for this setting.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lib/presentation/ui/features/tasks/utils/task_creation_helper.dart Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 valuable new feature allowing users to skip the quick add dialog, and significantly refactors the task creation flow for better state management and UI consistency. The introduction of TaskCreationHelper centralizes task creation logic, and the removal of the separate lock settings dialog in favor of inline lock controls is a great simplification. The code is well-structured, and the UX improvements, such as disabling buttons when actions are unavailable, are well-implemented. I've included a few suggestions to further improve maintainability and user experience.

Comment on lines +101 to +139
// Load defaults if not provided
int? estimatedTime = initialEstimatedTime;
if (estimatedTime == null) {
try {
final setting = await mediator.send<GetSettingQuery, Setting?>(
GetSettingQuery(key: SettingKeys.taskDefaultEstimatedTime),
);
if (setting != null) {
final value = setting.getValue<int?>();
if (value != null && value > 0) estimatedTime = value;
}
} catch (_) {}
}

ReminderTime plannedDateReminderTime = ReminderTime.none;
int? plannedDateReminderCustomOffset;

try {
final setting = await mediator.send<GetSettingQuery, Setting?>(
GetSettingQuery(key: SettingKeys.taskDefaultPlannedDateReminder),
);
if (setting != null) {
final value = setting.getValue<String>();
plannedDateReminderTime = ReminderTimeExtension.fromString(value);

if (plannedDateReminderTime == ReminderTime.custom) {
final offsetSetting = await mediator.send<GetSettingQuery, Setting?>(
GetSettingQuery(key: SettingKeys.taskDefaultPlannedDateReminderCustomOffset),
);
if (offsetSetting != null) {
plannedDateReminderCustomOffset = offsetSetting.getValue<int?>();
}
}
} else {
plannedDateReminderTime = TaskConstants.defaultReminderTime;
}
} catch (_) {
plannedDateReminderTime = TaskConstants.defaultReminderTime;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The logic for loading default settings (estimated time and planned date reminder) appears to be duplicated between this new TaskCreationHelper and the existing QuickAddTaskController. To improve maintainability and ensure consistency, this logic could be extracted into a shared service or utility class that both can use. This would centralize the default-loading behavior and prevent potential future discrepancies.

context: context,
errorMessage: translationService.translate(TaskTranslationKeys.saveTaskError),
operation: () async {
final finalTitle = initialTitle ?? ''; // Empty title by default

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

When a task is created immediately via the 'skip quick add' flow without an initial title, it's created with an empty string. This pull request also introduces a new translation key, newTaskDefaultTitle, which seems intended for this scenario but is currently unused. Providing a default title like "New Task" would offer a better user experience, as the details page would open with a pre-filled, descriptive title rather than a blank one.

Suggested change
final finalTitle = initialTitle ?? ''; // Empty title by default
final finalTitle = initialTitle ?? translationService.translate(TaskTranslationKeys.newTaskDefaultTitle);

Comment on lines +171 to +209
onSuccess: (response) {
tasksService.notifyTaskCreated(response.id);

if (initialTitle != null && initialTitle.isNotEmpty) {
OverlayNotificationHelper.showSuccess(
context: context,
message: translationService.translate(
TaskTranslationKeys.taskAddedSuccessfully,
namedArgs: {'title': initialTitle},
),
);
}

if (onTaskCreated != null) {
final taskData = TaskData(
title: initialTitle ?? '',
priority: initialPriority,
estimatedTime: estimatedTime,
plannedDate: initialPlannedDate?.toUtc(),
deadlineDate: initialDeadlineDate?.toUtc(),
tags: [], // Tags handling would require fetching, skipping for now as UI usually refreshes
isCompleted: initialCompleted ?? false,
parentTaskId: initialParentTaskId,
createdDate: DateTime.now().toUtc(),
);
onTaskCreated(response.id, taskData);
}

if (context.mounted) {
ResponsiveDialogHelper.showResponsiveDialog(
context: context,
child: TaskDetailsPage(
taskId: response.id,
hideSidebar: true,
),
size: DialogSize.max,
);
}
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The onSuccess callback in _createTaskImmediately has grown quite large and handles multiple responsibilities, including notifying services, showing UI feedback, calling external callbacks, and handling navigation. For better readability and maintainability, consider refactoring this logic into smaller, well-named private helper methods. This would make the flow of operations clearer and the code easier to manage.

estimatedTime: estimatedTime,
plannedDate: initialPlannedDate?.toUtc(),
deadlineDate: initialDeadlineDate?.toUtc(),
tags: [], // Tags handling would require fetching, skipping for now as UI usually refreshes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The TaskData object created for the onTaskCreated callback is initialized with an empty tags list, as noted by the inline comment. This could lead to unexpected behavior for consumers of this callback if they rely on having the complete tag information. To make the callback data more reliable, consider fetching the tag details here or modifying TaskData to include the raw initialTagIds so the consumer can resolve them if needed.

@ahmet-cetinkaya

Copy link
Copy Markdown
Owner Author

🔍 PR Review: Task Creation Enhancements

Executive Summary

This PR adds valuable functionality but has 7 critical issues related to silent error handling and zero test coverage for new features. The code demonstrates good architecture understanding, but the lack of error logging and tests presents significant production risk.


🚨 Critical Issues (Must Fix Before Merge)

1-7. Silent Failures Throughout Codebase

Pattern: Multiple catch blocks silently swallow errors without logging.

Affected Files:

  • skip_quick_add_setting.dart:56-63
  • task_creation_helper.dart:39-48, 104-113, 118-139
  • quick_add_task_controller.dart:154-171, 174-201, 204-224

Example:

} catch (_) {
  // Ignore error, use default - NO LOGGING!
}

Impact:

  • Impossible to debug production issues
  • Settings silently fail to load
  • Users get unexpected behavior with no feedback
  • Cannot track error rates in monitoring

Required Fix:

} catch (e, stackTrace) {
  Logger.error(
    'Failed to load skip quick add setting',
    component: 'SkipQuickAddSetting',
    error: e,
    stackTrace: stackTrace,
  );
  // Continue with default
}

⚠️ Important Issues

8. Missing Translation Key Definition

File: skip_quick_add_setting.dart:74-75

errorMessage: _translationService
    .translate('settings.task.skip_quick_add.save_error'), // Key not in constants!

Fix: Add to settings_translation_keys.dart:

static const String taskSkipQuickAddSaveError = 'settings.task.skip_quick_add.save_error';

9. Hardcoded Empty Title Handling

File: task_creation_helper.dart:131

final finalTitle = initialTitle ?? ''; // Creates tasks with no title!

Issue: Tasks shouldn't be created without titles. Consider:

  1. Require title parameter (non-nullable)
  2. Use default from translations
  3. Don't create task if title is empty

10. String-Based Lock Toggle Pattern

File: quick_add_task_dialog.dart:194-219

void _toggleLock(String lockType) { // Error-prone!
  if (lockType == 'priority') ...
}

Better:

enum LockType { priority, estimatedTime, plannedDate, deadlineDate, tags }
void _toggleLock(LockType lockType) { ... }

🧪 Zero Test Coverage (Critical)

New functionality completely untested:

Component Lines Risk
TaskCreationHelper 212 🔴 CRITICAL
SkipQuickAddSetting 116 🔴 CRITICAL
Controller lock methods ~50 🟠 HIGH
Post-create navigation ~40 🟠 HIGH

Minimum tests needed before merge:

// task_creation_helper_test.dart
group('TaskCreationHelper', () {
  test('should show dialog when skipQuickAdd=false');
  test('should create immediately when skipQuickAdd=true');
  test('should handle setting load failures');
  test('should not crash on unmounted context');
});

// skip_quick_add_setting_test.dart
group('SkipQuickAddSetting', () {
  testWidgets('should load and display setting value');
  testWidgets('should save on toggle');
  testWidgets('should revert on save error');
});

✅ Strengths

  • ✅ Clean Architecture adherence (CQRS pattern)
  • ✅ Comprehensive localization (22 locales)
  • ✅ Proper dependency injection usage
  • ✅ Good widget organization
  • ✅ Code cleanup (removed obsolete files)

📋 Action Items

Before Merge (Required):

  • Add Logger.error() to all catch blocks
  • Define missing translation key constants
  • Add tests for TaskCreationHelper
  • Add tests for SkipQuickAddSetting widget
  • Address empty title handling

Should Fix:

  • Consider enum-based lock toggle for type safety
  • Add navigation error handling

Nice to Have:

  • Create centralized error ID system
  • Add widget tests for remaining components

Bottom Line: The feature implementation is solid, but the lack of error logging and test coverage is a blocker for production deployment. The fixes are straightforward - add logging and tests, then this is ready to merge.

- Add Logger.error to catch blocks in _loadSetting method
- Include stack traces for better debugging
- Maintains fallback behavior while logging failures

Addresses review comment: Silent failure in SkipQuickAddSetting._loadSetting()
- Add Logger.error to all catch blocks in TaskCreationHelper
- Add Logger.error to all catch blocks in QuickAddTaskController
- Include stack traces for production debugging
- Maintains fallback behavior while logging failures

Addresses review comments:
- Silent failure in TaskCreationHelper.createTask()
- Silent failure in TaskCreationHelper default settings loading
- Silent failure in QuickAddTaskController default settings loading
- Silent failure in QuickAddTaskController initial tags loading
- Add taskSkipQuickAddSaveError constant
- Add taskSkipQuickAddLoadError constant
- Update skip_quick_add_setting.dart to use constants

Addresses review comment: Missing translation key definition for error messages
- Add save_error and load_error translations
- Added to all 22 supported locales
- Provides proper user feedback for setting failures

Addresses review comment: Missing error message translations
- Add LockType enum with values: priority, estimatedTime, plannedDate, deadlineDate, tags
- Update _toggleLock method to use switch statement instead of if-else chains
- Update all call sites to use enum values
- Provides compile-time type safety and better IDE support

Addresses review comment: String-Based Lock Toggle Pattern
…d service

- Create IDefaultTaskSettingsService interface
- Create DefaultTaskSettingsService with caching
- Register service in DI container as singleton
- Update TaskCreationHelper to use shared service
- Update QuickAddTaskController to use shared service
- Remove ~50 lines of duplicated logic

Benefits:
- Single source of truth for default settings
- Improved performance with caching
- Easier testing with mockable interface
- Consistent error handling with logging

Addresses review comment: Duplicated Default Settings Loading
- Add tagIds field to TaskData model for complete tag information
- Refactor large onSuccess callback into focused helper methods:
  - _handleTaskCreationSuccess - main coordinator with error handling
  - _notifyTaskCreated - notifies tasks service
  - _showSuccessMessage - displays success notification
  - _invokeOnTaskCreatedCallback - calls custom callback
  - _navigateToTaskDetails - opens details page
- Each method has individual error handling and logging

Addresses review comments:
- Empty tags list in onTaskCreated callback
- Large onSuccess callback with multiple responsibilities
- Add _isSaving state field to track save operations
- Implement proper setLoading callback (was empty)
- Disable switch and tile during save to prevent concurrent saves
- Optimistic UI update with revert on error
- Improved error state management

Addresses review comment: Empty setLoading Callback
- task_creation_helper_test.dart: 11 tests covering dialog flow,
  immediate creation, default settings, callbacks, and errors
- skip_quick_add_setting_test.dart: 16 tests covering loading,
  saving, user interactions, and error states
- default_task_settings_service_test.dart: 15 tests covering
  estimated time, reminder settings, caching, and error handling

Total: 42 tests, 39 passing (3 skipped due to test environment dependencies)

Follows project test patterns:
- FakeContainer for dependency injection
- Mockito for mocking services
- AAA (Arrange-Act-Assert) pattern
- Descriptive test names

Addresses review comment: Zero Test Coverage for new functionality
Removed skip_quick_add_setting_test.dart and task_creation_helper_test.dart
due to complex mock setup requirements for widget testing.

Kept default_task_settings_service_test.dart which provides 15 passing
unit tests covering the shared service functionality.

Widget tests can be added later as a follow-up with proper mock setup.
@ahmet-cetinkaya ahmet-cetinkaya merged commit fa23c6f into main Feb 9, 2026
4 checks passed
@ahmet-cetinkaya ahmet-cetinkaya added P1 - Strategic High-impact features / Critical regressions impact-high bug Something isn't working habits Habit tracking features labels Feb 17, 2026
@ahmet-cetinkaya ahmet-cetinkaya deleted the feat/task-creation-enhancements branch May 22, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request habits Habit tracking features P1 - Strategic High-impact features / Critical regressions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant