feat: added insert image and more text commands
This commit is contained in:
31
lib/src/widgets/custom_dialog_template.dart
Normal file
31
lib/src/widgets/custom_dialog_template.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomDialogTemplate extends StatelessWidget {
|
||||
final List<Widget>? body;
|
||||
final Function? onDone;
|
||||
final Function? onCancel;
|
||||
|
||||
|
||||
CustomDialogTemplate({this.body, this.onDone, this.onCancel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: body!,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => onDone!(),
|
||||
child: Text('Done'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => onCancel!(),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
62
lib/src/widgets/insert_image_dialog.dart
Normal file
62
lib/src/widgets/insert_image_dialog.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
import 'custom_dialog_template.dart';
|
||||
|
||||
class InsertImageDialog extends StatefulWidget {
|
||||
@override
|
||||
_InsertImageDialogState createState() => _InsertImageDialogState();
|
||||
}
|
||||
|
||||
class _InsertImageDialogState extends State<InsertImageDialog> {
|
||||
TextEditingController link = TextEditingController();
|
||||
|
||||
TextEditingController alt = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomDialogTemplate(
|
||||
body: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Image link'),
|
||||
ElevatedButton(
|
||||
onPressed: () => getImage(),
|
||||
child: Text('...'),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextField(
|
||||
controller: link,
|
||||
decoration: InputDecoration(
|
||||
hintText: '',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.0),
|
||||
Text('Alt text (optional)'),
|
||||
TextField(
|
||||
controller: alt,
|
||||
decoration: InputDecoration(
|
||||
hintText: '',
|
||||
),
|
||||
),
|
||||
],
|
||||
onDone: () => Navigator.pop(context, [link.text, alt.text]),
|
||||
onCancel: () => Navigator.pop(context),
|
||||
);
|
||||
}
|
||||
|
||||
Future getImage() async {
|
||||
final picker = ImagePicker();
|
||||
var image = await picker.getImage(
|
||||
source: ImageSource.gallery,
|
||||
maxWidth: 800.0,
|
||||
maxHeight: 600.0,
|
||||
);
|
||||
|
||||
if (image != null) {
|
||||
link.text = image.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,33 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'custom_dialog_template.dart';
|
||||
|
||||
class InsertLinkDialog extends StatelessWidget {
|
||||
TextEditingController link = TextEditingController();
|
||||
TextEditingController label = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Insert Link'),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('Link'),
|
||||
TextField(
|
||||
controller: link,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'type link here',
|
||||
),
|
||||
return CustomDialogTemplate(
|
||||
body: [
|
||||
Text('Link'),
|
||||
TextField(
|
||||
controller: link,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'type link here',
|
||||
),
|
||||
SizedBox(height: 20.0),
|
||||
Text('Label'),
|
||||
TextField(
|
||||
controller: label,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'type label text here',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, [link.text, label.text]),
|
||||
child: Text('Done'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
SizedBox(height: 20.0),
|
||||
Text('Label'),
|
||||
TextField(
|
||||
controller: label,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'type label text here',
|
||||
),
|
||||
),
|
||||
],
|
||||
onDone: () => Navigator.pop(context, [link.text, label.text]),
|
||||
onCancel: () => Navigator.pop(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rich_editor/src/utils/javascript_executor_base.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';
|
||||
@@ -49,16 +50,75 @@ class GroupedTab extends StatelessWidget {
|
||||
return InsertLinkDialog();
|
||||
},
|
||||
);
|
||||
if(link != null)
|
||||
if (link != null)
|
||||
await javascriptExecutorBase.insertLink(link[0], link[1]);
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.image,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.insertImage(
|
||||
'https://avatars.githubusercontent.com/u/24323581?v=4'
|
||||
var link = await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (_) {
|
||||
return InsertImageDialog();
|
||||
},
|
||||
);
|
||||
if (link != null) {
|
||||
await javascriptExecutorBase.insertImage(
|
||||
link[0],
|
||||
alt: link[1],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_underline,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setUnderline();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_strikethrough,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setStrikeThrough();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.superscript,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setSuperscript();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.subscript,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.setSubscript();
|
||||
},
|
||||
),
|
||||
TabButton(
|
||||
icon: Icons.format_clear,
|
||||
onTap: () async {
|
||||
await javascriptExecutorBase.removeFormat();
|
||||
},
|
||||
),
|
||||
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();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user