feat: added font size dialog and icon tooltip
This commit is contained in:
parent
25c6c39e1b
commit
758a107ed3
@ -1,23 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
||||||
<title>Spoon-Knife</title>
|
|
||||||
<LINK href="styles.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<img src="forkit.gif" id="octocat" alt="" />
|
|
||||||
|
|
||||||
<!-- Feel free to change this text here -->
|
|
||||||
<p>
|
|
||||||
Fork me? Fork you, @octocat!
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Sean made a change
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,3 +1,5 @@
|
|||||||
library rich_editor;
|
library rich_editor;
|
||||||
|
|
||||||
export 'package:rich_editor/src/rendering/rich_editor.dart';
|
export 'src/rendering/rich_editor.dart';
|
||||||
|
export 'src/widgets/tabs.dart';
|
||||||
|
export 'src/widgets/tab_button.dart';
|
33
lib/src/widgets/font_size_dialog.dart
Normal file
33
lib/src/widgets/font_size_dialog.dart
Normal file
@ -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': '<small><small><small>Teeny</small></small></small>'},
|
||||||
|
{'id': '2', 'title': '<small><small>Very small</small></small>'},
|
||||||
|
{'id': '3', 'title': '<small>Small</small>'},
|
||||||
|
{'id': '4', 'title': 'Medium'},
|
||||||
|
{'id': '5', 'title': '<big>Large</big>'},
|
||||||
|
{'id': '6', 'title': '<big><big>Very large</big></big>'},
|
||||||
|
{'id': '7', 'title': '<big><big><big>Huge</big></big></big>'},
|
||||||
|
];
|
||||||
|
|
||||||
|
@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']),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,9 @@ class FontsDialog extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return AlertDialog(
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -25,6 +27,8 @@ class FontsDialog extends StatelessWidget {
|
|||||||
onTap: () => Navigator.pop(context, font['id']),
|
onTap: () => Navigator.pop(context, font['id']),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ class HeadingDialog extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return AlertDialog(
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -29,6 +31,8 @@ class HeadingDialog extends StatelessWidget {
|
|||||||
onTap: () => Navigator.pop(context, format['id']),
|
onTap: () => Navigator.pop(context, format['id']),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,16 @@ import 'package:flutter/material.dart';
|
|||||||
class TabButton extends StatelessWidget {
|
class TabButton extends StatelessWidget {
|
||||||
final IconData? icon;
|
final IconData? icon;
|
||||||
final Function? onTap;
|
final Function? onTap;
|
||||||
|
final String tooltip;
|
||||||
|
|
||||||
TabButton({this.icon, this.onTap});
|
TabButton({this.icon, this.onTap, this.tooltip = ''});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 5.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 5.0),
|
||||||
|
child: Tooltip(
|
||||||
|
message: '$tooltip',
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 45.0,
|
height: 45.0,
|
||||||
width: 45.0,
|
width: 45.0,
|
||||||
@ -36,6 +39,7 @@ class TabButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import 'package:rich_editor/src/widgets/tab_button.dart';
|
|||||||
import 'package:webview_flutter/webview_flutter.dart';
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
|
|
||||||
import 'color_picker_dialog.dart';
|
import 'color_picker_dialog.dart';
|
||||||
|
import 'font_size_dialog.dart';
|
||||||
import 'heading_dialog.dart';
|
import 'heading_dialog.dart';
|
||||||
|
|
||||||
class GroupedTab extends StatelessWidget {
|
class GroupedTab extends StatelessWidget {
|
||||||
@ -34,20 +35,24 @@ class GroupedTab extends StatelessWidget {
|
|||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Bold',
|
||||||
icon: Icons.format_bold,
|
icon: Icons.format_bold,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setBold();
|
await javascriptExecutorBase.setBold();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Italic',
|
||||||
icon: Icons.format_italic,
|
icon: Icons.format_italic,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setItalic();
|
await javascriptExecutorBase.setItalic();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Insert Link',
|
||||||
icon: Icons.link,
|
icon: Icons.link,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_closeKeyboard();
|
||||||
var link = await showDialog(
|
var link = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
@ -60,8 +65,10 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Insert Image',
|
||||||
icon: Icons.image,
|
icon: Icons.image,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_closeKeyboard();
|
||||||
var link = await showDialog(
|
var link = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
@ -78,59 +85,68 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Underline',
|
||||||
icon: Icons.format_underline,
|
icon: Icons.format_underline,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setUnderline();
|
await javascriptExecutorBase.setUnderline();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Strike through',
|
||||||
icon: Icons.format_strikethrough,
|
icon: Icons.format_strikethrough,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setStrikeThrough();
|
await javascriptExecutorBase.setStrikeThrough();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Superscript',
|
||||||
icon: Icons.superscript,
|
icon: Icons.superscript,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setSuperscript();
|
await javascriptExecutorBase.setSuperscript();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Subscript',
|
||||||
icon: Icons.subscript,
|
icon: Icons.subscript,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setSubscript();
|
await javascriptExecutorBase.setSubscript();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Clear format',
|
||||||
icon: Icons.format_clear,
|
icon: Icons.format_clear,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.removeFormat();
|
await javascriptExecutorBase.removeFormat();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Undo',
|
||||||
icon: Icons.undo,
|
icon: Icons.undo,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.undo();
|
await javascriptExecutorBase.undo();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Redo',
|
||||||
icon: Icons.redo,
|
icon: Icons.redo,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.redo();
|
await javascriptExecutorBase.redo();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Blockquote',
|
||||||
icon: Icons.format_quote,
|
icon: Icons.format_quote,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setBlockQuote();
|
await javascriptExecutorBase.setBlockQuote();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Font format',
|
||||||
icon: Icons.text_format,
|
icon: Icons.text_format,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
var command = await showModalBottomSheet(
|
_closeKeyboard();
|
||||||
isScrollControlled: true,
|
var command = await showDialog(
|
||||||
|
// isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
return HeadingDialog();
|
return HeadingDialog();
|
||||||
@ -151,10 +167,12 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Font face',
|
||||||
icon: Icons.font_download,
|
icon: Icons.font_download,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
var command = await showModalBottomSheet(
|
_closeKeyboard();
|
||||||
isScrollControlled: true,
|
var command = await showDialog(
|
||||||
|
// isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
return FontsDialog();
|
return FontsDialog();
|
||||||
@ -166,13 +184,25 @@ class GroupedTab extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
icon: Icons.format_size,
|
icon: Icons.format_size,
|
||||||
|
tooltip: 'Font Size',
|
||||||
onTap: () async {
|
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(
|
TabButton(
|
||||||
|
tooltip: 'Text Color',
|
||||||
icon: Icons.format_color_text,
|
icon: Icons.format_color_text,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_closeKeyboard();
|
||||||
var color = await showDialog(
|
var color = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
@ -184,8 +214,10 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Background Color',
|
||||||
icon: Icons.format_color_fill,
|
icon: Icons.format_color_fill,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_closeKeyboard();
|
||||||
var color = await showDialog(
|
var color = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
@ -198,56 +230,66 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Increase Indent',
|
||||||
icon: Icons.format_indent_increase,
|
icon: Icons.format_indent_increase,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setIndent();
|
await javascriptExecutorBase.setIndent();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Decrease Indent',
|
||||||
icon: Icons.format_indent_decrease,
|
icon: Icons.format_indent_decrease,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setOutdent();
|
await javascriptExecutorBase.setOutdent();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Align Left',
|
||||||
icon: Icons.format_align_left_outlined,
|
icon: Icons.format_align_left_outlined,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setJustifyLeft();
|
await javascriptExecutorBase.setJustifyLeft();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Align Center',
|
||||||
icon: Icons.format_align_center,
|
icon: Icons.format_align_center,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setJustifyCenter();
|
await javascriptExecutorBase.setJustifyCenter();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Align Right',
|
||||||
icon: Icons.format_align_right,
|
icon: Icons.format_align_right,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setJustifyRight();
|
await javascriptExecutorBase.setJustifyRight();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Justify',
|
||||||
icon: Icons.format_align_justify,
|
icon: Icons.format_align_justify,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.setJustifyFull();
|
await javascriptExecutorBase.setJustifyFull();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Bullet List',
|
||||||
icon: Icons.format_list_bulleted,
|
icon: Icons.format_list_bulleted,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.insertBulletList();
|
await javascriptExecutorBase.insertBulletList();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Numbered List',
|
||||||
icon: Icons.format_list_numbered,
|
icon: Icons.format_list_numbered,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await javascriptExecutorBase.insertNumberedList();
|
await javascriptExecutorBase.insertNumberedList();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Checkbox',
|
||||||
icon: Icons.check_box_outlined,
|
icon: Icons.check_box_outlined,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
_closeKeyboard();
|
||||||
var text = await showDialog(
|
var text = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
@ -260,6 +302,7 @@ class GroupedTab extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TabButton(
|
TabButton(
|
||||||
|
tooltip: 'Search',
|
||||||
icon: Icons.search,
|
icon: Icons.search,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// await javascriptExecutorBase.insertNumberedList();
|
// 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();');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user