Fix Scribe on responsive mobile
- Button was not added in MobileResponsiveAppBar - Mobile behavior related scripts were not correctly added for web composer - Mobile behavior related scripts return value was not properly handled for web composer - In responsive web, bottomsheet modal clicks were intercepted by iframe behind
This commit is contained in:
@@ -220,9 +220,12 @@ 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 selection.toString();
|
const result = selection.toString()
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: saveSelection", result }), "*");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
delete window._savedRange;
|
delete window._savedRange;
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: saveSelection", result: "" }), "*");
|
||||||
return "";
|
return "";
|
||||||
})();''',
|
})();''',
|
||||||
name: 'saveSelection');
|
name: 'saveSelection');
|
||||||
@@ -236,9 +239,12 @@ class HtmlUtils {
|
|||||||
selection.removeAllRanges();
|
selection.removeAllRanges();
|
||||||
selection.addRange(window._savedRange);
|
selection.addRange(window._savedRange);
|
||||||
delete window._savedRange;
|
delete window._savedRange;
|
||||||
return selection.toString();
|
const result = selection.toString()
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: restoreSelection", result }), "*");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: restoreSelection", result: "" }), "*");
|
||||||
return "";
|
return "";
|
||||||
})();''',
|
})();''',
|
||||||
name: 'restoreSelection');
|
name: 'restoreSelection');
|
||||||
@@ -247,8 +253,11 @@ class HtmlUtils {
|
|||||||
script: '''
|
script: '''
|
||||||
(() => {
|
(() => {
|
||||||
if(window._savedRange) {
|
if(window._savedRange) {
|
||||||
return window._savedRange.toString();
|
const result = window._savedRange.toString();
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: getSavedSelection", result }), "*");
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
window.parent.postMessage(JSON.stringify({ "type": "toDart: getSavedSelection", result: "" }), "*");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
})();''',
|
})();''',
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
saveToDraftsAction: () => controller.handleClickSaveAsDraftsButton(context),
|
saveToDraftsAction: () => controller.handleClickSaveAsDraftsButton(context),
|
||||||
saveToTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
|
saveToTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
|
||||||
deleteComposerAction: controller.handleClickDeleteComposer,
|
deleteComposerAction: controller.handleClickDeleteComposer,
|
||||||
|
onOpenAiAssistantModal: controller.isAIScribeAvailable
|
||||||
|
? controller.openAIAssistantModal
|
||||||
|
: null,
|
||||||
)),
|
)),
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
|
|||||||
+11
@@ -4,6 +4,7 @@ import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
|||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
|
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:scribe/scribe/ai/presentation/widgets/button/ai_assistant_button.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/highlight_svg_icon_on_hover.dart';
|
import 'package:tmail_ui_user/features/base/widget/highlight_svg_icon_on_hover.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
|
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart';
|
import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart';
|
||||||
@@ -32,6 +33,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
|
|||||||
final VoidCallback saveToTemplateAction;
|
final VoidCallback saveToTemplateAction;
|
||||||
final VoidCallback deleteComposerAction;
|
final VoidCallback deleteComposerAction;
|
||||||
final VoidCallback toggleMarkAsImportantAction;
|
final VoidCallback toggleMarkAsImportantAction;
|
||||||
|
final OnOpenAiAssistantModal? onOpenAiAssistantModal;
|
||||||
|
|
||||||
const MobileResponsiveAppBarComposerWidget({
|
const MobileResponsiveAppBarComposerWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -55,6 +57,7 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
|
|||||||
required this.saveToTemplateAction,
|
required this.saveToTemplateAction,
|
||||||
required this.deleteComposerAction,
|
required this.deleteComposerAction,
|
||||||
required this.toggleMarkAsImportantAction,
|
required this.toggleMarkAsImportantAction,
|
||||||
|
this.onOpenAiAssistantModal,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -74,6 +77,14 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget {
|
|||||||
onTapActionCallback: onCloseViewAction
|
onTapActionCallback: onCloseViewAction
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
|
if (onOpenAiAssistantModal != null)
|
||||||
|
AiAssistantButton(
|
||||||
|
imagePaths: imagePaths,
|
||||||
|
margin: const EdgeInsetsDirectional.only(
|
||||||
|
end: MobileAppBarComposerWidgetStyle.space,
|
||||||
|
),
|
||||||
|
onOpenAiAssistantModal: onOpenAiAssistantModal!,
|
||||||
|
),
|
||||||
TMailButtonWidget.fromIcon(
|
TMailButtonWidget.fromIcon(
|
||||||
icon: imagePaths.icRichToolbar,
|
icon: imagePaths.icRichToolbar,
|
||||||
padding: MobileAppBarComposerWidgetStyle.richTextIconPadding,
|
padding: MobileAppBarComposerWidgetStyle.richTextIconPadding,
|
||||||
|
|||||||
@@ -205,6 +205,22 @@ class _WebEditorState extends State<WebEditorWidget> with TextSelectionMixin {
|
|||||||
name: HtmlUtils.deleteSelectionContent.name,
|
name: HtmlUtils.deleteSelectionContent.name,
|
||||||
script: HtmlUtils.deleteSelectionContent.script,
|
script: HtmlUtils.deleteSelectionContent.script,
|
||||||
),
|
),
|
||||||
|
WebScript(
|
||||||
|
name: HtmlUtils.saveSelection.name,
|
||||||
|
script: HtmlUtils.saveSelection.script,
|
||||||
|
),
|
||||||
|
WebScript(
|
||||||
|
name: HtmlUtils.restoreSelection.name,
|
||||||
|
script: HtmlUtils.restoreSelection.script,
|
||||||
|
),
|
||||||
|
WebScript(
|
||||||
|
name: HtmlUtils.getSavedSelection.name,
|
||||||
|
script: HtmlUtils.getSavedSelection.script,
|
||||||
|
),
|
||||||
|
WebScript(
|
||||||
|
name: HtmlUtils.clearSavedSelection.name,
|
||||||
|
script: HtmlUtils.clearSavedSelection.script,
|
||||||
|
),
|
||||||
WebScript(
|
WebScript(
|
||||||
name: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).name,
|
name: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).name,
|
||||||
script: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).script,
|
script: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).script,
|
||||||
|
|||||||
+34
-31
@@ -2,6 +2,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
|||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
import 'package:scribe/scribe.dart';
|
import 'package:scribe/scribe.dart';
|
||||||
|
|
||||||
class AiScribeMobileActionsBottomSheet extends StatefulWidget {
|
class AiScribeMobileActionsBottomSheet extends StatefulWidget {
|
||||||
@@ -196,39 +197,41 @@ class _AiScribeMobileActionsBottomSheetState
|
|||||||
|
|
||||||
final hasContent = widget.content?.isNotEmpty ?? false;
|
final hasContent = widget.content?.isNotEmpty ?? false;
|
||||||
|
|
||||||
return Container(
|
return PointerInterceptor(
|
||||||
height: double.infinity,
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
height: double.infinity,
|
||||||
color: AIScribeColors.background,
|
decoration: const BoxDecoration(
|
||||||
),
|
color: AIScribeColors.background,
|
||||||
child: SafeArea(
|
),
|
||||||
child: Column(
|
child: SafeArea(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
Expanded(
|
children: [
|
||||||
child: Column(
|
Expanded(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
_buildHeader(context, localizations),
|
children: [
|
||||||
_buildTextCard(context),
|
_buildHeader(context, localizations),
|
||||||
if(hasContent)
|
_buildTextCard(context),
|
||||||
Flexible(
|
if(hasContent)
|
||||||
child: ValueListenableBuilder<AiScribeCategoryContextMenuAction?>(
|
Flexible(
|
||||||
valueListenable: _selectedCategory,
|
child: ValueListenableBuilder<AiScribeCategoryContextMenuAction?>(
|
||||||
builder: (context, selectedCategory, _) {
|
valueListenable: _selectedCategory,
|
||||||
return selectedCategory == null
|
builder: (context, selectedCategory, _) {
|
||||||
? _buildMenuListView(menuActions)
|
return selectedCategory == null
|
||||||
: _buildSubmenuListView();
|
? _buildMenuListView(menuActions)
|
||||||
},
|
: _buildSubmenuListView();
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
_buildBottomBar(context),
|
||||||
_buildBottomBar(context),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
+23
-20
@@ -1,5 +1,6 @@
|
|||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
import 'package:scribe/scribe.dart';
|
import 'package:scribe/scribe.dart';
|
||||||
|
|
||||||
class AiScribeMobileSuggestionBottomSheet extends StatefulWidget {
|
class AiScribeMobileSuggestionBottomSheet extends StatefulWidget {
|
||||||
@@ -41,27 +42,29 @@ class _AiScribeMobileSuggestionBottomSheetState
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localizations = ScribeLocalizations.of(context);
|
final localizations = ScribeLocalizations.of(context);
|
||||||
|
|
||||||
return Container(
|
return PointerInterceptor(
|
||||||
height: double.infinity,
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
height: double.infinity,
|
||||||
color: AIScribeColors.background,
|
decoration: const BoxDecoration(
|
||||||
),
|
color: AIScribeColors.background,
|
||||||
child: SafeArea(
|
),
|
||||||
child: Column(
|
child: SafeArea(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
Padding(
|
children: [
|
||||||
padding: AIScribeSizes.suggestionHeaderPadding,
|
Padding(
|
||||||
child: AiScribeSuggestionHeader(
|
padding: AIScribeSizes.suggestionHeaderPadding,
|
||||||
title: aiAction.getLabel(localizations),
|
child: AiScribeSuggestionHeader(
|
||||||
imagePaths: imagePaths,
|
title: aiAction.getLabel(localizations),
|
||||||
|
imagePaths: imagePaths,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Flexible(
|
||||||
Flexible(
|
child: buildStateContent(context),
|
||||||
child: buildStateContent(context),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user