diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20c70d58..32fa25fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+## [1.2.0] - 2021-02-20
+* Add support for accessing `InAppWebViewController` via a getter
+* Add support for inserting files via the editor dialog itself
+* Add methods:
+ * toggle code view
+ * enable/disable editor
+ * undo/redo
+ * inserting plaintext/HTML/images/links
+* Add callbacks:
+ * onChange
+ * onEnter
+ * onFocus/onBlur/onBlurCodeview
+ * onKeyUp/onKeyDown
+ * onPaste
+* Downgraded dependencies to non-nullsafety to prevent errors
+* Updated docs and example app to showcase new features, refer to those for info on the above changes
+
## [1.1.1] - 2021-02-19
* Minor update to add documentation to code and completely refactor/reorganize code
diff --git a/README.md b/README.md
index d67d4c14..2310b884 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,62 @@
# Flutter Html Editor - Enhanced
+[![pub package](https://img.shields.io/pub/v/html_editor_enhanced.svg)](https://pub.dev/packages/html_editor_enhanced)
-Flutter HTML Editor is a text editor for Android and iOS to help write WYSIWYG HTML code with on the Summernote JavaScript wrapper.
+Flutter HTML Editor Enhanced is a text editor for Android and iOS to help write WYSIWYG HTML code with on the Summernote JavaScript wrapper.
-![demo example](https://github.com/xrb21/flutter-html-editor/blob/master/screenshoot/flutter_html_editor.gif) ![demo android](https://github.com/xrb21/flutter-html-editor/blob/master/screenshoot/sc.jpeg) ![demo ios](https://github.com/xrb21/flutter-html-editor/blob/master/screenshoot/sc_iphone.png)
+
+
+
Video Example
+
+
+
+
+
+
+## Table of Contents:
+
+- ["Enhanced"? In what ways?](#in-what-ways-is-this-package-enhanced)
+
+- [Setup](#setup)
+
+- [Usage](#basic-usage)
+
+- [API Reference](#api-reference)
+
+ - [Parameters Table](#parameters)
+
+ - [Methods Table](#methods)
+
+ - [Callbacks Table](#callbacks)
+
+ - [Getters](#getters)
+
+ - [Examples](#examples)
+
+- [Notes](#notes)
+
+- [License](#license)
+
+- [Contribution Guide](#contribution-guide)
+
+## In what ways is this package "enhanced"?
+
+1. It uses a heavily optimized [WebView](https://github.com/pichillilorenzo/flutter_inappwebview) to deliver the best possible experience when using the editor
+
+2. It doesn't use a local server to load the HTML code containing the editor. Instead, this package simply loads the HTML file, which improves performance and the editor's startup time.
+
+3. It uses a `StatelessWidget`. You don't have to fiddle around with `GlobalKey`s to access methods, instead you can simply call `HtmlEditor.` anywhere you want.
+
+4. It has support for many of Summernote's methods
+
+5. It has support for many of Summernote's callbacks
+
+6. It exposes the `InAppWebViewController` so you can customize the WebView however you like - you can even load your own HTML code and inject your own JavaScript for your use cases.
+
+More is on the way! File a feature request or contribute to the project if you'd like to see other features added.
## Setup
-Add `html_editor_enhanced: ^1.1.1` as dependency to your pubspec.yaml
+Add `html_editor_enhanced: ^1.2.0` as dependency to your pubspec.yaml
Follow the setup instructions for the image_picker plugin
@@ -21,6 +71,7 @@ Add the following keys to your _Info.plist_ file, located in `/ios
### Android
#### API < 29
+
No configuration required - the plugin should work out of the box.
#### API 29+
@@ -29,7 +80,11 @@ Add `android:requestLegacyExternalStorage="true"` as an attribute to the `
-Additional setup is required to allow the user to pick images via ``, add the following to your app's AndroidManifest.xml inside the `` tag:
+Additional setup is required to allow the user to pick images via ``:
+
+Instructions
+
+Add the following to your app's AndroidManifest.xml inside the `` tag:
```xml
+
+```
+
+In Dart, you'll need to request these permissions. You can use [`permission_handler`](https://pub.dev/packages/permission_handler) like this:
+
+```dart
+//Android
+await Permission.storage.request();
+//iOS
+await Permission.photos.request();
+```
+
+If you'd like the user to be able to insert images via the camera, you need to request for those permissions. AndroidManifest:
+
+```xml
+
+```
+
+Dart:
+
+```dart
+await Permission.camera.request();
+```
+
+You must request the permissions in Dart before the user accesses the file upload dialog. I recommend requesting the permissions in `initState()` or something similar.
+
+IMPORTANT: When using `permission_handler` on iOS, you must modify the Podfile, otherwise you will not be able to upload a build to App Store Connect. Add the following at the very bottom, right underneath `flutter_additional_ios_build_settings(target)`:
+
+```text
+target.build_configurations.each do |config|
+ config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
+ '$(inherited)',
+ ## use a hashtag symbol on the permissions you want to include in your app. Make sure they are defined in Info.plist as well!
+ ## dart: PermissionGroup.calendar
+ 'PERMISSION_EVENTS=0',
+
+ ## dart: PermissionGroup.reminders
+ 'PERMISSION_REMINDERS=0',
+
+ ## dart: PermissionGroup.contacts
+ 'PERMISSION_CONTACTS=0',
+
+ ## dart: PermissionGroup.camera
+ 'PERMISSION_CAMERA=0',
+
+ ## dart: PermissionGroup.microphone
+ 'PERMISSION_MICROPHONE=0',
+
+ ## dart: PermissionGroup.speech
+ 'PERMISSION_SPEECH_RECOGNIZER=0',
+
+ ## dart: PermissionGroup.photos
+ # 'PERMISSION_PHOTOS=0',
+
+ ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
+ 'PERMISSION_LOCATION=0',
+
+ ## dart: PermissionGroup.notification
+ 'PERMISSION_NOTIFICATIONS=0',
+
+ ## dart: PermissionGroup.mediaLibrary
+ 'PERMISSION_MEDIA_LIBRARY=0',
+
+ ## dart: PermissionGroup.sensors
+ 'PERMISSION_SENSORS=0'
+ ]
+ end
+```
+
+If you decide to allow images directly from the camera, you will need to comment `'PERMISSION_CAMERA=0',` as well.
+
+
+
+## Basic Usage
```dart
import 'package:html_editor/html_editor.dart';
@@ -62,35 +194,88 @@ When you want to get text from the editor:
final txt = await HtmlEditor.getText();
```
-### In what ways is this package "enhanced"?
+## API Reference
-1. It uses a heavily optimized [WebView](https://github.com/pichillilorenzo/flutter_inappwebview) to deliver the best possible experience when using the editor
+For the full API reference, see [here](https://pub.dev/documentation/html_editor_enhanced/latest/).
-2. It doesn't use a local server to load the HTML code containing the editor. Instead, this package simply loads the HTML file, which improves performance and the editor's startup time.
-
-3. It uses a `StatelessWidget`. You don't have to fiddle around with `GlobalKey`s to access methods, instead you can simply call `HtmlEditor.` anywhere you want.
+For a full example, see [here](https://github.com/tneotia/html-editor-enhanced/tree/master/example).
-4. It has support for many of Summernote's methods
+Below, you will find brief descriptions of the parameters the`HtmlEditor` widget accepts and some code snippets to help you use this package.
-5. It has support for many of Summernote's callbacks
+### Parameters
-6. It exposes the `InAppWebViewController` so you can customize the WebView however you like - you can even load your own HTML code and inject your own JavaScript for your use cases.
+Parameter | Type | Default | Description
+------------ | ------------- | ------------- | -------------
+**initialText** | `String` | empty | Initial text content for text editor
+**height** | `double` | 380 | Height of text editor (does not set the height in HTML yet, only the height of the WebView widget)
+**decoration** | `BoxDecoration` | | `BoxDecoration` that surrounds the widget
+**useBottomSheet** | `bool` | true | If true, open a bottom sheet (Android intent style) to pick an image, otherwise use a dialog
+**imageWidth** | `double` | 100 | Width of image once inserted. Must be between 0 and 100.
+**showBottomToolbar** | `bool` | true | Show or hide bottom toolbar
+**hint** | `String` | empty | Placeholder hint text
+**callbacks** | `Callbacks` | empty | Customize the callbacks for various events
-More is on the way! File a feature request or contribute to the project if you'd like to see other features added.
+### Methods
-### Parameters
+Access these methods like this: `HtmlEditor.`
-Parameter | Type | Default | Description
+Method | Argument(s) | Returned Value(s) | Description
------------ | ------------- | ------------- | -------------
-**value** | String | empty | initial text content for text editor
-**height** | double | 380 | height of text editor
-**decoration** | BoxDecoration | | Decoration editor
-**useBottomSheet** | bool | true | if true, open a bottom sheet (Android intent style) to pick an image, otherwise use a dialog
-**widthImage** | String | 100% | width of image picker
-**showBottomToolbar** | bool | true | show or hide bottom toolbar
-**hint** | String | empty | Placeholder hint text
-**callbacks** | Callbacks | empty | Customize the callbacks for various events
+**getText()** | N/A | `Future` | Returns the current HTML in the editor
+**setText()** | `String` | N/A | Sets the current text in the HTML to the input HTML string
+**setFullScreen()** | N/A | N/A | Sets the editor to take up the entire size of the webview
+**setFocus()** | N/A | N/A | If the pointer is in the webview, the focus will be set to the editor box
+**clear()** | N/A | N/A | Resets the HTML editor to its default state
+**setHint()** | `String` | N/A | Sets the current hint text of the editor
+**toggleCodeview()** | N/A | N/A | Toggles between the code view and the rich text view
+**disable()** | N/A | N/A | Disables the editor (a gray mask is applied and all touches are absorbed)
+**enable()** | N/A | N/A | Enables the editor
+**undo()** | N/A | N/A | Undoes the last command in the editor
+**redo()** | N/A | N/A | Redoes the last command in the editor
+**insertText()** | `String` | N/A | Inserts the provided text into the editor at the current cursor position. Do *not* use this method for HTML strings.
+**insertHtml()** | `String` | N/A | Inserts the provided HTML string into the editor at the current cursor position. Do *not* use this method for plaintext strings.
+**insertNetworkImage()** | `String` url, `String` filename (optional) | N/A | Inserts an image using the provided url and optional filename into the editor at the current cursor position. The image must be accessible via a URL.
+**insertLink()** | `String` text, `String` url, `bool` isNewWindow | N/A | Inserts a hyperlink using the provided text and url into the editor at the current cursor position. `isNewWindow` defines whether a new browser window is launched if the link is tapped.
+
+### Callbacks
+
+Every callback is defined as a `Function()`. See the [documentation](https://pub.dev/documentation/html_editor_enhanced/latest/) for more specific details on each callback.
+
+Callback | Parameter(s) | Description
+------------ | ------------- | -------------
+**onChange** | `String` | Called when the content of the editor changes, passes the current HTML in the editor
+**onEnter** | N/A | Called when enter/return is pressed
+**onFocus** | N/A | Called when the rich text field gains focus
+**onBlur** | N/A | Called when the rich text field or the codeview loses focus
+**onBlurCodeview** | N/A | Called when the codeview either gains or loses focus
+**onKeyDown** | `int` | Called when a key is downed, passes the keycode of the downed key
+**onKeyUp** | `int` | Called when a key is released, passes the keycode of the released key
+**onPaste** | N/A | Called when content is pasted into the editor
+
+### Getters
+
+Currently, the package has one getter: `HtmlEditor.controller`. This returns the `InAppWebViewController`, which manages the webview that displays the editor.
+
+This is extremely powerful, as it allows you to create your own custom methods and implementations directly in your app. See [`flutter_inappwebview`](https://github.com/pichillilorenzo/flutter_inappwebview) for documentation on the controller.
+
+### Examples
+
+See the [example app](https://github.com/tneotia/html-editor-enhanced/blob/master/example/lib/main.dart) to see how the majority of methods & callbacks can be used. You can also play around with the parameters to see how they function.
+
+This section will be updated later with more specialized and specific examples as this library grows and more features are implemented.
+
+## Notes
+
+Due to this package depending on a webview for rendering the HTML editor, there will be some general weirdness in how the editor behaves. Unfortunately, these are not things I can fix, they are inherent problems with how webviews function on Flutter.
+
+If you do find any issues, please report them in the Issues tab and I will see if a fix is possible, but if I close the issue it is likely due to the above fact.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## Contribution Guide
+
+> Coming soon!
+>
+> Meanwhile, PRs are always welcome
\ No newline at end of file
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 78e8f6ec..669a566f 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -7,42 +7,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.5.0-nullsafety.3"
+ version: "2.5.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.5"
+ version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.15.0-nullsafety.5"
+ version: "1.15.0"
convert:
dependency: transitive
description:
@@ -70,7 +70,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
@@ -89,7 +89,7 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0-nullsafety.2"
+ version: "1.0.11"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -108,42 +108,42 @@ packages:
name: http
url: "https://pub.dartlang.org"
source: hosted
- version: "0.13.0-nullsafety.0"
+ version: "0.12.2"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.0-nullsafety"
+ version: "3.1.4"
image_picker:
dependency: transitive
description:
name: image_picker
url: "https://pub.dartlang.org"
source: hosted
- version: "0.7.0-nullsafety"
+ version: "0.6.7+22"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0-nullsafety"
+ version: "1.1.6"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.10-nullsafety.3"
+ version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.6"
+ version: "1.3.0"
mime:
dependency: transitive
description:
@@ -157,7 +157,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.3"
+ version: "1.8.0"
pedantic:
dependency: transitive
description:
@@ -183,49 +183,49 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.4"
+ version: "1.8.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.10.0-nullsafety.6"
+ version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.19-nullsafety.6"
+ version: "0.2.19"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.5"
+ version: "1.3.0"
uuid:
dependency: transitive
description:
@@ -239,7 +239,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.5"
+ version: "2.1.0"
sdks:
dart: ">=2.12.0-0.0 <3.0.0"
flutter: ">=1.20.0"
diff --git a/pubspec.lock b/pubspec.lock
index f29c14de..ffae6d1e 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,6 +1,20 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.5.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0"
characters:
dependency: transitive
description:
@@ -15,6 +29,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
collection:
dependency: transitive
description:
@@ -36,6 +57,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
@@ -54,35 +82,47 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0-nullsafety.2"
+ version: "1.0.11"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
http:
dependency: transitive
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
- version: "0.13.0"
+ version: "0.12.2"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.0"
+ version: "3.1.4"
image_picker:
dependency: "direct main"
description:
name: image_picker
url: "https://pub.dartlang.org"
source: hosted
- version: "0.7.0-nullsafety"
+ version: "0.6.7+22"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0-nullsafety"
+ version: "1.1.6"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.10"
meta:
dependency: transitive
description:
@@ -91,7 +131,7 @@ packages:
source: hosted
version: "1.3.0"
mime:
- dependency: "direct main"
+ dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
@@ -129,7 +169,21 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.1"
+ version: "1.8.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.10.0"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0"
string_scanner:
dependency: transitive
description:
@@ -144,6 +198,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.19"
typed_data:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index d24ebff9..22f02cdd 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: html_editor_enhanced
description: HTML Editor Enhanced is a text editor for Android and iOS to help write WYSIWYG HTML code using Summernote. Initially created by @xrb21, enhanced version maintained by @tneotia.
-version: 1.1.1
+version: 1.2.0
homepage: https://github.com/tneotia/html-editor-enhanced
environment: