html_editor_enhanced 1.8.0 copy "html_editor_enhanced: ^1.8.0" to clipboard
html_editor_enhanced: ^1.8.0 copied to clipboard

outdated

HTML rich text editor for Android, iOS, and Web, using the Summernote library. Enhanced with critical bug fixes and support for callbacks, plugins, dark mode, and much more.

example/lib/main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced/html_editor.dart';

void main() => runApp(HtmlEditorExampleApp());

class HtmlEditorExampleApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      darkTheme: ThemeData.dark(),
      home: HtmlEditorExample(title: 'Flutter HTML Editor Example'),
    );
  }
}

class HtmlEditorExample extends StatefulWidget {
  HtmlEditorExample({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _HtmlEditorExampleState createState() => _HtmlEditorExampleState();
}

class _HtmlEditorExampleState extends State<HtmlEditorExample> {
  String result = "";
  final HtmlEditorController controller = HtmlEditorController();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        if (!kIsWeb) {
          controller.clearFocus();
        }
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          elevation: 0,
          actions: [
            IconButton(
                icon: Icon(Icons.refresh),
                onPressed: () {
                  if (kIsWeb) {
                    controller.reloadWeb();
                  } else {
                    controller.editorController!.reload();
                  }
                })
          ],
        ),
        floatingActionButton: FloatingActionButton(
          child: Text(r"<\>",
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
          onPressed: () {
            controller.toggleCodeView();
          },
        ),
        body: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              HtmlEditor(
                controller: controller,
                hint: "Your text here...",
                //initialText: "<p>text content initial, if any</p>",
                options:
                    HtmlEditorOptions(height: 450, shouldEnsureVisible: true),
                callbacks: Callbacks(onBeforeCommand: (String? currentHtml) {
                  print("html before change is $currentHtml");
                }, onChange: (String? changed) {
                  print("content changed to $changed");
                }, onChangeCodeview: (String? changed) {
                  print("code changed to $changed");
                }, onDialogShown: () {
                  print("dialog shown");
                }, onEnter: () {
                  print("enter/return pressed");
                }, onFocus: () {
                  print("editor focused");
                }, onBlur: () {
                  print("editor unfocused");
                }, onBlurCodeview: () {
                  print("codeview either focused or unfocused");
                }, onInit: () {
                  print("init");
                },
                    //this is commented because it overrides the default Summernote handlers
                    /*onImageLinkInsert: (String? url) {
                    print(url ?? "unknown url");
                  },
                  onImageUpload: (FileUpload file) async {
                    print(file.name);
                    print(file.size);
                    print(file.type);
                    print(file.base64);
                  },*/
                    onImageUploadError: (FileUpload? file, String? base64Str,
                        UploadError error) {
                  print(describeEnum(error));
                  print(base64Str ?? "");
                  if (file != null) {
                    print(file.name);
                    print(file.size);
                    print(file.type);
                  }
                }, onKeyDown: (int? keyCode) {
                  print("$keyCode key downed");
                }, onKeyUp: (int? keyCode) {
                  print("$keyCode key released");
                }, onMouseDown: () {
                  print("mouse downed");
                }, onMouseUp: () {
                  print("mouse released");
                }, onPaste: () {
                  print("pasted into editor");
                }, onScroll: () {
                  print("editor scrolled");
                }),
                plugins: [
                  SummernoteEmoji(),
                  AdditionalTextTags(),
                  SummernoteCaseConverter(),
                  SummernoteListStyles(),
                  SummernoteRTL(),
                  SummernoteAtMention(
                      getSuggestionsMobile: (String value) {
                        List<String> mentions = ['test1', 'test2', 'test3'];
                        return mentions
                            .where((element) => element.contains(value))
                            .toList();
                      },
                      mentionsWeb: ['test1', 'test2', 'test3'],
                      onSelect: (String value) {
                        print(value);
                      }),
                  SummernoteCodewrapper(),
                  SummernoteFile(
                      //this is commented because it overrides the default SummernoteFile handlers
                      /*onFileUpload: (FileUpload file) {
                      print(file.name);
                      print(file.size);
                      print(file.type);
                      print(file.base64);
                    },*/
                      onFileLinkInsert: (String link) {
                    print(link);
                  }, onFileUploadError: (FileUpload? file, String? base64Str,
                          UploadError error) {
                    print(describeEnum(error));
                    print(base64Str ?? "");
                    if (file != null) {
                      print(file.name);
                      print(file.size);
                      print(file.type);
                    }
                  }),
                ],
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.undo();
                      },
                      child:
                          Text("Undo", style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.clear();
                      },
                      child:
                          Text("Reset", style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () async {
                        String? txt = await controller.getText();
                        if (txt != null) {
                          if (txt.contains("src=\"data:")) {
                            txt =
                                "<text removed due to base-64 data, displaying the text could cause the app to crash>";
                          }
                          setState(() {
                            result = txt!;
                          });
                        }
                      },
                      child: Text(
                        "Submit",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () {
                        controller.redo();
                      },
                      child: Text(
                        "Redo",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(result),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.disable();
                      },
                      child: Text("Disable",
                          style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () async {
                        controller.enable();
                      },
                      child: Text(
                        "Enable",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(height: 16),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () {
                        controller.insertText("Google");
                      },
                      child: Text("Insert Text",
                          style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () {
                        controller.insertHtml(
                            """<p style="color: blue">Google in blue</p>""");
                      },
                      child: Text("Insert HTML",
                          style: TextStyle(color: Colors.white)),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () async {
                        controller.insertLink(
                            "Google linked", "https://google.com", true);
                      },
                      child: Text(
                        "Insert Link",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () {
                        controller.insertNetworkImage(
                            "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png",
                            filename: "Google network image");
                      },
                      child: Text(
                        "Insert network image",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(height: 16),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.addNotification(
                            "Info notification", NotificationType.info);
                      },
                      child:
                          Text("Info", style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.addNotification(
                            "Warning notification", NotificationType.warning);
                      },
                      child: Text("Warning",
                          style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () async {
                        controller.addNotification(
                            "Success notification", NotificationType.success);
                      },
                      child: Text(
                        "Success",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () {
                        controller.addNotification(
                            "Danger notification", NotificationType.danger);
                      },
                      child: Text(
                        "Danger",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(height: 16),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.addNotification("Plaintext notification",
                            NotificationType.plaintext);
                      },
                      child: Text("Plaintext",
                          style: TextStyle(color: Colors.white)),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Theme.of(context).accentColor),
                      onPressed: () async {
                        controller.removeNotification();
                      },
                      child: Text(
                        "Remove",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
566
likes
80
pub points
98%
popularity

Publisher

unverified uploader

HTML rich text editor for Android, iOS, and Web, using the Summernote library. Enhanced with critical bug fixes and support for callbacks, plugins, dark mode, and much more.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

flutter, flutter_inappwebview, flutter_keyboard_visibility, js, visibility_detector

More

Packages that depend on html_editor_enhanced