From 27393d4cc8d4ffe23fa4c2b79273943119ae8640 Mon Sep 17 00:00:00 2001 From: dab246 Date: Thu, 18 Dec 2025 10:20:57 +0700 Subject: [PATCH] feat(ai-scribe): Add method to collapse selection and insert/replace callback --- ...andle_ai_scribe_in_composer_extension.dart | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/features/composer/presentation/extensions/ai_scribe/handle_ai_scribe_in_composer_extension.dart b/lib/features/composer/presentation/extensions/ai_scribe/handle_ai_scribe_in_composer_extension.dart index 5a4d8545f..048cc3421 100644 --- a/lib/features/composer/presentation/extensions/ai_scribe/handle_ai_scribe_in_composer_extension.dart +++ b/lib/features/composer/presentation/extensions/ai_scribe/handle_ai_scribe_in_composer_extension.dart @@ -1,10 +1,9 @@ import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/html/html_utils.dart'; import 'package:core/utils/platform_info.dart'; import 'package:core/utils/string_convert.dart'; import 'package:flutter/material.dart'; import 'package:scribe/scribe.dart'; -import 'package:scribe/scribe/ai/presentation/model/context_menu/ai_scribe_suggestion_actions.dart'; -import 'package:scribe/scribe/ai/presentation/model/modal/modal_cross_axis_alignment.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/text_selection_mixin.dart'; @@ -40,6 +39,45 @@ extension HandleAiScribeInComposerExtension on ComposerController { } } + Future collapseSelection() async { + if (PlatformInfo.isWeb) { + await richTextWebController?.editorController.evaluateJavascriptWeb( + HtmlUtils.collapseSelectionToEnd.name, + hasReturnValue: false, + ); + } else { + await richTextMobileTabletController?.htmlEditorApi?.webViewController + .evaluateJavascript( + source: HtmlUtils.collapseSelectionToEnd.script, + ); + } + } + + void clearTextInEditor() { + if (PlatformInfo.isWeb) { + richTextWebController?.editorController.setText(''); + } else { + richTextMobileTabletController?.htmlEditorApi?.setText(''); + } + } + + // Ensure we only insert at cursor position by collapsing selection before inserting + void onInsertTextCallback(String text) async { + await collapseSelection(); + + insertTextInEditor(text); + } + + // If there is a selection, it will replace the selection, else it will replace everything + void onReplaceTextCallback(String text) async { + final selection = editorTextSelection.value?.selectedText; + if (selection == null || selection.isEmpty) { + clearTextInEditor(); + } + + insertTextInEditor(text); + } + Future openAIAssistantModal(Offset? position, Size? size) async { final fullText = await _getTextOnlyContentInEditor(); @@ -59,11 +97,12 @@ extension HandleAiScribeInComposerExtension on ComposerController { AiScribeSuggestionActions action, String suggestionText, ) { - switch(action) { + switch (action) { case AiScribeSuggestionActions.replace: + onReplaceTextCallback(suggestionText); break; case AiScribeSuggestionActions.insert: - insertTextInEditor(suggestionText); + onInsertTextCallback(suggestionText); break; } }