Rich text editor for Flutter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

16 KiB

Mirgration guide

Here you can find the mirgration guide between different versions, you can contribute to this page to make it better for everyone!!

from 7.0.0 to 8.0.0

We have refactored a lot of the base code to allow you to customize everything you want, and it allow us to add new configurations very easily using inherited widgets without passing configurations all over the constructors everywhere which will be very hard to test, fix bugs, and maintain

  1. Passing the controller

The controller code (should be the same)

QuillController _controller = QuillController.basic();

Old code:


Column(
  children: [
    QuillToolbar.basic(controller: _controller),
    Expanded(
      child: QuillEditor.basic(
          controller: _controller,
          readOnly: false, // true for view only mode
      ),
    )
  ],
)

New code:

QuillProvider(
  configurations: QuillConfigurations(
    controller: _controller,
    sharedConfigurations: const QuillSharedConfigurations(),
  ),
  child: Column(
    children: [
      const QuillToolbar(),
      Expanded(
        child: QuillEditor.basic(
          configurations: const QuillEditorConfigurations(
            readOnly: false, // true for view only mode
          ),
        ),
      )
    ],
  ),
)

The QuillProvider is inherited widget which allow you pass configurations once and use them in the children of it. here we are passing the _controller once in the configurations of QuillProvider and the QuillToolbar and QuillEditor will get the QuillConfigurations internally, if it doesn't exists you will get an exception.

we also added the sharedConfigurations which allow you to configure shared things like the Local so you don't have to define them twice, we have removed those from the QuillToolbar and QuillEditor

  1. The QuillToolbar buttons, we have renamed almost all the buttons, examples:
    • QuillHistory to QuillToolbarHistoryButton
    • IndentButton to QuillToolbarIndentButton

and they usually have two parameters, controller and options, example of the type for the buttons

  • QuillToolbarHistoryButton have QuillToolbarHistoryButtonOptions
  • QuillToolbarIndentButton have QuillToolbarIndentButtonOptions
  • QuillToolbarClearFormatButton have QuillToolbarClearFormatButtonOptions

All the options have parent QuillToolbarBaseButtonOptions which have commons things like

  /// By default it will use a Icon data from Icons which comes from material
  /// library for each button, to change this, please pass a different value
  /// If there is no Icon in this button then pass null in the child class
  final IconData? iconData;

  /// To change the the icon size pass a different value, by default will be
  /// [kDefaultIconSize]
  /// this will be used for all the buttons but you can override this
  final double globalIconSize;

  /// To do extra logic after pressing the button
  final VoidCallback? afterButtonPressed;

  /// By default it will use the default tooltip which already localized
  final String? tooltip;

  /// Use custom theme
  final QuillIconTheme? iconTheme;

  /// If you want to dispaly a differnet widget based using a builder
  final QuillToolbarButtonOptionsChildBuilder<T, I> childBuilder;

  /// By default it will be from the one in [QuillProvider]
  /// To override it you must pass not null controller
  /// if you wish to use the controller in the [childBuilder], please use the
  /// one from the extraOptions since it will be not null and will be the one
  /// which will be used from the quill toolbar
  final QuillController? controller;

The QuillToolbarBaseButtonOptions is: /// The [T] is the options for the button, usually should refresnce itself /// it's used in [childBuilder] so the developer can custmize this when using it /// The [I] is extra options for the button, usually for it's state

@immutable
class QuillToolbarBaseButtonOptions<T, I> extends Equatable

Example for the clear format button:

class QuillToolbarClearFormatButtonExtraOptions
    extends QuillToolbarBaseButtonExtraOptions {
  const QuillToolbarClearFormatButtonExtraOptions({
    required super.controller,
    required super.context,
    required super.onPressed,
  });
}

class QuillToolbarClearFormatButtonOptions
    extends QuillToolbarBaseButtonOptions<QuillToolbarClearFormatButtonOptions,
        QuillToolbarClearFormatButtonExtraOptions> {
  const QuillToolbarClearFormatButtonOptions({
    super.iconData,
    super.afterButtonPressed,
    super.childBuilder,
    super.controller,
    super.iconTheme,
    super.tooltip,
    this.iconSize,
  });

  final double? iconSize;
}

