TF-3911 Support mail keyboard shortcut actions in email detailed view on web
This commit is contained in:
@@ -106,6 +106,7 @@ export 'presentation/views/button/multi_click_widget.dart';
|
||||
export 'presentation/views/semantics/checkbox_semantics.dart';
|
||||
export 'presentation/views/semantics/text_field_semantics.dart';
|
||||
export 'presentation/views/semantics/icon_semantics.dart';
|
||||
export 'presentation/views/shortcut/key_shortcut.dart';
|
||||
|
||||
// Resources
|
||||
export 'presentation/resources/assets_paths.dart';
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:core/presentation/constants/constants_ui.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/views/shortcut/key_shortcut.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/html/html_interaction.dart';
|
||||
import 'package:core/utils/html/html_template.dart';
|
||||
@@ -14,6 +15,7 @@ import 'package:universal_html/html.dart' as html;
|
||||
|
||||
typedef OnClickHyperLinkAction = Function(Uri?);
|
||||
typedef OnMailtoClicked = void Function(Uri? uri);
|
||||
typedef OnIFrameKeyboardShortcutAction = void Function(KeyShortcut keyShortcut);
|
||||
|
||||
class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
|
||||
@@ -30,6 +32,8 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
|
||||
final OnClickHyperLinkAction? onClickHyperLinkAction;
|
||||
|
||||
final OnIFrameKeyboardShortcutAction? onIFrameKeyboardShortcutAction;
|
||||
|
||||
// if widthContent is bigger than width of htmlContent, set this to true let widget able to resize to width of htmlContent
|
||||
final bool allowResizeToDocumentSize;
|
||||
|
||||
@@ -66,6 +70,7 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
this.htmlContentMinWidth = ConstantsUI.htmlContentMinWidth,
|
||||
this.offsetHtmlContentHeight = ConstantsUI.htmlContentOffsetHeight,
|
||||
this.viewMaxHeight,
|
||||
this.onIFrameKeyboardShortcutAction,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -116,6 +121,9 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb>
|
||||
} else if (_isScrollingIsAvailable && _isScrollEndEventTriggered(type)) {
|
||||
_handleIframeOnScrollEndListener(data, widget.scrollController!);
|
||||
return;
|
||||
} else if (_isIframeKeyboardEventTriggered(type)) {
|
||||
_handleOnIFrameKeyboardEvent(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data['message'] == iframeOnLoadMessage) {
|
||||
@@ -257,6 +265,21 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb>
|
||||
}
|
||||
}
|
||||
|
||||
bool _isIframeKeyboardEventTriggered(String? type) {
|
||||
return widget.onIFrameKeyboardShortcutAction != null &&
|
||||
type?.contains('toDart: iframeKeydown') == true;
|
||||
}
|
||||
|
||||
void _handleOnIFrameKeyboardEvent(dynamic data) {
|
||||
final shortcut = KeyShortcut(
|
||||
key: data['key'] as String,
|
||||
code: data['code'] as String,
|
||||
shift: data['shift'] == true,
|
||||
);
|
||||
log('_HtmlContentViewerOnWebState::_handleOnIFrameKeyboardEvent:📥 Shortcut pressed: $shortcut');
|
||||
widget.onIFrameKeyboardShortcutAction?.call(shortcut);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant HtmlContentViewerOnWeb oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
@@ -397,6 +420,8 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb>
|
||||
viewId: _createdViewId,
|
||||
onScrollChangedEvent: onScrollChangedEvent,
|
||||
),
|
||||
if (widget.onIFrameKeyboardShortcutAction != null)
|
||||
HtmlInteraction.scriptHandleIframeKeyboardListener(_createdViewId),
|
||||
].join();
|
||||
|
||||
final htmlTemplate = HtmlUtils.generateHtmlDocument(
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class KeyShortcut with EquatableMixin{
|
||||
final String key;
|
||||
final String code;
|
||||
final bool shift;
|
||||
|
||||
KeyShortcut({
|
||||
required this.key,
|
||||
required this.code,
|
||||
this.shift = false,
|
||||
});
|
||||
|
||||
bool matches(String expectedKey, {bool shift = false}) {
|
||||
return key.toLowerCase() == expectedKey.toLowerCase() &&
|
||||
this.shift == shift;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [key, code, shift];
|
||||
}
|
||||
@@ -60,7 +60,7 @@ class HtmlInteraction {
|
||||
''';
|
||||
|
||||
static const String scriptsHandleContentSizeChanged = '''
|
||||
<script>
|
||||
<script type="text/javascript">
|
||||
const bodyResizeObserver = new ResizeObserver(entries => {
|
||||
window.flutter_inappwebview.callHandler('$contentSizeChangedEventJSChannelName', '');
|
||||
})
|
||||
@@ -70,7 +70,7 @@ class HtmlInteraction {
|
||||
''';
|
||||
|
||||
static const String scriptsHandleLazyLoadingBackgroundImage = '''
|
||||
<script>
|
||||
<script type="text/javascript">
|
||||
const lazyImages = document.querySelectorAll('[lazy]');
|
||||
const lazyImageObserver = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
@@ -378,4 +378,19 @@ class HtmlInteraction {
|
||||
</script>
|
||||
|
||||
''';
|
||||
|
||||
static String scriptHandleIframeKeyboardListener(String viewId) => '''
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('keydown', function (event) {
|
||||
const payload = {
|
||||
view: '$viewId',
|
||||
type: 'toDart: iframeKeydown',
|
||||
key: event.key,
|
||||
code: event.code,
|
||||
shift: event.shiftKey
|
||||
};
|
||||
window.parent.postMessage(JSON.stringify(payload), "*");
|
||||
});
|
||||
</script>
|
||||
''';
|
||||
}
|
||||
Reference in New Issue
Block a user