import 'dart:convert' show jsonEncode; import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart' show FlutterQuillEmbeds, QuillSharedExtensionsConfigurations; import 'package:quill_html_converter/quill_html_converter.dart'; import 'package:share_plus/share_plus.dart' show Share; import '../extensions/scaffold_messenger.dart'; import '../shared/widgets/home_screen_button.dart'; import 'my_quill_editor.dart'; import 'my_quill_toolbar.dart'; @immutable class QuillScreenArgs { const QuillScreenArgs({required this.document}); final Document document; } class QuillScreen extends StatefulWidget { const QuillScreen({ required this.args, super.key, }); final QuillScreenArgs args; static const routeName = '/quill'; @override State createState() => _QuillScreenState(); } class _QuillScreenState extends State { final _controller = QuillController.basic(); final _editorFocusNode = FocusNode(); final _editorScrollController = ScrollController(); var _isReadOnly = false; @override void initState() { super.initState(); _controller.document = widget.args.document; } // Future _init() async { // final reader = await ClipboardReader.readClipboard(); // if (reader.canProvide(Formats.htmlText)) { // final html = await reader.readValue(Formats.htmlText); // if (html == null) { // return; // } // final delta = DeltaHtmlExt.fromHtml(html); // _controller.document = Document.fromDelta(delta); // } // } @override void dispose() { _controller.dispose(); _editorFocusNode.dispose(); _editorScrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter Quill'), actions: [ IconButton( tooltip: 'Load with HTML', onPressed: () { final html = _controller.document.toDelta().toHtml(); _controller.document = Document.fromDelta(QuillController.fromHtml(html)); }, icon: const Icon(Icons.html), ), IconButton( tooltip: 'Share', onPressed: () { final plainText = _controller.document.toPlainText( FlutterQuillEmbeds.defaultEditorBuilders(), ); if (plainText.trim().isEmpty) { ScaffoldMessenger.of(context).showText( "We can't share empty document, please enter some text first", ); return; } Share.share(plainText); }, icon: const Icon(Icons.share), ), IconButton( tooltip: 'Print to log', onPressed: () { print( jsonEncode(_controller.document.toDelta().toJson()), ); ScaffoldMessenger.of(context).showText( 'The quill delta json has been printed to the log.', ); }, icon: const Icon(Icons.print), ), const HomeScreenButton(), ], ), body: Column( children: [ if (!_isReadOnly) MyQuillToolbar( controller: _controller, focusNode: _editorFocusNode, ), Builder( builder: (context) { return Expanded( child: MyQuillEditor( configurations: QuillEditorConfigurations( sharedConfigurations: _sharedConfigurations, controller: _controller, readOnly: _isReadOnly, customStyles: const DefaultStyles(), elementOptions: const QuillEditorElementOptions( codeBlock: QuillEditorCodeBlockElementOptions( enableLineNumbers: true, ), // orderedList: QuillEditorOrderedListElementOptions( // backgroundColor: Colors.amber, // fontColor: Colors.black, // ), // unorderedList: QuillEditorUnOrderedListElementOptions( // backgroundColor: Colors.green, // fontColor: Colors.red, // ), ), ), scrollController: _editorScrollController, focusNode: _editorFocusNode, ), ); }, ), ], ), floatingActionButton: FloatingActionButton( child: Icon(_isReadOnly ? Icons.lock : Icons.edit), onPressed: () => setState(() => _isReadOnly = !_isReadOnly), ), ); } QuillSharedConfigurations get _sharedConfigurations { return const QuillSharedConfigurations( // locale: Locale('en'), extraConfigurations: { QuillSharedExtensionsConfigurations.key: QuillSharedExtensionsConfigurations( assetsPrefix: 'assets', // Defaults to assets ), }, ); } }