The base for extra options:

@immutable
class QuillToolbarBaseButtonExtraOptions extends Equatable {
  const QuillToolbarBaseButtonExtraOptions({
    required this.controller,
    required this.context,
    required this.onPressed,
  });

  /// if you need the not null controller for some usage in the [childBuilder]
  /// then please use this instead of the one in the [options]
  final QuillController controller;

  /// if the child builder you must use this when the widget tapped or pressed
  /// in order to do what it expected to do
  final VoidCallback? onPressed;

  final BuildContext context;
  @override
  List<Object?> get props => [
        controller,
      ];
}

which usually share common things, it also add extra property which was not exsisting, which is childBuilder which allow to render custom widget based on the state of the button and the options of it

QuillToolbar(
    configurations: QuillToolbarConfigurations(
        buttonOptions: QuillToolbarButtonOptions(
        clearFormat: QuillToolbarClearFormatButtonOptions(
            childBuilder: (options, extraOptions) {
            return IconButton.filled(
                onPressed: extraOptions.onPressed,
                icon: const Icon(
                    CupertinoIcons.clear // or options.iconData
                    ),
            );
            },
        ),
        ),
    ),
),

the extraOptions usually contains the state variables and the evenets that you need to trigger like the onPressed, it also has the end context and the controller that will be used while the options has the custom controller for each button and it's nullable because there could be no custom controller so we will just use the global one

  1. The QuillToolbar and QuillToolbar.basic() factory constructor

since the basic factory constructor has more options than the original QuillToolbar which doesn't make much sense, at least to some developers, we have refactored the QuillToolbar.basic() to a different widget called the QuillToolbar and the QuillToolbar has been renamed to QuillBaseToolbar which is the base for QuillToolbar or any custom toolbar, sure you can create custom toolbar from scratch by just using the controller but if you want more support from the library use the QuillBaseToolbar

the children widgets of the new QuillToolbar and QuillEditor access to thier configurations by another two inherited widgets since QuillToolbar and QuillEditor take the configuration class and provide them internally using QuillToolbarProvider and QuillEditorProvider however the QuillBaseToolbar has a little bit different configurations so it has a different provider called QuillBaseToolbarProvider and it also already provided by default

But there is one note:

If you are using the toolbar buttons like QuillToolbarHistoryButton, QuillToolbarToggleStyleButton in the somewhere like the the custom toolbar (using QuillBaseToolbar or any custom widget) then you must provide them with QuillToolbarProvider inherited widget, you don't have to do this if you are using the QuillToolbar since it will be done for you

Example of custom toolbar:

