Fix Scribe mobile issues
- Fix Scribe replace on mobile when opened from menu bar (to be complete this fix needs this PR https://github.com/Enough-Software/enough_html_editor/pull/37) - Ensure all mobile editor call are awaited - Do not clear text if a selection has been restored (which mean we replace a selection) - Avoid collapseToEnd crash
This commit is contained in:
@@ -197,7 +197,7 @@ class HtmlUtils {
|
|||||||
script: '''
|
script: '''
|
||||||
(() => {
|
(() => {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (selection) {
|
if (selection && selection.rangeCount > 0) {
|
||||||
selection.collapseToEnd()
|
selection.collapseToEnd()
|
||||||
}
|
}
|
||||||
})();''',
|
})();''',
|
||||||
@@ -220,9 +220,10 @@ class HtmlUtils {
|
|||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (selection && selection.rangeCount > 0) {
|
if (selection && selection.rangeCount > 0) {
|
||||||
window._savedRange = selection.getRangeAt(0).cloneRange();
|
window._savedRange = selection.getRangeAt(0).cloneRange();
|
||||||
return true;
|
return selection.toString();
|
||||||
}
|
}
|
||||||
return false;
|
delete window._savedRange;
|
||||||
|
return "";
|
||||||
})();''',
|
})();''',
|
||||||
name: 'saveSelection');
|
name: 'saveSelection');
|
||||||
|
|
||||||
@@ -234,10 +235,10 @@ class HtmlUtils {
|
|||||||
if (selection) {
|
if (selection) {
|
||||||
selection.removeAllRanges();
|
selection.removeAllRanges();
|
||||||
selection.addRange(window._savedRange);
|
selection.addRange(window._savedRange);
|
||||||
return true;
|
return selection.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return "";
|
||||||
})();''',
|
})();''',
|
||||||
name: 'restoreSelection');
|
name: 'restoreSelection');
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -21,7 +21,10 @@ class RichTextMobileTabletController extends GetxController {
|
|||||||
|
|
||||||
Future<void> focus() async {
|
Future<void> focus() async {
|
||||||
try {
|
try {
|
||||||
await htmlEditorApi?.webViewController.evaluateJavascript(source: "document.getElementById('editor').focus();");
|
await htmlEditorApi?.webViewController.evaluateJavascript(source: '''
|
||||||
|
(() => {
|
||||||
|
document.getElementById('editor').focus();
|
||||||
|
})();''');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logWarning('RichTextMobileTabletController::focus:Exception: $e');
|
logWarning('RichTextMobileTabletController::focus:Exception: $e');
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-24
@@ -35,6 +35,10 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> insertTextInEditor(String text) async {
|
Future<void> insertTextInEditor(String text) async {
|
||||||
|
if (PlatformInfo.isMobile) {
|
||||||
|
await ensureMobileEditorFocused();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final htmlContent = StringConvert.convertTextContentToHtmlContent(text);
|
final htmlContent = StringConvert.convertTextContentToHtmlContent(text);
|
||||||
|
|
||||||
@@ -46,7 +50,7 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
|
|
||||||
richTextWebController?.editorController.insertHtml(htmlContent);
|
richTextWebController?.editorController.insertHtml(htmlContent);
|
||||||
} else {
|
} else {
|
||||||
richTextMobileTabletController?.htmlEditorApi?.insertHtml(htmlContent);
|
await richTextMobileTabletController?.htmlEditorApi?.insertHtml(htmlContent);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logWarning('$runtimeType::insertTextInEditor:Exception = $e');
|
logWarning('$runtimeType::insertTextInEditor:Exception = $e');
|
||||||
@@ -71,45 +75,45 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> saveSelection() async {
|
Future<String> saveSelection() async {
|
||||||
try {
|
try {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
final result = await richTextWebController?.editorController.evaluateJavascriptWeb(
|
final result = await richTextWebController?.editorController.evaluateJavascriptWeb(
|
||||||
HtmlUtils.saveSelection.name,
|
HtmlUtils.saveSelection.name,
|
||||||
hasReturnValue: true,
|
hasReturnValue: true,
|
||||||
) ?? false;
|
);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
final result = await richTextMobileTabletController?.htmlEditorApi?.webViewController
|
final result = await richTextMobileTabletController?.htmlEditorApi?.webViewController
|
||||||
.evaluateJavascript(
|
.evaluateJavascript(
|
||||||
source: HtmlUtils.saveSelection.script,
|
source: HtmlUtils.saveSelection.script,
|
||||||
) ?? false;
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('$runtimeType::saveSelection:Exception = $e');
|
logError('$runtimeType::saveSelection:Exception = $e');
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> restoreSelection() async {
|
Future<String> restoreSelection() async {
|
||||||
try {
|
try {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
final result = await richTextWebController?.editorController.evaluateJavascriptWeb(
|
final result = await richTextWebController?.editorController.evaluateJavascriptWeb(
|
||||||
HtmlUtils.restoreSelection.name,
|
HtmlUtils.restoreSelection.name,
|
||||||
hasReturnValue: true,
|
hasReturnValue: true,
|
||||||
) ?? false;
|
);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
final result = await richTextMobileTabletController?.htmlEditorApi?.webViewController
|
final result = await richTextMobileTabletController?.htmlEditorApi?.webViewController
|
||||||
.evaluateJavascript(
|
.evaluateJavascript(
|
||||||
source: HtmlUtils.restoreSelection.script,
|
source: HtmlUtils.restoreSelection.script,
|
||||||
) ?? false;
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('$runtimeType::restoreSelection:Exception = $e');
|
logError('$runtimeType::restoreSelection:Exception = $e');
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,10 +146,8 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveAndUnfocusForModal() async {
|
Future<void> saveAndUnfocusForModal() async {
|
||||||
final saved = await saveSelection();
|
await saveSelection();
|
||||||
if (saved) {
|
await unfocusEditor();
|
||||||
await unfocusEditor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> ensureMobileEditorFocused() async {
|
Future<void> ensureMobileEditorFocused() async {
|
||||||
@@ -156,12 +158,12 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearTextInEditor() {
|
Future<void> clearTextInEditor() async {
|
||||||
try {
|
try {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
richTextWebController?.editorController.setText('');
|
richTextWebController?.editorController.setText('');
|
||||||
} else {
|
} else {
|
||||||
richTextMobileTabletController?.htmlEditorApi?.setText('');
|
await richTextMobileTabletController?.htmlEditorApi?.setText('');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logWarning('$runtimeType::clearTextInEditor:Exception = $e');
|
logWarning('$runtimeType::clearTextInEditor:Exception = $e');
|
||||||
@@ -178,12 +180,10 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
Future<void> onReplaceTextCallback(String text) async {
|
Future<void> onReplaceTextCallback(String text) async {
|
||||||
final selection = editorTextSelection.value?.selectedText;
|
final selection = editorTextSelection.value?.selectedText;
|
||||||
|
|
||||||
if (PlatformInfo.isMobile) {
|
final isSelectionRestored = PlatformInfo.isMobile ? await restoreSelection() : "";
|
||||||
await restoreSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selection == null || selection.isEmpty) {
|
if ((selection == null || selection.isEmpty) && isSelectionRestored.isEmpty) {
|
||||||
clearTextInEditor();
|
await clearTextInEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
await insertTextInEditor(text);
|
await insertTextInEditor(text);
|
||||||
@@ -215,10 +215,6 @@ extension HandleAiScribeInComposerExtension on ComposerController {
|
|||||||
AiScribeSuggestionActions action,
|
AiScribeSuggestionActions action,
|
||||||
String suggestionText,
|
String suggestionText,
|
||||||
) async {
|
) async {
|
||||||
if (PlatformInfo.isMobile) {
|
|
||||||
await ensureMobileEditorFocused();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case AiScribeSuggestionActions.replace:
|
case AiScribeSuggestionActions.replace:
|
||||||
await onReplaceTextCallback(suggestionText);
|
await onReplaceTextCallback(suggestionText);
|
||||||
|
|||||||
Reference in New Issue
Block a user