From 7b809401ec79eb982c1684d3a6b95a574d77db80 Mon Sep 17 00:00:00 2001 From: jideguru Date: Sun, 6 Jun 2021 21:09:09 +0100 Subject: [PATCH] feat: added 'Add Video' feature --- assets/editor/rich_text_editor.js | 19 ++++++++++ example/lib/basic.dart | 5 +++ lib/src/rendering/rich_editor.dart | 21 ++++++----- lib/src/utils/javascript_executor_base.dart | 17 +++++++++ lib/src/widgets/editor_tool_bar.dart | 21 +++++++++-- lib/src/widgets/insert_image_dialog.dart | 42 +++++++++++++++------ 6 files changed, 100 insertions(+), 25 deletions(-) diff --git a/assets/editor/rich_text_editor.js b/assets/editor/rich_text_editor.js index 451721e..50f7d4c 100644 --- a/assets/editor/rich_text_editor.js +++ b/assets/editor/rich_text_editor.js @@ -474,6 +474,25 @@ var editor = { } }, + insertVideo: function(url, width, height, fromDevice) { + console.log(url); + if (fromDevice) { + this._insertVideo(url, width, height); + } else { + this._insertYoutubeVideo(url, width, height); + } + }, + + _insertYoutubeVideo: function(url, width, height) { + var html = ''; + this._insertHtml(html); + }, + + _insertVideo: function(url, width, height) { + var html = '' + this._insertHtml(html); + }, + insertCheckbox: function(text) { var editor = this; diff --git a/example/lib/basic.dart b/example/lib/basic.dart index d522606..b821535 100644 --- a/example/lib/basic.dart +++ b/example/lib/basic.dart @@ -88,6 +88,11 @@ class BasicDemo extends StatelessWidget { String base64String = 'data:image/png;base64, $base64'; return base64String; }, + getVideoUrl: (video) { + String link = 'https://file-examples-com.github.io/uploads/2017/' + '04/file_example_MP4_480_1_5MG.mp4'; + return link; + }, ), ); } diff --git a/lib/src/rendering/rich_editor.dart b/lib/src/rendering/rich_editor.dart index b66cd7b..66a0861 100644 --- a/lib/src/rendering/rich_editor.dart +++ b/lib/src/rendering/rich_editor.dart @@ -88,11 +88,7 @@ class RichEditorState extends State { children: [ Visibility( visible: widget.editorOptions!.barPosition == BarPosition.TOP, - child: EditorToolBar( - getImageUrl: widget.getImageUrl, - javascriptExecutor: javascriptExecutor, - enableVideo: widget.editorOptions!.enableVideo, - ), + child: _buildToolBar(), ), Expanded( child: InAppWebView( @@ -135,16 +131,21 @@ class RichEditorState extends State { ), Visibility( visible: widget.editorOptions!.barPosition == BarPosition.BOTTOM, - child: EditorToolBar( - getImageUrl: widget.getImageUrl, - javascriptExecutor: javascriptExecutor, - enableVideo: widget.editorOptions!.enableVideo, - ), + child: _buildToolBar(), ), ], ); } + _buildToolBar() { + return EditorToolBar( + getImageUrl: widget.getImageUrl, + getVideoUrl: widget.getVideoUrl, + javascriptExecutor: javascriptExecutor, + enableVideo: widget.editorOptions!.enableVideo, + ); + } + _setInitialValues() async { if (widget.value != null) await javascriptExecutor.setHtml(widget.value!); if (widget.editorOptions!.padding != null) diff --git a/lib/src/utils/javascript_executor_base.dart b/lib/src/utils/javascript_executor_base.dart index 8868850..da03694 100644 --- a/lib/src/utils/javascript_executor_base.dart +++ b/lib/src/utils/javascript_executor_base.dart @@ -198,6 +198,23 @@ class JavascriptExecutorBase { ); } + insertVideo(String url, + {int? width, int? height, bool fromDevice = true}) async { + bool? local; + local = fromDevice ? true : null; + if (width == null) width = 300; + if (height == null) height = 220; + // check if link is yt link + if (url.contains('youtu')) { + // Get Video id from link. + String youtubeId = url.split(r'?v=')[1]; + url = 'https://www.youtube.com/embed/$youtubeId'; + } + await executeJavascript( + "insertVideo('$url', '$width', '$height', $local);", + ); + } + insertCheckbox(String text) async { await executeJavascript("insertCheckbox('$text');"); } diff --git a/lib/src/widgets/editor_tool_bar.dart b/lib/src/widgets/editor_tool_bar.dart index 3d4d2f0..99cbf9b 100644 --- a/lib/src/widgets/editor_tool_bar.dart +++ b/lib/src/widgets/editor_tool_bar.dart @@ -71,7 +71,6 @@ class EditorToolBar extends StatelessWidget { onTap: () async { var link = await showDialog( context: context, - barrierDismissible: false, builder: (_) { return InsertImageDialog(); }, @@ -88,11 +87,27 @@ class EditorToolBar extends StatelessWidget { }, ), Visibility( - visible: false, + visible: enableVideo!, child: TabButton( tooltip: 'Insert video', icon: Icons.video_call_sharp, - onTap: () async {}, + onTap: () async { + var link = await showDialog( + context: context, + builder: (_) { + return InsertImageDialog(isVideo: true); + }, + ); + if(link != null) { + if (getVideoUrl != null && link[2]) { + link[0] = await getVideoUrl!(File(link[0])); + } + await javascriptExecutor.insertVideo( + link[0], + fromDevice: link[2], + ); + } + }, ), ), TabButton( diff --git a/lib/src/widgets/insert_image_dialog.dart b/lib/src/widgets/insert_image_dialog.dart index bfc01bc..2a6f139 100644 --- a/lib/src/widgets/insert_image_dialog.dart +++ b/lib/src/widgets/insert_image_dialog.dart @@ -4,6 +4,10 @@ import 'package:image_picker/image_picker.dart'; import 'custom_dialog_template.dart'; class InsertImageDialog extends StatefulWidget { + final bool isVideo; + + InsertImageDialog({this.isVideo = false}); + @override _InsertImageDialogState createState() => _InsertImageDialogState(); } @@ -21,7 +25,7 @@ class _InsertImageDialogState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('Image link'), + Text(widget.isVideo ? 'Video link' : 'Image link'), ElevatedButton( onPressed: () => getImage(), child: Text('...'), @@ -34,12 +38,21 @@ class _InsertImageDialogState extends State { hintText: '', ), ), - SizedBox(height: 20.0), - Text('Alt text (optional)'), - TextField( - controller: alt, - decoration: InputDecoration( - hintText: '', + Visibility( + visible: !widget.isVideo, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 20.0), + Text('Alt text (optional)'), + TextField( + controller: alt, + decoration: InputDecoration( + hintText: '', + ), + ), + ], ), ), ], @@ -50,11 +63,16 @@ class _InsertImageDialogState extends State { Future getImage() async { final picker = ImagePicker(); - var image = await picker.getImage( - source: ImageSource.gallery, - maxWidth: 800.0, - maxHeight: 600.0, - ); + var image; + if (widget.isVideo) { + image = await picker.getVideo(source: ImageSource.gallery); + } else { + image = await picker.getImage( + source: ImageSource.gallery, + maxWidth: 800.0, + maxHeight: 600.0, + ); + } if (image != null) { link.text = image.path;