Skip to content

fix(tags): add tag creation in select dialog#230

Merged
ahmet-cetinkaya merged 6 commits into
mainfrom
fix/onboarding-ux-and-cleanup
Feb 7, 2026
Merged

fix(tags): add tag creation in select dialog#230
ahmet-cetinkaya merged 6 commits into
mainfrom
fix/onboarding-ux-and-cleanup

Conversation

@ahmet-cetinkaya

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

Copy link
Copy Markdown
Owner

🚀 Motivation and Context

This PR adds the ability to create new tags directly from the tag selection dialog, improving the user workflow by eliminating the need to navigate away from the current context. Previously, users had to leave their task/habit/note editing flow to create a new tag in the tags section.

⚙️ Implementation Details

  • Added createTagButton translation key with translations for all 22 supported languages
  • Modified TagSelectDialog to show a "Create tag" option when search text doesn't match existing tags
  • Implemented _createAndSelectTag() method that creates the tag and automatically selects it
  • Added _shouldShowCreateOption getter to conditionally show the create option
  • The create option appears with a success color and add icon for clear visual indication

📋 Checklist for Reviewer

  • Tests passed locally (1745 tests)
  • Commit history is clean and descriptive
  • Translations added for all supported languages
  • Code quality standards were met (analysis passed)

🔗 Related

N/A

Summary by Sourcery

Allow creating and selecting new tags directly from the tag selection dialog while improving onboarding permissions handling and mobile initialization.

New Features:

  • Add a create-tag option in the tag selection dialog that appears when the search text does not match existing tags and automatically selects the newly created tag.
  • Introduce localized copy for the create-tag button across all supported languages.
  • Enable the onboarding dialog to reactively check and reflect notification permissions status via the notification service.

Enhancements:

  • Adjust onboarding dialog navigation to allow closing only from the first page and make its height responsive to screen size.
  • Visually distinguish the permissions button as completed using success-themed styling when permissions have been reviewed.
  • Ensure system tray initialization runs during mobile platform startup to support Android notification channel creation.

…management

- Add INotificationService dependency and widgets binding observer
- Implement app lifecycle state handling for permission checks
- Add permission status checking on dialog initialization and resume
- Update button styling based on permission status
- Allow back navigation when on first page only
- Refresh permissions after dialog closes
…in select dialog

Adds a new create button translation key for multiple languages and implements
the functionality to create new tags directly from the tag selection dialog.
The dialog now shows a create option when searching for non-existent tags,
allowing users to create and select tags in one flow.
@ahmet-cetinkaya ahmet-cetinkaya added bug Something isn't working ui User interface and user experience issues labels Feb 7, 2026
@ahmet-cetinkaya ahmet-cetinkaya self-assigned this Feb 7, 2026
@sourcery-ai

sourcery-ai Bot commented Feb 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Enables creating tags directly from the tag selection dialog, improves onboarding permissions handling/UX, ensures system tray initialization on mobile, and adds localized copy for the new tag-create action in all supported languages.

Sequence diagram for creating a new tag from TagSelectDialog

sequenceDiagram
    actor User
    participant TagSelectDialogState
    participant AsyncErrorHandler
    participant Mediator
    participant SaveTagCommand
    participant TagStore

    User->>TagSelectDialogState: Type search text
    TagSelectDialogState->>TagSelectDialogState: Evaluate _shouldShowCreateOption
    TagSelectDialogState-->>User: Show Create_tag_option

    User->>TagSelectDialogState: Tap Create_tag_option
    TagSelectDialogState->>AsyncErrorHandler: execute(operation: _createAndSelectTag)

    AsyncErrorHandler->>TagSelectDialogState: Invoke operation callback
    TagSelectDialogState->>SaveTagCommand: Create instance(name: searchText)
    TagSelectDialogState->>Mediator: send(command: SaveTagCommand)
    Mediator->>TagStore: Handle SaveTagCommand
    TagStore-->>Mediator: SaveTagCommandResponse(id)
    Mediator-->>AsyncErrorHandler: SaveTagCommandResponse
    AsyncErrorHandler-->>TagSelectDialogState: onSuccess(result)

    TagSelectDialogState->>TagSelectDialogState: setState(add result.id to _tempSelectedTags)
    TagSelectDialogState->>TagSelectDialogState: Clear _searchController
    TagSelectDialogState->>TagSelectDialogState: Set _tags = null
    TagSelectDialogState->>TagSelectDialogState: _getTags(pageIndex: 0)
    TagSelectDialogState-->>User: Updated tag list with new tag selected