QuillProvider(
  configurations: QuillConfigurations(
    controller: _controller,
    sharedConfigurations: const QuillSharedConfigurations(),
  ),
  child: Column(
    children: [
      QuillToolbarProvider(
        toolbarConfigurations: const QuillToolbarConfigurations(),
        child: QuillBaseToolbar(
          configurations: QuillBaseToolbarConfigurations(
            toolbarSize: 15 * 2,
            multiRowsDisplay: false,
            childrenBuilder: (context) {
              final controller = context.requireQuillController; // new extension which is a little bit shorter to access the quill provider then the controller

              // there are many options, feel free to explore them all!!
              return [
                QuillToolbarHistoryButton(
                  controller: controller,
                  options: const QuillToolbarHistoryButtonOptions(
                      isUndo: true),
                ),
                QuillToolbarHistoryButton(
                  controller: controller,
                  options: const QuillToolbarHistoryButtonOptions(
                      isUndo: false),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.bold,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_bold,
                    iconSize: 20,
                  ),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.italic,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_italic,
                    iconSize: 20,
                  ),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.underline,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_underline,
                    iconSize: 20,
                  ),
                ),
                QuillToolbarClearFormatButton(
                  controller: controller,
                  options: const QuillToolbarClearFormatButtonOptions(
                    iconData: Icons.format_clear,
                    iconSize: 20,
                  ),
                ),
                VerticalDivider(
                  indent: 12,
                  endIndent: 12,
                  color: Colors.grey.shade400,
                ),
                QuillToolbarSelectHeaderStyleButtons(
                  controller: controller,
                  options:
                      const QuillToolbarSelectHeaderStyleButtonsOptions(
                    iconSize: 20,
                  ),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.ol,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_list_numbered,
                    iconSize: 20,
                  ),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.ul,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_list_bulleted,
                    iconSize: 20,
                  ),
                ),
                QuillToolbarToggleStyleButton(
                  attribute: Attribute.blockQuote,
                  controller: controller,
                  options: const QuillToolbarToggleStyleButtonOptions(
                    iconData: Icons.format_quote,
                    iconSize: 20,
                  ),
                ),
                VerticalDivider(
                  indent: 12,
                  endIndent: 12,
                  color: Colors.grey.shade400,
                ),
                QuillToolbarIndentButton(
                    controller: controller,
                    isIncrease: true,
                    options: const QuillToolbarIndentButtonOptions(
                      iconData: Icons.format_indent_increase,
                      iconSize: 20,
                    )),
                QuillToolbarIndentButton(
                  controller: controller,
                  isIncrease: false,
                  options: const QuillToolbarIndentButtonOptions(
                    iconData: Icons.format_indent_decrease,
                    iconSize: 20,
                  ),
                ),
              ];
            },
          ),
        ),
      ),
      Expanded(
        child: QuillEditor.basic(
          configurations: const QuillEditorConfigurations(
            readOnly: false,
            placeholder: 'Write your notes',
            padding: EdgeInsets.all(16),
          ),
        ),
      )
    ],
  ),
)
  1. The QuillEditor and QuillEditor.basic()

since the QuillEditor.basic() is a lighter version than the original QuillEditor since it has less required configurations so we didn't change much, other than configuration class, but we most inform you if you are plan on sending pull request or you are a maintainer and when you add new property or change anything in QuillEditorConfigurations please regenerate the copyWith otherwise the QuilEditor.basic() will not apply some configurations

we have disabled the line numbers in the code block by default, you can enable them again using the followings:

QuillEditor.basic(
    configurations: const QuillEditorConfigurations(
            elementOptions: QuillEditorElementOptions(
            codeBlock: QuillEditorCodeBlockElementOptions(
                enableLineNumbers: true,
            ),
        ),
    ),
)
  1. QuillCustomButton:

We have renamed the property icon to iconData for indicate it a icon data and not icon widget

    QuillCustomButton(
        iconData: Icons.ac_unit,
        onTap: () {
          debugPrint('snowflake');
        }
    ),
  1. Using custom local for both QuillEditor and QuillToolbar

We have added sharedConfigurations property for shared things

 QuillProvider(
  configurations: QuillConfigurations(
    controller: _controller,
    sharedConfigurations: const QuillSharedConfigurations(
      locale: Locale('fr'),
    ),
  ),
  child: Column(
    children: [
      const QuillToolbar(
        configurations: QuillToolbarConfigurations(),
      ),
      Expanded(
        child: QuillEditor.basic(
          configurations: const QuillEditorConfigurations(),
        ),
      )
    ],
  ),
)
  1. Custom Size Image for other platforms (excluding web)

We have added new properties width, height, margin, alignment for all platforms other than mobile and web for the images for example

{
      "insert": {
         "image": "https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png"
      },
      "attributes":{
         "style":"width: 50; height: 50; margin: 10; alignment: topLeft"
      }
}
  1. Other Improvemenets

You don't need anything to get this done, we have used const more when possible, removed unused evenets, flutter best practices, convert to stateless widgets when possible, use better ways to listen for changes example:

instead of

MediaQuery.of(context).size;

we will use

MediaQuery.sizeOf(context);

We also minimized the amount of rebuilds using more efficent logic and there is more.

  1. More options

We have add more options in the extension package, for all the buttons, configurations, animations, enable and disable things

If you have facing any issues or questions feel free to ask us on Github issues