diff --git a/README.md b/README.md
index a35681d..80e45fc 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,6 @@ Based on https://github.com/dankito/RichTextEditor, but for Flutter.
## 📸 Screenshots
-
## Usage
diff --git a/example/lib/basic.dart b/example/lib/basic.dart
index b821535..64e6609 100644
--- a/example/lib/basic.dart
+++ b/example/lib/basic.dart
@@ -60,14 +60,11 @@ class BasicDemo extends StatelessWidget {
),
body: RichEditor(
key: keyEditor,
-// value: '''
-//
Heading 1
-// Heading 2
-// Heading 3
-// Heading 4
-// Heading 5
-// Heading 6
-// ''', // initial HTML data
+ value: '''
+ Hello, This is a rich text Editor for Flutter. It supports most things like Bold, italics and underline.
+ As well as Subscript, Superscript, Colored text, Colors bg text and hyperlink.
+ Images and Videos are also supports
+ ''', // initial HTML data
editorOptions: RichEditorOptions(
placeholder: 'Start typing',
// backgroundColor: Colors.blueGrey, // Editor's bg color
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 063bc6c..09e7406 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -211,7 +211,7 @@ packages:
path: ".."
relative: true
source: path
- version: "0.0.3"
+ version: "0.0.4"
sky_engine:
dependency: transitive
description: flutter
diff --git a/lib/src/utils/javascript_executor_base.dart b/lib/src/utils/javascript_executor_base.dart
index e0a6cd7..61b3112 100644
--- a/lib/src/utils/javascript_executor_base.dart
+++ b/lib/src/utils/javascript_executor_base.dart
@@ -1,12 +1,10 @@
-import 'dart:convert';
-
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:rich_editor/src/extensions/extensions.dart';
import 'package:rich_editor/src/models/callbacks/did_html_change_listener.dart';
import 'package:rich_editor/src/models/callbacks/html_changed_listener.dart';
import 'package:rich_editor/src/models/callbacks/loaded_listener.dart';
-import 'package:rich_editor/src/models/editor_state.dart';
import 'package:rich_editor/src/models/enum/command_name.dart';
import '../models/command_state.dart';
@@ -43,10 +41,13 @@ class JavascriptExecutorBase {
List loadedListeners = [];
+ /// Initialise the controller so we don't have to
+ /// pass a controller into every Method
init(InAppWebViewController? controller) {
_controller = controller;
}
+ /// Run Javascript commands in the editor using the webview controller
executeJavascript(String command) async {
return await _controller!.evaluateJavascript(source: 'editor.$command');
}
@@ -55,14 +56,16 @@ class JavascriptExecutorBase {
return htmlField!;
}
+ /// Display HTML data in editor
setHtml(String html) async {
String? baseUrl;
await executeJavascript("setHtml('" + encodeHtml(html) + "', '$baseUrl');");
htmlField = html;
}
+ /// Get current HTML data from Editor
getCurrentHtml() async {
- String? html = await executeJavascript('getEncodedHtml()');
+ String? html = await executeJavascript('getEncodedHtml();');
String? decodedHtml = decodeHtml(html!);
if (decodedHtml!.startsWith('"') && decodedHtml.endsWith('"')) {
decodedHtml = decodedHtml.substring(1, decodedHtml.length - 1);
@@ -70,57 +73,72 @@ class JavascriptExecutorBase {
return decodedHtml;
}
+ /// Check if editor's content has been modified
bool isDefaultRichTextEditorHtml(String html) {
return defaultHtml == html;
}
// Text commands
+
+ /// Undo last editor command/action
undo() async {
await executeJavascript("undo();");
}
+ /// Redo last editor command/action
redo() async {
await executeJavascript("redo();");
}
+ /// Make selected or subsequent text Bold
setBold() async {
await executeJavascript("setBold();");
}
+ /// Make selected or subsequent text Italic
setItalic() async {
await executeJavascript("setItalic();");
}
+ /// Make selected or subsequent text Underlined
setUnderline() async {
await executeJavascript("setUnderline();");
}
+ /// Make selected or subsequent text Subscript
setSubscript() async {
await executeJavascript("setSubscript();");
}
+ /// Make selected or subsequent text Superscript
setSuperscript() async {
await executeJavascript("setSuperscript();");
}
+ /// Strike through selected text
setStrikeThrough() async {
await executeJavascript("setStrikeThrough();");
}
+ /// Set a [Color] for the selected text
setTextColor(Color? color) async {
String? hex = color!.toHexColorString();
await executeJavascript("setTextColor('$hex');");
}
+ /// Set a [Color] for the selected text's background
setTextBackgroundColor(Color? color) async {
String? hex = color!.toHexColorString();
await executeJavascript("setTextBackgroundColor('$hex');");
}
+ /// Apply a font face to selected text
setFontName(String fontName) async {
await executeJavascript("setFontName('$fontName');");
}
+ /// Apply a font size to selected text
+ /// (Value can only be between 1 and 7)
setFontSize(int fontSize) async {
if (fontSize < 1 || fontSize > 7) {
throw ("Font size should have a value between 1-7");
@@ -128,6 +146,8 @@ class JavascriptExecutorBase {
await executeJavascript("setFontSize('$fontSize');");
}
+ /// Apply a Heading style to selected text
+ /// (Value can only be between 1 and 6)
setHeading(int heading) async {
await executeJavascript("setHeading('$heading');");
}
@@ -140,47 +160,58 @@ class JavascriptExecutorBase {
await executeJavascript("setPreformat();");
}
+ /// Create BlockQuote / make selected text a BlockQuote
setBlockQuote() async {
await executeJavascript("setBlockQuote();");
}
+ /// Remove formatting from selected text
removeFormat() async {
await executeJavascript("removeFormat();");
}
+ /// Align content left
setJustifyLeft() async {
await executeJavascript("setJustifyLeft();");
}
+ /// Align content center
setJustifyCenter() async {
await executeJavascript("setJustifyCenter();");
}
+ /// Align content right
setJustifyRight() async {
await executeJavascript("setJustifyRight();");
}
+ /// Justify content
setJustifyFull() async {
await executeJavascript("setJustifyFull();");
}
+ /// Add indentation
setIndent() async {
await executeJavascript("setIndent();");
}
+ /// Remove indentation
setOutdent() async {
await executeJavascript("setOutdent();");
}
+ /// Start an unordered list
insertBulletList() async {
await executeJavascript("insertBulletList();");
}
+ /// Start a ordered list
insertNumberedList() async {
await executeJavascript("insertNumberedList();");
}
// Insert element
+ /// Insert hyper link / make selected text an hyperlink
insertLink(String url, String title) async {
await executeJavascript("insertLink('$url', '$title');");
}
@@ -217,50 +248,63 @@ class JavascriptExecutorBase {
);
}
+ /// Add a checkbox to the current editor
insertCheckbox(String text) async {
await executeJavascript("insertCheckbox('$text');");
}
+ /// Insert HTML code into the editor
+ /// (It wont display the HTML code but it'll render it)
insertHtml(String html) async {
String? encodedHtml = encodeHtml(html);
await executeJavascript("insertHtml('$encodedHtml');");
}
+ /// Enable Images resizing
makeImagesResizeable() async {
await executeJavascript("makeImagesResizeable();");
}
+ /// Disable Images resizing
disableImageResizing() async {
await executeJavascript("disableImageResizing();");
}
// Editor settings commands
+ /// Focus on editor and bring up keyboard
focus() async {
await executeJavascript("focus();");
+ SystemChannels.textInput.invokeMethod('TextInput.show');
}
+ /// Remove focus from the editor and close the keyboard
unFocus() async {
await executeJavascript("blurFocus();");
}
+ /// Set a [Color] for the editor's background
setBackgroundColor(Color? color) async {
String? hex = color!.toHexColorString();
await executeJavascript("setBackgroundColor('$hex');");
}
+ /// Set an image for the editor's background
setBackgroundImage(String image) async {
await executeJavascript("setBackgroundImage('$image');");
}
+ /// Set a default editor text color
setBaseTextColor(Color? color) async {
String? hex = color!.toHexColorString();
await executeJavascript("setBaseTextColor('$hex');");
}
+ /// Set a default editor text font family
setBaseFontFamily(String fontFamily) async {
await executeJavascript("setBaseFontFamily('$fontFamily');");
}
+ /// Add padding to the editor's content
setPadding(EdgeInsets? padding) async {
String left = padding!.left.toString();
String top = padding.top.toString();
@@ -270,19 +314,23 @@ class JavascriptExecutorBase {
"setPadding('${left}px', '${top}px', '${right}px', '${bottom}px');");
}
- // Doesnt actually work for' now
+ /// Set a hint when the editor is empty
+ /// Doesn't actually work for now
setPlaceholder(String placeholder) async {
await executeJavascript("setPlaceholder('$placeholder');");
}
+ /// Set editor's width in pixels
setEditorWidth(int px) async {
await executeJavascript("setWidth('" + px.toString() + "px');");
}
+ /// Set editor's height in pixels
setEditorHeight(int px) async {
await executeJavascript("setHeight('" + px.toString() + "px');");
}
+ /// Enable text input on editor
setInputEnabled(bool inputEnabled) async {
await executeJavascript("setInputEnabled($inputEnabled);");
}
@@ -295,143 +343,143 @@ class JavascriptExecutorBase {
return Uri.encodeFull(html);
}
- bool shouldOverrideUrlLoading(String url) {
- String decodedUrl;
- try {
- decodedUrl = decodeHtml(url);
- } catch (e) {
- // No handling
- return false;
- }
-
- if (url.indexOf(editorStateChangedCallbackScheme) == 0) {
- editorStateChanged(
- decodedUrl.substring(editorStateChangedCallbackScheme.length));
- return true;
- }
-
- return false;
- }
-
- editorStateChanged(String statesString) {
- try {
- var editorState = EditorState.fromJson(jsonDecode(statesString));
-
- bool currentHtmlChanged = this.htmlField != editorState.html;
- this.htmlField = editorState.html;
-
- retrievedEditorState(
- editorState.didHtmlChange!, editorState.commandStates!);
-
- if (currentHtmlChanged) {
- // fireHtmlChangedListenersAsync(editorState.html);
- }
- } catch (e) {
- throw ("Could not parse command states: $statesString $e");
- }
- }
-
- retrievedEditorState(
- bool didHtmlChange, Map commandStates) {
- if (this.didHtmlChange != didHtmlChange) {
- this.didHtmlChange = didHtmlChange;
- didHtmlChangeListeners.forEach((element) {
- element.didHtmlChange(didHtmlChange);
- });
- }
-
- handleRetrievedCommandStates(commandStates);
- }
-
- handleRetrievedCommandStates(Map commandStates) {
- determineDerivedCommandStates(commandStates);
-
- this.commandStates = commandStates;
- commandStatesChangedListeners.forEach((element) {
- element = this.commandStates;
- });
- }
-
- determineDerivedCommandStates(Map commandStates) {
- if (commandStates[CommandName.FORMATBLOCK] != null) {
- var formatCommandState = commandStates[CommandName.FORMATBLOCK];
- commandStates.update(
- CommandName.H1,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h1")),
- );
- commandStates.update(
- CommandName.H2,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h2")));
- commandStates.update(
- CommandName.H3,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h3")),
- );
- commandStates.update(
- CommandName.H4,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h4")),
- );
- commandStates.update(
- CommandName.H5,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h5")),
- );
- commandStates.update(
- CommandName.H6,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "h6")),
- );
- commandStates.update(
- CommandName.P,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "p")),
- );
- commandStates.update(
- CommandName.PRE,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "pre")),
- );
- commandStates.update(
- CommandName.BR,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "")),
- );
- commandStates.update(
- CommandName.BLOCKQUOTE,
- (val) => CommandState(formatCommandState!.executable,
- isFormatActivated(formatCommandState, "blockquote")),
- );
- }
-
- if (commandStates[CommandName.INSERTHTML] != null) {
- CommandState? insertHtmlState = commandStates[CommandName.INSERTHTML];
- commandStates.update(CommandName.INSERTLINK, (val) => insertHtmlState!);
- commandStates.update(CommandName.INSERTIMAGE, (val) => insertHtmlState!);
- commandStates.update(
- CommandName.INSERTCHECKBOX, (val) => insertHtmlState!);
- }
- }
-
- String isFormatActivated(CommandState formatCommandState, String format) {
- return (formatCommandState.value == format)
- .toString(); // rich_text_editor.js reports boolean values as string, so we also have to convert it to string
- }
-
- addCommandStatesChangedListener(
- Map commandStates) {
- commandStatesChangedListeners.add(commandStates);
-
- // listener.invoke(commandStates);
- }
-
- addDidHtmlChangeListener(DidHtmlChangeListener listener) {
- didHtmlChangeListeners.add(listener);
- }
-
- addHtmlChangedListener(HtmlChangedListener listener) {
- htmlChangedListeners.add(listener);
- }
+// bool shouldOverrideUrlLoading(String url) {
+// String decodedUrl;
+// try {
+// decodedUrl = decodeHtml(url);
+// } catch (e) {
+// // No handling
+// return false;
+// }
+//
+// if (url.indexOf(editorStateChangedCallbackScheme) == 0) {
+// editorStateChanged(
+// decodedUrl.substring(editorStateChangedCallbackScheme.length));
+// return true;
+// }
+//
+// return false;
+// }
+//
+// editorStateChanged(String statesString) {
+// try {
+// var editorState = EditorState.fromJson(jsonDecode(statesString));
+//
+// bool currentHtmlChanged = this.htmlField != editorState.html;
+// this.htmlField = editorState.html;
+//
+// retrievedEditorState(
+// editorState.didHtmlChange!, editorState.commandStates!);
+//
+// if (currentHtmlChanged) {
+// // fireHtmlChangedListenersAsync(editorState.html);
+// }
+// } catch (e) {
+// throw ("Could not parse command states: $statesString $e");
+// }
+// }
+//
+// retrievedEditorState(
+// bool didHtmlChange, Map commandStates) {
+// if (this.didHtmlChange != didHtmlChange) {
+// this.didHtmlChange = didHtmlChange;
+// didHtmlChangeListeners.forEach((element) {
+// element.didHtmlChange(didHtmlChange);
+// });
+// }
+//
+// handleRetrievedCommandStates(commandStates);
+// }
+//
+// handleRetrievedCommandStates(Map commandStates) {
+// determineDerivedCommandStates(commandStates);
+//
+// this.commandStates = commandStates;
+// commandStatesChangedListeners.forEach((element) {
+// element = this.commandStates;
+// });
+// }
+//
+// determineDerivedCommandStates(Map commandStates) {
+// if (commandStates[CommandName.FORMATBLOCK] != null) {
+// var formatCommandState = commandStates[CommandName.FORMATBLOCK];
+// commandStates.update(
+// CommandName.H1,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h1")),
+// );
+// commandStates.update(
+// CommandName.H2,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h2")));
+// commandStates.update(
+// CommandName.H3,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h3")),
+// );
+// commandStates.update(
+// CommandName.H4,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h4")),
+// );
+// commandStates.update(
+// CommandName.H5,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h5")),
+// );
+// commandStates.update(
+// CommandName.H6,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "h6")),
+// );
+// commandStates.update(
+// CommandName.P,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "p")),
+// );
+// commandStates.update(
+// CommandName.PRE,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "pre")),
+// );
+// commandStates.update(
+// CommandName.BR,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "")),
+// );
+// commandStates.update(
+// CommandName.BLOCKQUOTE,
+// (val) => CommandState(formatCommandState!.executable,
+// isFormatActivated(formatCommandState, "blockquote")),
+// );
+// }
+//
+// if (commandStates[CommandName.INSERTHTML] != null) {
+// CommandState? insertHtmlState = commandStates[CommandName.INSERTHTML];
+// commandStates.update(CommandName.INSERTLINK, (val) => insertHtmlState!);
+// commandStates.update(CommandName.INSERTIMAGE, (val) => insertHtmlState!);
+// commandStates.update(
+// CommandName.INSERTCHECKBOX, (val) => insertHtmlState!);
+// }
+// }
+//
+// String isFormatActivated(CommandState formatCommandState, String format) {
+// return (formatCommandState.value == format)
+// .toString(); // rich_text_editor.js reports boolean values as string, so we also have to convert it to string
+// }
+//
+// addCommandStatesChangedListener(
+// Map commandStates) {
+// commandStatesChangedListeners.add(commandStates);
+//
+// // listener.invoke(commandStates);
+// }
+//
+// addDidHtmlChangeListener(DidHtmlChangeListener listener) {
+// didHtmlChangeListeners.add(listener);
+// }
+//
+// addHtmlChangedListener(HtmlChangedListener listener) {
+// htmlChangedListeners.add(listener);
+// }
}
diff --git a/pubspec.yaml b/pubspec.yaml
index b6f30d1..c904e27 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: rich_editor
description: WYSIWYG editor for Flutter with a rich set of supported formatting options.
-version: 0.0.3
+version: 0.0.4
homepage: https://github.com/JideGuru/rich_editor
environment:
diff --git a/res/1.png b/res/1.png
index a1a4f4c..4d7b220 100644
Binary files a/res/1.png and b/res/1.png differ
diff --git a/res/2.png b/res/2.png
deleted file mode 100644
index a72873d..0000000
Binary files a/res/2.png and /dev/null differ