Loading

Updated class diagram for tag selection, onboarding, and platform initialization

classDiagram
    class TagSelectDialogState {
      - ScrollController _scrollController
      - TextEditingController _searchController
      - dynamic _tags
      - Set~String~ _tempSelectedTags
      - bool _hasExplicitlySelectedNone
      + Widget build(BuildContext context)
      + Future _getTags(int pageIndex)
      + bool get _shouldShowCreateOption
      + Future _createAndSelectTag()
    }

    class AsyncErrorHandler {
      + Future execute(BuildContext context, String errorMessage, Future operation(), void onSuccess(dynamic result))
    }

    class Mediator {
      + Future send(SaveTagCommand command)
    }

    class SaveTagCommand {
      + String name
      + SaveTagCommand(String name)
    }

    class SaveTagCommandResponse {
      + String id
    }

    TagSelectDialogState --> AsyncErrorHandler : uses
    TagSelectDialogState --> Mediator : sends_commands
    TagSelectDialogState --> SaveTagCommand : creates
    Mediator --> SaveTagCommandResponse : returns

    class OnboardingDialogState {
      - ITranslationService _translationService
      - IThemeService _themeService
      - Mediator _mediator
      - INotificationService _notificationService
      - PageController _pageController
      - int _currentPage
      - String _selectedLanguageCode
      - bool _permissionsReviewed
      - List~_OnboardingStep~ _steps
      + void initState()
      + void dispose()
      + void didChangeAppLifecycleState(AppLifecycleState state)
      + Future _checkPermissions()
      + List~_OnboardingStep~ _buildSteps()
      + Widget build(BuildContext context)
      + Future _showPermissionsPage(BuildContext context)
      + Future _onLanguageChanged(String languageCode)
    }

    class INotificationService {
      + Future<bool> checkPermissionStatus()
    }

    OnboardingDialogState ..|> WidgetsBindingObserver : implements
    OnboardingDialogState --> INotificationService : uses

    class PlatformInitializationService {
      + Future initializeMobile(dynamic container)
      + Future _initializeAndroidServerMode(dynamic container)
      + Future _initializeSystemTray(dynamic container)
    }

    PlatformInitializationService --> SystemTrayComponent : initializes

    class SystemTrayComponent {
      + void setupNotificationChannels()
    }
Loading

File-Level Changes

Change Details Files
Allow creating a new tag directly from TagSelectDialog when the search text doesn’t match existing tags.
  • Adjust list itemCount and index handling to account for an optional "create tag" row between the tags header and tag items.
  • Introduce _shouldShowCreateOption getter to show the create row only when search text is non-empty and no tag name exactly matches it (case-insensitive).
  • Add a "Create tag" ListTile with success color and add icon that uses a parameterized translation string with the current search text.
  • Implement _createAndSelectTag to call SaveTagCommand via Mediator, handle errors via AsyncErrorHandler, select the created tag, clear the search field, reset the tag list and refresh it from page 0.
  • Import SaveTagCommand and related response types needed by the new create flow.
src/lib/presentation/ui/features/tags/components/tag_select_dialog.dart
src/lib/presentation/ui/features/tags/constants/tag_translation_keys.dart
Improve onboarding dialog lifecycle handling, permissions state refresh, and layout responsiveness.
  • Make _OnboardingDialogState a WidgetsBindingObserver, register/unregister in initState/dispose, and react to AppLifecycleState.resumed to re-check permissions.
  • Inject INotificationService and implement _checkPermissions to query mobile notification permission status, updating _permissionsReviewed and rebuilding steps when it changes.
  • Update _showPermissionsPage to re-check permissions after the dialog closes instead of unconditionally marking permissions as reviewed.
  • Visually distinguish the permissions button as completed by styling the OutlinedButton with AppTheme.successColor when permissions are reviewed.
  • Allow closing the onboarding dialog only on the first page (canPop depends on _currentPage) and make the dialog height responsive using MediaQuery instead of a fixed 400px height.
  • Reorder dispose implementation to cleanly dispose the PageController alongside removing the observer.
src/lib/presentation/ui/features/about/components/onboarding_dialog.dart
Ensure mobile platform initialization sets up the system tray, needed for Android notification channels.
  • Call _initializeSystemTray during mobile initialization after server mode initialization to guarantee notification-related system tray setup.
