diff --git a/assets/editor/index.html b/assets/editor/index.html deleted file mode 100644 index 96ce0ae..0000000 --- a/assets/editor/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - Spoon-Knife - - - - - - - - -

- Fork me? Fork you, @octocat! -

-

- Sean made a change -

- - - \ No newline at end of file diff --git a/lib/rich_editor.dart b/lib/rich_editor.dart index 8e9b42b..9478106 100644 --- a/lib/rich_editor.dart +++ b/lib/rich_editor.dart @@ -1,3 +1,5 @@ library rich_editor; -export 'package:rich_editor/src/rendering/rich_editor.dart'; \ No newline at end of file +export 'src/rendering/rich_editor.dart'; +export 'src/widgets/tabs.dart'; +export 'src/widgets/tab_button.dart'; \ No newline at end of file diff --git a/lib/src/widgets/font_size_dialog.dart b/lib/src/widgets/font_size_dialog.dart new file mode 100644 index 0000000..b575dbc --- /dev/null +++ b/lib/src/widgets/font_size_dialog.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; + +class FontSizeDialog extends StatelessWidget { + List formats = [ + {'id': '1', 'title': 'Teeny'}, + {'id': '2', 'title': 'Very small'}, + {'id': '3', 'title': 'Small'}, + {'id': '4', 'title': 'Medium'}, + {'id': '5', 'title': 'Large'}, + {'id': '6', 'title': 'Very large'}, + {'id': '7', 'title': 'Huge'}, + ]; + + @override + Widget build(BuildContext context) { + return AlertDialog( + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + for (Map format in formats) + InkWell( + child: Html(data: format['title']), + onTap: () => Navigator.pop(context, format['id']), + ) + ], + ), + ), + ); + } +} diff --git a/lib/src/widgets/fonts_dialog.dart b/lib/src/widgets/fonts_dialog.dart index db6ab4f..74b65e2 100644 --- a/lib/src/widgets/fonts_dialog.dart +++ b/lib/src/widgets/fonts_dialog.dart @@ -15,16 +15,20 @@ class FontsDialog extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - for (Map font in fonts) - InkWell( - child: Html(data: font['title']), - onTap: () => Navigator.pop(context, font['id']), - ) - ], + return AlertDialog( + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + for (Map font in fonts) + InkWell( + child: Html(data: font['title']), + onTap: () => Navigator.pop(context, font['id']), + ) + ], + ), + ), ); } } diff --git a/lib/src/widgets/heading_dialog.dart b/lib/src/widgets/heading_dialog.dart index e63eaaa..8a7c6ce 100644 --- a/lib/src/widgets/heading_dialog.dart +++ b/lib/src/widgets/heading_dialog.dart @@ -19,16 +19,20 @@ class HeadingDialog extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - for (Map format in formats) - InkWell( - child: Html(data: format['title']), - onTap: () => Navigator.pop(context, format['id']), - ) - ], + return AlertDialog( + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + for (Map format in formats) + InkWell( + child: Html(data: format['title']), + onTap: () => Navigator.pop(context, format['id']), + ) + ], + ), + ), ); } } diff --git a/lib/src/widgets/tab_button.dart b/lib/src/widgets/tab_button.dart index 098130a..b5827a6 100644 --- a/lib/src/widgets/tab_button.dart +++ b/lib/src/widgets/tab_button.dart @@ -3,33 +3,37 @@ import 'package:flutter/material.dart'; class TabButton extends StatelessWidget { final IconData? icon; final Function? onTap; + final String tooltip; - TabButton({this.icon, this.onTap}); + TabButton({this.icon, this.onTap, this.tooltip = ''}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 5.0), - child: Container( - height: 45.0, - width: 45.0, - decoration: BoxDecoration( - // color: Color(0xff212121), - borderRadius: BorderRadius.all( - Radius.circular(5.0), + child: Tooltip( + message: '$tooltip', + child: Container( + height: 45.0, + width: 45.0, + decoration: BoxDecoration( + // color: Color(0xff212121), + borderRadius: BorderRadius.all( + Radius.circular(5.0), + ), ), - ), - child: Material( - type: MaterialType.transparency, - child: InkWell( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - onTap: () => onTap!(), - child: Center( - child: Padding( - padding: const EdgeInsets.all(5.0), - child: Icon( - icon, - // color: Theme.of(context).accentColor, + child: Material( + type: MaterialType.transparency, + child: InkWell( + borderRadius: BorderRadius.all(Radius.circular(5.0)), + onTap: () => onTap!(), + child: Center( + child: Padding( + padding: const EdgeInsets.all(5.0), + child: Icon( + icon, + // color: Theme.of(context).accentColor, + ), ), ), ), diff --git a/lib/src/widgets/tabs.dart b/lib/src/widgets/tabs.dart index 760cb11..f0ab7f1 100644 --- a/lib/src/widgets/tabs.dart +++ b/lib/src/widgets/tabs.dart @@ -8,6 +8,7 @@ import 'package:rich_editor/src/widgets/tab_button.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'color_picker_dialog.dart'; +import 'font_size_dialog.dart'; import 'heading_dialog.dart'; class GroupedTab extends StatelessWidget { @@ -34,20 +35,24 @@ class GroupedTab extends StatelessWidget { scrollDirection: Axis.horizontal, children: [ TabButton( + tooltip: 'Bold', icon: Icons.format_bold, onTap: () async { await javascriptExecutorBase.setBold(); }, ), TabButton( + tooltip: 'Italic', icon: Icons.format_italic, onTap: () async { await javascriptExecutorBase.setItalic(); }, ), TabButton( + tooltip: 'Insert Link', icon: Icons.link, onTap: () async { + _closeKeyboard(); var link = await showDialog( context: context, barrierDismissible: false, @@ -60,8 +65,10 @@ class GroupedTab extends StatelessWidget { }, ), TabButton( + tooltip: 'Insert Image', icon: Icons.image, onTap: () async { + _closeKeyboard(); var link = await showDialog( context: context, barrierDismissible: false, @@ -78,59 +85,68 @@ class GroupedTab extends StatelessWidget { }, ), TabButton( + tooltip: 'Underline', icon: Icons.format_underline, onTap: () async { await javascriptExecutorBase.setUnderline(); }, ), TabButton( + tooltip: 'Strike through', icon: Icons.format_strikethrough, onTap: () async { await javascriptExecutorBase.setStrikeThrough(); }, ), TabButton( + tooltip: 'Superscript', icon: Icons.superscript, onTap: () async { await javascriptExecutorBase.setSuperscript(); }, ), TabButton( + tooltip: 'Subscript', icon: Icons.subscript, onTap: () async { await javascriptExecutorBase.setSubscript(); }, ), TabButton( + tooltip: 'Clear format', icon: Icons.format_clear, onTap: () async { await javascriptExecutorBase.removeFormat(); }, ), - TabButton( + tooltip: 'Undo', icon: Icons.undo, onTap: () async { await javascriptExecutorBase.undo(); }, ), TabButton( + tooltip: 'Redo', icon: Icons.redo, onTap: () async { await javascriptExecutorBase.redo(); }, ), TabButton( + tooltip: 'Blockquote', icon: Icons.format_quote, onTap: () async { await javascriptExecutorBase.setBlockQuote(); }, ), TabButton( + tooltip: 'Font format', icon: Icons.text_format, onTap: () async { - var command = await showModalBottomSheet( - isScrollControlled: true, + _closeKeyboard(); + var command = await showDialog( + // isScrollControlled: true, context: context, builder: (_) { return HeadingDialog(); @@ -151,10 +167,12 @@ class GroupedTab extends StatelessWidget { }, ), TabButton( + tooltip: 'Font face', icon: Icons.font_download, onTap: () async { - var command = await showModalBottomSheet( - isScrollControlled: true, + _closeKeyboard(); + var command = await showDialog( + // isScrollControlled: true, context: context, builder: (_) { return FontsDialog(); @@ -166,13 +184,25 @@ class GroupedTab extends StatelessWidget { ), TabButton( icon: Icons.format_size, + tooltip: 'Font Size', onTap: () async { - await javascriptExecutorBase.setFontSize(7); + _closeKeyboard(); + String? command = await showDialog( + // isScrollControlled: true, + context: context, + builder: (_) { + return FontSizeDialog(); + }, + ); + if (command != null) + await javascriptExecutorBase.setFontSize(int.tryParse(command)!); }, ), TabButton( + tooltip: 'Text Color', icon: Icons.format_color_text, onTap: () async { + _closeKeyboard(); var color = await showDialog( context: context, builder: (BuildContext context) { @@ -184,8 +214,10 @@ class GroupedTab extends StatelessWidget { }, ), TabButton( + tooltip: 'Background Color', icon: Icons.format_color_fill, onTap: () async { + _closeKeyboard(); var color = await showDialog( context: context, builder: (BuildContext context) { @@ -198,56 +230,66 @@ class GroupedTab extends StatelessWidget { }, ), TabButton( + tooltip: 'Increase Indent', icon: Icons.format_indent_increase, onTap: () async { await javascriptExecutorBase.setIndent(); }, ), TabButton( + tooltip: 'Decrease Indent', icon: Icons.format_indent_decrease, onTap: () async { await javascriptExecutorBase.setOutdent(); }, ), TabButton( + tooltip: 'Align Left', icon: Icons.format_align_left_outlined, onTap: () async { await javascriptExecutorBase.setJustifyLeft(); }, ), TabButton( + tooltip: 'Align Center', icon: Icons.format_align_center, onTap: () async { await javascriptExecutorBase.setJustifyCenter(); }, ), TabButton( + tooltip: 'Align Right', icon: Icons.format_align_right, onTap: () async { await javascriptExecutorBase.setJustifyRight(); }, ), TabButton( + tooltip: 'Justify', icon: Icons.format_align_justify, onTap: () async { await javascriptExecutorBase.setJustifyFull(); }, ), TabButton( + tooltip: 'Bullet List', icon: Icons.format_list_bulleted, onTap: () async { await javascriptExecutorBase.insertBulletList(); }, ), TabButton( + tooltip: 'Numbered List', icon: Icons.format_list_numbered, onTap: () async { await javascriptExecutorBase.insertNumberedList(); }, ), TabButton( + tooltip: 'Checkbox', icon: Icons.check_box_outlined, onTap: () async { + _closeKeyboard(); var text = await showDialog( context: context, builder: (BuildContext context) { @@ -255,11 +297,12 @@ class GroupedTab extends StatelessWidget { }, ); print(text); - if(text != null) + if (text != null) await javascriptExecutorBase.insertCheckbox(text); }, ), TabButton( + tooltip: 'Search', icon: Icons.search, onTap: () async { // await javascriptExecutorBase.insertNumberedList(); @@ -272,4 +315,10 @@ class GroupedTab extends StatelessWidget { ), ); } + + // Hide the keyboard using JavaScript since it's being opened in a WebView + // https://stackoverflow.com/a/8263376/10835183 + _closeKeyboard() async { + // controller!.evaluateJavascript('document.activeElement.blur();'); + } }