Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix initialization logic for web #219

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:name="${applicationName}"
android:label="html_editor_enhanced_example"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
Expand Down
9 changes: 8 additions & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
meta:
dependency: transitive
description:
Expand Down Expand Up @@ -244,7 +251,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.3"
version: "0.4.8"
typed_data:
dependency: transitive
description:
Expand Down
1 change: 0 additions & 1 deletion lib/src/html_editor_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class HtmlEditor extends StatelessWidget {
htmlEditorOptions: htmlEditorOptions,
htmlToolbarOptions: htmlToolbarOptions,
otherOptions: otherOptions,
initBC: context,
);
} else {
return Text(
Expand Down
8 changes: 5 additions & 3 deletions lib/src/widgets/html_editor_widget_mobile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class _HtmlEditorWidgetMobileState extends State<HtmlEditorWidget> {

@override
void initState() {
super.initState();
docHeight = widget.otherOptions.height;
key = getRandString(10);
if (widget.htmlEditorOptions.filePath != null) {
Expand All @@ -76,7 +77,6 @@ class _HtmlEditorWidgetMobileState extends State<HtmlEditorWidget> {
} else {
filePath = 'packages/html_editor_enhanced/assets/summernote.html';
}
super.initState();
}

@override
Expand Down Expand Up @@ -150,7 +150,8 @@ class _HtmlEditorWidgetMobileState extends State<HtmlEditorWidget> {
useShouldOverrideUrlLoading: true,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: widget.htmlEditorOptions.androidUseHybridComposition,
useHybridComposition: widget
.htmlEditorOptions.androidUseHybridComposition,
loadWithOverviewMode: true,
)),
initialUserScripts:
Expand Down Expand Up @@ -506,7 +507,8 @@ class _HtmlEditorWidgetMobileState extends State<HtmlEditorWidget> {
keyCode.first as int;
});
//disable editor if necessary
if (widget.htmlEditorOptions.disabled && !callbacksInitialized) {
if (widget.htmlEditorOptions.disabled &&
!callbacksInitialized) {
widget.controller.disable();
}
//initialize callbacks
Expand Down
66 changes: 34 additions & 32 deletions lib/src/widgets/html_editor_widget_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:html_editor_enhanced/utils/utils.dart';
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
import 'package:html_editor_enhanced/utils/shims/dart_ui.dart' as ui;
import 'package:async/async.dart';

/// The HTML Editor widget itself, for web (uses IFrameElement)
class HtmlEditorWidget extends StatefulWidget {
Expand All @@ -21,7 +22,6 @@ class HtmlEditorWidget extends StatefulWidget {
required this.htmlEditorOptions,
required this.htmlToolbarOptions,
required this.otherOptions,
required this.initBC,
}) : super(key: key);

final HtmlEditorController controller;
Expand All @@ -30,7 +30,6 @@ class HtmlEditorWidget extends StatefulWidget {
final HtmlEditorOptions htmlEditorOptions;
final HtmlToolbarOptions htmlToolbarOptions;
final OtherOptions otherOptions;
final BuildContext initBC;

@override
_HtmlEditorWidgetWebState createState() => _HtmlEditorWidgetWebState();
Expand All @@ -41,17 +40,14 @@ class HtmlEditorWidget extends StatefulWidget {
/// A stateful widget is necessary here, otherwise the IFrameElement will be
/// rebuilt excessively, hurting performance
class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
final memoizer = AsyncMemoizer();

/// The view ID for the IFrameElement. Must be unique.
late String createdViewId;

/// The actual height of the editor, used to automatically set the height
late double actualHeight;

/// A Future that is observed by the [FutureBuilder]. We don't use a function
/// as the Future on the [FutureBuilder] because when the widget is rebuilt,
/// the function may be excessively called, hurting performance.
Future<bool>? summernoteInit;

/// Helps get the height of the toolbar to accurately adjust the height of
/// the editor when the keyboard is visible.
GlobalKey toolbarKey = GlobalKey();
Expand All @@ -61,14 +57,13 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {

@override
void initState() {
super.initState();
actualHeight = widget.otherOptions.height;
createdViewId = getRandString(10);
widget.controller.viewId = createdViewId;
initSummernote();
super.initState();
}

void initSummernote() async {
Future<void> initSummernote(BuildContext context) async {
var headString = '';
var summernoteCallbacks = '''callbacks: {
onKeydown: function(e) {
Expand Down Expand Up @@ -183,7 +178,7 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
}
summernoteCallbacks = summernoteCallbacks + '}';
var darkCSS = '';
if ((Theme.of(widget.initBC).brightness == Brightness.dark ||
if ((Theme.of(context).brightness == Brightness.dark ||
widget.htmlEditorOptions.darkMode == true) &&
widget.htmlEditorOptions.darkMode != false) {
darkCSS =
Expand Down Expand Up @@ -241,7 +236,10 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
window.parent.postMessage(JSON.stringify({"view": "$createdViewId", "type": "toDart: htmlHeight", "height": height}), "*");
}
if (data["type"].includes("setInputType")) {
document.getElementsByClassName('note-editable')[0].setAttribute('inputmode', '${describeEnum(widget.htmlEditorOptions.inputType)}');
const editable = document.getElementsByClassName('note-editable')[0];
if (editable) {
editable.setAttribute('inputmode', '${describeEnum(widget.htmlEditorOptions.inputType)}');
}
}
if (data["type"].includes("setText")) {
\$('#summernote-2').summernote('code', data["text"]);
Expand Down Expand Up @@ -464,7 +462,7 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
'"assets/packages/html_editor_enhanced/assets/summernote-lite.min.js"');
if (widget.callbacks != null) addJSListener(widget.callbacks!);
final iframe = html.IFrameElement()
..width = MediaQuery.of(widget.initBC).size.width.toString() //'800'
..width = MediaQuery.of(context).size.width.toString() //'800'
..height = widget.htmlEditorOptions.autoAdjustHeight
? actualHeight.toString()
: widget.otherOptions.height.toString()
Expand Down Expand Up @@ -531,11 +529,11 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
});
ui.platformViewRegistry
.registerViewFactory(createdViewId, (int viewId) => iframe);
setState(mounted, this.setState, () {
summernoteInit = Future.value(true);
});
}

/*

*/
@override
Widget build(BuildContext context) {
return Container(
Expand All @@ -553,22 +551,26 @@ class _HtmlEditorWidgetWebState extends State<HtmlEditorWidget> {
callbacks: widget.callbacks)
: Container(height: 0, width: 0),
Expanded(
child: Directionality(
textDirection: TextDirection.ltr,
child: FutureBuilder<bool>(
future: summernoteInit,
builder: (context, snapshot) {
if (snapshot.hasData) {
return HtmlElementView(
viewType: createdViewId,
);
} else {
return Container(
height: widget.htmlEditorOptions.autoAdjustHeight
? actualHeight
: widget.otherOptions.height);
}
}))),
child: Directionality(
textDirection: TextDirection.ltr,
child: FutureBuilder<void>(
future: memoizer.runOnce(() => initSummernote(context)),
builder: (context, state) {
if (state.hasError) return ErrorWidget(state.error!);
if (state.connectionState != ConnectionState.done) {
return Container(
height: widget.htmlEditorOptions.autoAdjustHeight
? actualHeight
: widget.otherOptions.height,
);
}
return HtmlElementView(
viewType: createdViewId,
);
},
),
),
),
widget.htmlToolbarOptions.toolbarPosition ==
ToolbarPosition.belowEditor
? ToolbarWidget(
Expand Down
4 changes: 3 additions & 1 deletion lib/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import 'package:html_editor_enhanced/utils/shims/dart_ui.dart';
void setState(
bool mounted, void Function(Function()) setState, void Function() fn) {
if (mounted) {
setState.call(fn);
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState.call(fn);
});
Comment on lines +15 to +17
Copy link
Owner

Choose a reason for hiding this comment

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

I am having issues with this change when the caret selection position is changed on web. The toolbar will not update the values, e.g. font size will not update when the text selection position is changed. Is there any particular reason why you added the postFrameCallback? I don't recall there being any issues with this setState function.

Copy link
Author

Choose a reason for hiding this comment

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

that's because calling setState during build throws an exception
but now that we moved initialization logic in a future builder i am not sure if this throws or not

but font size not updating is not related to the changes i made, i think

Copy link
Owner

Choose a reason for hiding this comment

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

I didn't see any exceptions when this was removed. Also removing this caused the font size to update correctly, the set state was not firing due to the post frame callback. Do you mind testing on your end and making sure there are no side effects to removing this?

}
}

Expand Down
23 changes: 15 additions & 8 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ packages:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.0"
version: "4.4.0"
flex_color_picker:
dependency: "direct main"
description:
name: flex_color_picker
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
version: "2.3.0"
flutter:
dependency: "direct main"
description: flutter
Expand All @@ -89,7 +89,7 @@ packages:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
version: "5.2.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
Expand All @@ -110,7 +110,7 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.5"
flutter_test:
dependency: "direct dev"
description: flutter
Expand Down Expand Up @@ -142,6 +142,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
meta:
dependency: "direct main"
description:
Expand Down Expand Up @@ -176,14 +183,14 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.2"
pointer_interceptor:
dependency: "direct main"
description:
name: pointer_interceptor
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0+1"
version: "0.9.3"
sky_engine:
dependency: transitive
description: flutter
Expand Down Expand Up @@ -230,7 +237,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.3"
version: "0.4.8"
typed_data:
dependency: transitive
description:
Expand All @@ -254,4 +261,4 @@ packages:
version: "0.2.2"
sdks:
dart: ">=2.14.0 <3.0.0"
flutter: ">=2.2.0"
flutter: ">=2.10.0"