src/lib/presentation/ui/shared/services/platform_initialization_service.dart
Add localized text for the new "create tag" action across all supported languages.
  • Introduce the create_button entry under tags.actions in each locale yaml with a parameterized {name} placeholder that is used to render the "Create "{name}" tag" label in the dialog.
  • Expose the new translation key via TagTranslationKeys.createTagButton for use in the UI.
src/lib/presentation/ui/features/tags/assets/locales/cs.yaml
src/lib/presentation/ui/features/tags/assets/locales/da.yaml
src/lib/presentation/ui/features/tags/assets/locales/de.yaml
src/lib/presentation/ui/features/tags/assets/locales/el.yaml
src/lib/presentation/ui/features/tags/assets/locales/en.yaml
src/lib/presentation/ui/features/tags/assets/locales/es.yaml
src/lib/presentation/ui/features/tags/assets/locales/fi.yaml
src/lib/presentation/ui/features/tags/assets/locales/fr.yaml
src/lib/presentation/ui/features/tags/assets/locales/it.yaml
src/lib/presentation/ui/features/tags/assets/locales/ja.yaml
src/lib/presentation/ui/features/tags/assets/locales/ko.yaml
src/lib/presentation/ui/features/tags/assets/locales/nl.yaml
src/lib/presentation/ui/features/tags/assets/locales/no.yaml
src/lib/presentation/ui/features/tags/assets/locales/pl.yaml
src/lib/presentation/ui/features/tags/assets/locales/pt.yaml
src/lib/presentation/ui/features/tags/assets/locales/ro.yaml
src/lib/presentation/ui/features/tags/assets/locales/ru.yaml
src/lib/presentation/ui/features/tags/assets/locales/sl.yaml
src/lib/presentation/ui/features/tags/assets/locales/sv.yaml
src/lib/presentation/ui/features/tags/assets/locales/tr.yaml
src/lib/presentation/ui/features/tags/assets/locales/uk.yaml
src/lib/presentation/ui/features/tags/assets/locales/zh.yaml

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 introduces a significant quality-of-life improvement by integrating tag creation directly into the tag selection dialog. This change streamlines the user workflow, allowing users to create and select new tags without interrupting their current task, habit, or note editing process, thereby enhancing efficiency and reducing friction.

Highlights

  • Direct Tag Creation: Users can now create new tags directly from the tag selection dialog, eliminating the need to navigate to a separate section.
  • Dynamic 'Create Tag' Option: A 'Create tag' option dynamically appears in the dialog when the user's search input does not match any existing tags.
  • Automatic Selection: Newly created tags are automatically selected and added to the current selection upon creation.
  • Localization Support: The new 'Create tag' button includes translations for all 22 supported languages.

