feat: added more text commands
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension ColorX on Color {
|
||||
String toHexColorString() => '#${value.toString().replaceAll('ColorSwatch(',
|
||||
'').replaceAll('Color(0xff', '').replaceAll('MaterialColor(', '')
|
||||
.replaceAll('MaterialAccentColor(', '').replaceAll('primary value: '
|
||||
'Color(0xff', '').replaceAll('primary', '').replaceAll('value:', '')
|
||||
.replaceAll(')', '').trim()}';
|
||||
String toHexColorString() => '#${value.toRadixString(16).replaceAll('ff', '')}';
|
||||
}
|
||||
22
lib/src/widgets/check_dialog.dart
Normal file
22
lib/src/widgets/check_dialog.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'custom_dialog_template.dart';
|
||||
|
||||
class CheckDialog extends StatelessWidget {
|
||||
TextEditingController text = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomDialogTemplate(
|
||||
body: [
|
||||
Text('Checkbox title'),
|
||||
TextField(
|
||||
controller: text,
|
||||
decoration: InputDecoration(hintText: ''),
|
||||
),
|
||||
],
|
||||
onDone: () => Navigator.pop(context, text.text),
|
||||
onCancel: () => Navigator.pop(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
54
lib/src/widgets/color_picker_dialog.dart
Normal file
54
lib/src/widgets/color_picker_dialog.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
||||
|
||||
class ColorPickerDialog extends StatefulWidget {
|
||||
final Color? color;
|
||||
|
||||
ColorPickerDialog({this.color});
|
||||
|
||||
@override
|
||||
_ColorPickerDialogState createState() => _ColorPickerDialogState();
|
||||
}
|
||||
|
||||
class _ColorPickerDialogState extends State<ColorPickerDialog> {
|
||||
Color? color;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
color = widget.color;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
titlePadding: const EdgeInsets.all(0.0),
|
||||
contentPadding: const EdgeInsets.all(0.0),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: color!,
|
||||
onColorChanged: (pickedColor) {
|
||||
color = pickedColor;
|
||||
setState(() {});
|
||||
},
|
||||
colorPickerWidth: 300.0,
|
||||
pickerAreaHeightPercent: 0.7,
|
||||
enableAlpha: true,
|
||||
displayThumbColor: true,
|
||||
showLabel: true,
|
||||
paletteType: PaletteType.hsv,
|
||||
pickerAreaBorderRadius: const BorderRadius.only(
|
||||
topLeft: const Radius.circular(2.0),
|
||||
topRight: const Radius.circular(2.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, color),
|
||||
child: Text('Done'),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
30
lib/src/widgets/fonts_dialog.dart
Normal file
30
lib/src/widgets/fonts_dialog.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
|
||||
class FontsDialog extends StatelessWidget {
|
||||
List fonts = [
|
||||
{
|
||||
'id': 'cursive',
|
||||
'title': '<p style="font-family:cursive">This is a paragraph.</p>'
|
||||
},
|
||||
{
|
||||
'id': 'monospace',
|
||||
'title': '<p style="font-family:monospace">This is a paragraph.</p>'
|
||||
}
|
||||
];
|
||||
|
||||
@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']),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
34
lib/src/widgets/heading_dialog.dart
Normal file
34
lib/src/widgets/heading_dialog.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
|
||||
class HeadingDialog extends StatelessWidget {
|
||||
List formats = [
|
||||
{'id': '1', 'title': '<h1>Heading 1</h1>'},
|
||||
{'id': '2', 'title': '<h2>Heading 2</h2>'},
|
||||
{'id': '3', 'title': '<h3>Heading 3</h3>'},
|
||||
{'id': '4', 'title': '<h4>Heading 4</h4>'},
|
||||
{'id': '5', 'title': '<h5>Heading 5</h5>'},
|
||||
{'id': '6', 'title': '<h6>Heading 6</h6>'},
|
||||
{'id': 'p', 'title': '<p>Text body</p>'},
|
||||
{
|
||||
'id': 'pre',
|
||||
'title': '<pre><font face=\"courier\">Preformat</font></pre>'
|
||||
},
|
||||
{'id': 'blockquote', 'title': '<blockquote>Quote</blockquote>'},
|
||||
];
|
||||
|
||||
@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']),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rich_editor/src/utils/javascript_executor_base.dart';
|
||||
import 'package:rich_editor/src/widgets/check_dialog.dart';
|
||||
import 'package:rich_editor/src/widgets/fonts_dialog.dart';
|
||||
import 'package:rich_editor/src/widgets/insert_image_dialog.dart';
|
||||
import 'package:rich_editor/src/widgets/insert_link_dialog.dart';
|
||||
import 'package:rich_editor/src/widgets/tab_button.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import 'color_picker_dialog.dart';
|
||||
import 'heading_dialog.dart';
|
||||
|
||||
class GroupedTab extends StatelessWidget {
|
||||
final WebViewController? controller;
|
||||
|
||||
@@ -102,25 +107,164 @@ class GroupedTab extends StatelessWidget {
|
||||
await javascriptExecutorBase.removeFormat();
|
||||
},
|
||||
),
|
||||
|
||||
TabButton(
|
||||
icon: Icons.undo,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.undo();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.redo,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.redo();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.undo,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.undo();
|
||||
},
|
||||
),
|
||||
|
||||
TabButton(
|
||||
icon: Icons.format_quote,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setBlockQuote();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.text_format,
|
||||
onTap: () async {
|
||||
var command = await showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return HeadingDialog();
|
||||
},
|
||||
);
|
||||
if (command != null) {
|
||||
if (command == 'p') {
|
||||
await javascriptExecutorBase.setFormattingToParagraph();
|
||||
} else if (command == 'pre') {
|
||||
await javascriptExecutorBase.setPreformat();
|
||||
} else if (command == 'blockquote') {
|
||||
await javascriptExecutorBase.setBlockQuote();
|
||||
} else {
|
||||
await javascriptExecutorBase
|
||||
.setHeading(int.tryParse(command)!);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.font_download,
|
||||
onTap: () async {
|
||||
var command = await showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return FontsDialog();
|
||||
},
|
||||
);
|
||||
if (command != null)
|
||||
await javascriptExecutorBase.setFontName(command);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_size,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setFontSize(7);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_color_text,
|
||||
onTap: () async {
|
||||
var color = await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ColorPickerDialog(color: Colors.blue);
|
||||
},
|
||||
);
|
||||
if (color != null)
|
||||
await javascriptExecutorBase.setTextColor(color);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_color_fill,
|
||||
onTap: () async {
|
||||
var color = await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ColorPickerDialog(color: Colors.blue);
|
||||
},
|
||||
);
|
||||
if (color != null)
|
||||
await javascriptExecutorBase
|
||||
.setTextBackgroundColor(color);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_indent_increase,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setIndent();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_indent_decrease,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setOutdent();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_align_left_outlined,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setJustifyLeft();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_align_center,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setJustifyCenter();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_align_right,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setJustifyRight();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_align_justify,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setJustifyFull();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_list_bulleted,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.insertBulletList();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_list_numbered,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.insertNumberedList();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.check_box_outlined,
|
||||
onTap: () async {
|
||||
var text = await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CheckDialog();
|
||||
},
|
||||
);
|
||||
print(text);
|
||||
if(text != null)
|
||||
await javascriptExecutorBase.insertCheckbox(text);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.search,
|
||||
onTap: () async {
|
||||
// await javascriptExecutorBase.insertNumberedList();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user