🧠 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/presentation/ui/features/about/components/onboarding_dialog.dart
    • Integrated INotificationService for managing notification permissions.
    • Implemented WidgetsBindingObserver to monitor app lifecycle, allowing permission checks to be refreshed when the app resumes.
    • Updated the permissions button style to visually indicate the permission status (e.g., success color for granted permissions).
    • Adjusted the PopScope behavior to allow popping only on the first page of the onboarding dialog.
    • Modified the SizedBox height for the PageView.builder to be dynamic, adapting to screen height while capping at 400 pixels for better responsiveness.
  • src/lib/presentation/ui/features/tags/assets/locales/cs.yaml
    • Added create_button translation key for Czech.
  • src/lib/presentation/ui/features/tags/assets/locales/da.yaml
    • Added create_button translation key for Danish.
  • src/lib/presentation/ui/features/tags/assets/locales/de.yaml
    • Added create_button translation key for German.
  • src/lib/presentation/ui/features/tags/assets/locales/el.yaml
    • Added create_button translation key for Greek.
  • src/lib/presentation/ui/features/tags/assets/locales/en.yaml
    • Added create_button translation key for English.
  • src/lib/presentation/ui/features/tags/assets/locales/es.yaml
    • Added create_button translation key for Spanish.
  • src/lib/presentation/ui/features/tags/assets/locales/fi.yaml
    • Added create_button translation key for Finnish.
  • src/lib/presentation/ui/features/tags/assets/locales/fr.yaml
    • Added create_button translation key for French.
  • src/lib/presentation/ui/features/tags/assets/locales/it.yaml
    • Added create_button translation key for Italian.
  • src/lib/presentation/ui/features/tags/assets/locales/ja.yaml
    • Added create_button translation key for Japanese.
  • src/lib/presentation/ui/features/tags/assets/locales/ko.yaml
    • Added create_button translation key for Korean.
  • src/lib/presentation/ui/features/tags/assets/locales/nl.yaml
    • Added create_button translation key for Dutch.
  • src/lib/presentation/ui/features/tags/assets/locales/no.yaml
    • Added create_button translation key for Norwegian.
  • src/lib/presentation/ui/features/tags/assets/locales/pl.yaml
    • Added create_button translation key for Polish.
  • src/lib/presentation/ui/features/tags/assets/locales/pt.yaml
    • Added create_button translation key for Portuguese.
  • src/lib/presentation/ui/features/tags/assets/locales/ro.yaml
    • Added create_button translation key for Romanian.
  • src/lib/presentation/ui/features/tags/assets/locales/ru.yaml
    • Added create_button translation key for Russian.
  • src/lib/presentation/ui/features/tags/assets/locales/sl.yaml
    • Added create_button translation key for Slovenian.
  • src/lib/presentation/ui/features/tags/assets/locales/sv.yaml
    • Added create_button translation key for Swedish.
  • src/lib/presentation/ui/features/tags/assets/locales/tr.yaml
    • Added create_button translation key for Turkish.
  • src/lib/presentation/ui/features/tags/assets/locales/uk.yaml
    • Added create_button translation key for Ukrainian.
  • src/lib/presentation/ui/features/tags/assets/locales/zh.yaml
    • Added create_button translation key for Chinese.
  • src/lib/presentation/ui/features/tags/components/tag_select_dialog.dart
    • Imported SaveTagCommand for creating new tags.
    • Modified ListView.builder to conditionally include a 'Create tag' option in the item count.
    • Implemented a new ListTile item that displays 'Create "{name}" tag' with an add icon and success styling.
    • Added a _shouldShowCreateOption getter to determine when the 'Create tag' option should be visible (when search text is not empty and no existing tag matches).
    • Implemented _createAndSelectTag() method to handle the creation of a new tag via SaveTagCommand, automatically select it, clear the search, and refresh the tag list.
  • src/lib/presentation/ui/features/tags/constants/tag_translation_keys.dart
    • Added createTagButton as a new static constant for the tag creation translation key.
  • src/lib/presentation/ui/shared/services/platform_initialization_service.dart
    • Added _initializeSystemTray(container) call during mobile platform initialization, which is necessary for creating notification channels on Android.
Activity
  • No specific activity (comments, reviews) was provided in the context.
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 left some high level feedback:

  • The TagTranslationKeys.createTagButton key is defined as tags.actions.create_button but the locale files add create_button directly under tags, so either the key path or the YAML nesting should be adjusted to match or the translations won’t resolve at runtime.
  • In _OnboardingDialogState._checkPermissions you rebuild _steps and call setState whenever the permission status changes; if only the button style/icon depend on _permissionsReviewed, consider deriving that directly in the build method to avoid regenerating the step list on each permission check.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `TagTranslationKeys.createTagButton` key is defined as `tags.actions.create_button` but the locale files add `create_button` directly under `tags`, so either the key path or the YAML nesting should be adjusted to match or the translations won’t resolve at runtime.
- In `_OnboardingDialogState._checkPermissions` you rebuild `_steps` and call `setState` whenever the permission status changes; if only the button style/icon depend on `_permissionsReviewed`, consider deriving that directly in the build method to avoid regenerating the step list on each permission check.

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.

@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 feature allowing users to create tags directly from the selection dialog, which significantly improves the workflow. The implementation is well-structured, especially the refactoring in TagSelectDialog to handle dynamic list items. The accompanying enhancements to the onboarding dialog, such as responsive height and more robust permission checking, are also great additions.

I've found one functional issue in the new tag creation logic that doesn't respect the single-selection mode or the 'None' option state, which I've detailed in a comment. Overall, this is a solid contribution with thoughtful improvements to the user experience.

Comment on lines +393 to +397
setState(() {
_tempSelectedTags.add(result.id);
_searchController.clear();
_tags = null; // Refresh list to include new tag
});

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.

high

When creating a new tag, there are a couple of state-handling issues that should be addressed to ensure consistent behavior with the rest of the dialog:

  1. Single-select mode: If isMultiSelect is false, creating a new tag should clear any previously selected tag. The current code just adds the new tag, which could lead to multiple selections.
  2. 'None' option state: If the 'None' option was selected (_hasExplicitlySelectedNone is true), creating a new tag should set this to false.

I've suggested a change to the setState block to handle both of these cases correctly, aligning it with the logic used when selecting existing tags from the list.

          setState(() {
            if (_hasExplicitlySelectedNone) {
              _hasExplicitlySelectedNone = false;
            }
            if (!widget.isMultiSelect) {
              _tempSelectedTags.clear();
            }
            _tempSelectedTags.add(result.id);
            _searchController.clear();
            _tags = null; // Refresh list to include new tag
          });

@ahmet-cetinkaya ahmet-cetinkaya left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

PR Review: #230 "fix(tags): add tag creation in select dialog"

Overall Assessment

This PR adds useful functionality for creating tags directly in the selection dialog, which is a great UX improvement. The code generally follows project patterns and all tests pass. However, there are some error handling and code clarity issues that should be addressed.

Medium Issues (Should Fix)

1. Potential silent failure after tag creation

Location: tag_select_dialog.dart:398

The _getTags(pageIndex: 0) call inside the onSuccess callback is not wrapped in error handling. If the list refresh fails, users will be in an inconsistent state (tag created but list empty).

Suggestion: Move _getTags inside the main operation callback for atomicity, or add explicit error handling.

2. Missing error context

Location: tag_select_dialog.dart:384-401

Uses generic unexpectedError message instead of a specific tag creation error. This makes debugging production issues difficult.

Suggestion: Create a specific translation key like TagTranslationKeys.createTagError.

3. Potential race condition with mounted check

Location: tag_select_dialog.dart:398

The _getTags call is outside the mounted check scope:

onSuccess: (result) {
  if (mounted) {
    setState(() { ... });
    _getTags(pageIndex: 0);  // Called outside mounted check
  }
}

Suggestion: Move _getTags inside the mounted check or add a separate check.

4. Complex itemBuilder logic

Location: tag_select_dialog.dart:238-275

The currentIndex tracking approach creates confusing control flow that's hard to follow and maintain.

Suggestion: Consider extracting to separate _build*Tile() methods for better clarity.

Low Issues (Consider Fixing)

5. No client-side tag name validation

Location: tag_select_dialog.dart:382

Only checks for empty string. Adding client-side validation (min/max length, invalid characters) would provide immediate feedback.

6. Case-insensitive matching consistency

Location: tag_select_dialog.dart:377

The toLowerCase() comparison for duplicate detection should be verified to match backend behavior.

Positive Notes ✅

  • Proper use of currentIndex pattern for extensibility
  • Good separation of concerns with dedicated getter and method
  • Consistent use of AsyncErrorHandler following project patterns
  • Proper mounted checks before setState
  • Comprehensive translations for all 22 languages
  • All 1,745 tests pass

Recommendation

Request Changes - Please address issues #1, #2, and #3 before merging for better robustness. Issues #4-6 are optional improvements that could be handled as follow-up.


Review generated via PR Review Toolkit

Fixes state management issues when creating a new tag from the select dialog:
- Clear 'None' option state (_hasExplicitlySelectedNone) when creating a tag
- In single-select mode, clear previously selected tags before adding new one
- Move _getTags call inside mounted check for better lifecycle safety

These changes align the tag creation behavior with the existing tag selection
logic, ensuring consistent state management across all selection modes.

Addresses review comments from PR #230.
Adds a specific error translation key (createTagError) for tag creation
failures in the select dialog, providing better debugging information
than the generic unexpectedError message.

Changes:
- Added createTagError translation key to tag_translation_keys.dart
- Added translated error messages to all 22 locale files
- Updated AsyncErrorHandler to use the specific error message

This addresses review feedback requesting more context-specific error
messages for better user experience and production debugging.

Addresses review comments from PR #230.
@ahmet-cetinkaya ahmet-cetinkaya merged commit 8519b43 into main Feb 7, 2026
3 checks passed
@ahmet-cetinkaya ahmet-cetinkaya added P2 - Enhancement Feature expansions and UX improvements impact-medium labels Feb 17, 2026
@ahmet-cetinkaya ahmet-cetinkaya deleted the fix/onboarding-ux-and-cleanup 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 P2 - Enhancement Feature expansions and UX improvements ui User interface and user experience issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant