-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f96e0d2
commit 1657e45
Showing
1 changed file
with
375 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,375 @@ | ||
# migraiton to visual studio | ||
# Migrating `flutter-quill` to `visual-editor` | ||
|
||
> [!WARNING] | ||
> | ||
> At the time of writing, | ||
> `visual-editor` is still in development and **does not offer all the features `flutter-quill` offers**. | ||
> There are a few bugs that are noticeable (more specifically, text selection) | ||
> that do not work properly on mobile devices. | ||
> | ||
> We will make a migration to a **fork of `visual-editor`** - https://github.com/LuchoTurtle/visual-editor. | ||
> This is because the PR that was opened to `visual-editor` has need yet been merged | ||
> (https://github.com/visual-space/visual-editor/pull/237). | ||
> Once it is merged and this document has yet to be updated, | ||
> [please open an issue](https://github.com/dwyl/flutter-wysiwyg-editor-tutorial/issues/). | ||
|
||
[`visual-editor`](https://github.com/visual-space/visual-editor) is a fork of `flutter-quill` that, | ||
unlike the latter, | ||
is actively maintained. | ||
They've done a complete refactor of `flutter-quill`, | ||
documented the code and made it easier to contribute to. | ||
Because it offers some new features that can be easily integrated into your app, | ||
we've created this small migration guide so you can leverage this library | ||
from the app you've just implemented with `flutter-quill`. | ||
|
||
> [!NOTE] | ||
> | ||
> `visual-editor` provides a migration guide. | ||
> Check it in https://github.com/visual-space/visual-editor. | ||
|
||
# 0. Pre-requisites | ||
|
||
This guide builds upon the app that was created in | ||
[`README.md`](../README.md). | ||
Make sure you have completed the tutorial first | ||
and head back here so the code is in the same state. | ||
|
||
|
||
# 1. Install dependencies | ||
|
||
Head over to `pubspec.yaml` | ||
and change the `dependencies` section to the following. | ||
|
||
```yaml | ||
dependencies: | ||
flutter: | ||
sdk: flutter | ||
|
||
file_picker: ^5.3.3 | ||
universal_io: ^2.2.2 | ||
responsive_framework: ^1.1.0 | ||
universal_html: ^2.2.3 | ||
path: ^1.8.3 | ||
path_provider: ^2.1.0 | ||
http: ^1.1.0 | ||
mime: ^1.0.4 | ||
http_parser: ^4.0.2 | ||
|
||
visual_editor: | ||
git: | ||
url: https://github.com/LuchoTurtle/visual-editor.git | ||
ref: update_dependencies#236 | ||
``` | ||
- we've removed `flutter_quill` and `flutter_quill_extensions`. | ||
- we've upgraded `http` to version `1.1.0`. | ||
- we've installed `visual_editor` through the aforementioned fork. | ||
Normally you'll follow the guidelines in [`visual_editor`](https://github.com/visual-space/visual-editor#getting-started). | ||
|
||
|
||
# 2. Delete `web_embeds` | ||
|
||
With `visual-editor`, we do not need to use separate web embeds | ||
to make it work on the web. | ||
So you can safely delete 🗑️ | ||
`mobile_platform_registry.dart`, | ||
`web_embeds.dart` | ||
and `web_platform_registry.dart`, | ||
as they no longer will be needed. | ||
|
||
|
||
# 3. Update import, rename classes and delete unnecessary code | ||
|
||
The classes from `visual_editor`, | ||
although similar to `flutter-quill`, | ||
have different constructors and some will differ, | ||
so renaming classes won't work sometimes. | ||
|
||
But let's do that first! | ||
We'll deal with each issue along the way. | ||
Let's start with replacing the imports. | ||
Change the imports like so: | ||
|
||
`import 'package:flutter_quill/flutter_quill.dart';` -> `import 'package:visual_editor/visual-editor.dart';` | ||
|
||
Add `import 'package:visual_editor/document/models/attributes/attributes.model.dart';`, as well. | ||
We are going to need it. | ||
|
||
You can now delete any `flutter_quill` and `flutter_quill_extensions` import. | ||
You can also delete `import 'web_embeds/web_embeds.dart';`, | ||
since it no longer exists. | ||
|
||
Now, it's time to rename some classes! | ||
Follow the next steps. | ||
|
||
`QuillEditor` -> `VisualEditor` | ||
`QuillController` -> `EditorController` | ||
`QuillToolbar` -> `EditorToolbar` | ||
`DefaultTextBlockStyle` -> `TextBlockStyleM` | ||
`DefaultStyles` -> `EditorStylesM` | ||
`Document` -> `DeltaDocM` | ||
|
||
Awesome! | ||
|
||
The last thing we need to do is | ||
deleting our `_SelectionType` methods and classes. | ||
We have used these to handle the triple click selection behaviour | ||
on tap up. | ||
We don't need this any more. | ||
|
||
Therefore: | ||
- delete the `_SelectionType` enum. | ||
- delete `_SelectionType _selectionType = _SelectionType.none;` field from `HomePageState`. | ||
- delete the `_onTripleClickSelection()` function inside `HomePageState`. | ||
|
||
Great job! 🥳 | ||
|
||
We are now ready to | ||
change how our `visual-editor` classes are constructed! | ||
|
||
|
||
# 4. Update `visual-editor` classes invocations | ||
|
||
**From now on, we'll only be working inside the `HomePageState` class.** | ||
|
||
Let's start by changing our `_initializeText` function. | ||
`EditorController` now only receives one argument, | ||
which is the `document`. | ||
Change it to look like so: | ||
|
||
```dart | ||
Future<void> _initializeText() async { | ||
final doc = DeltaDocM(); | ||
setState(() { | ||
_controller = EditorController( | ||
document: doc, | ||
); | ||
}); | ||
} | ||
``` | ||
|
||
|
||
## 4.1 `VisualEditor` | ||
|
||
Let's move to the `VisualEditor`. | ||
We previously used `QuillEditor`, | ||
where we had a myriad of parameters we set. | ||
These parameters *are now more organised*, | ||
and will be changed like so. | ||
|
||
```dart | ||
Widget quillEditor = VisualEditor( | ||
controller: _controller!, | ||
scrollController: ScrollController(), | ||
focusNode: _focusNode, | ||
config: EditorConfigM( | ||
scrollable: true, | ||
autoFocus: false, | ||
readOnly: false, | ||
placeholder: 'Write what\'s on your mind.', | ||
enableInteractiveSelection: true, | ||
expands: false, | ||
padding: EdgeInsets.zero, | ||
customStyles: const EditorStylesM( | ||
h1: TextBlockStyleM( | ||
TextStyle( | ||
fontSize: 32, | ||
color: Colors.black, | ||
height: 1.15, | ||
fontWeight: FontWeight.w300, | ||
), | ||
VerticalSpacing(top: 16, bottom: 0), | ||
VerticalSpacing(top: 0, bottom: 0), | ||
VerticalSpacing(top: 16, bottom: 0), | ||
null, | ||
), | ||
sizeSmall: TextStyle(fontSize: 9), | ||
), | ||
), | ||
); | ||
``` | ||
|
||
As you can see, most of the configuration | ||
is now done under the `config` parameter, | ||
which receives an `EditorConfigM`. | ||
|
||
- `enableSelectionToolbar` becomes `enableInteractiveSelection`. | ||
- we define the `customStyles` with the `EditorStyleM` class. | ||
In this case, we are defining the `h1` field with `TextBlockStyleM` class, | ||
which has also changed. | ||
- `TextBlockStyleM` has an additional parameter, where you will need to define 4 arguments, instead of 3. | ||
The added argument pertains to `lastLineSpacing`, the spacing at the end of the text block. | ||
We've just added a `VerticalSpacing(top: 16, bottom: 0)` | ||
- we can't set the `subscript` and `superscript` fields in `EditorStylesM` (previously `DefaultStyles`), | ||
as they're not yet available. | ||
- we've also removed the `onTapUp` callback field, | ||
as we no longer need it. | ||
|
||
In the same file, | ||
we've re-defined `quillEditor` if it was in a web platform. | ||
Let's update that as well. | ||
It now becomes the following: | ||
|
||
```dart | ||
// Alternatively, the web editor version is shown (with the web embeds) | ||
if (widget.platformService.isWebPlatform()) { | ||
quillEditor = VisualEditor( | ||
controller: _controller!, | ||
scrollController: ScrollController(), | ||
focusNode: _focusNode, | ||
config: EditorConfigM( | ||
scrollable: true, | ||
enableInteractiveSelection: false, | ||
autoFocus: false, | ||
readOnly: false, | ||
placeholder: 'Add content', | ||
expands: false, | ||
padding: EdgeInsets.zero, | ||
customStyles: const EditorStylesM( | ||
h1: TextBlockStyleM( | ||
TextStyle( | ||
fontSize: 32, | ||
color: Colors.black, | ||
height: 1.15, | ||
fontWeight: FontWeight.w300, | ||
), | ||
VerticalSpacing(top: 16, bottom: 0), | ||
VerticalSpacing(top: 0, bottom: 0), | ||
VerticalSpacing(top: 16, bottom: 0), | ||
null, | ||
), | ||
sizeSmall: TextStyle(fontSize: 9), | ||
), | ||
), | ||
); | ||
} | ||
``` | ||
|
||
## 4.2 `EditorToolbar` | ||
|
||
`QuillToolbar` now becomes `EditorToolbar`. | ||
With `flutter-quill`, | ||
we used `FlutterQuillEmbeds.buttons` and appended these custom embed buttons | ||
this to the toolbar's children. | ||
|
||
**This is not the case in `visual-editor`.** | ||
|
||
You will simply list the buttons in the `customButton` field | ||
and add the necessary callbacks (like `webImagePickImpl` or `onImagePickCallback`, for example) to the relevant buttons. | ||
You can also use the `children` field to enforce a custom order, | ||
feeding the list straight to `EditorToolbar`'s constructor. | ||
However, in this case, it's almost pointless to use this field as it does not provide much functionality on top of the customs buttons set. | ||
|
||
Let's add our buttons to the toolbar, then! | ||
Locate the `toolbar` variable, | ||
and change it. | ||
|
||
```dart | ||
// Toolbar definitions | ||
const toolbarIconSize = 18.0; | ||
const toolbarButtonSpacing = 2.5; | ||
// Instantiating the toolbar | ||
final toolbar = EditorToolbar( | ||
children: [ | ||
HistoryButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
icon: Icons.undo_outlined, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
isUndo: true, | ||
), | ||
HistoryButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
icon: Icons.redo_outlined, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
isUndo: false, | ||
), | ||
ToggleStyleButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
attribute: AttributesM.bold, | ||
icon: Icons.format_bold, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
), | ||
ToggleStyleButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
attribute: AttributesM.italic, | ||
icon: Icons.format_italic, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
), | ||
ToggleStyleButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
attribute: AttributesM.underline, | ||
icon: Icons.format_underline, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
), | ||
ToggleStyleButton( | ||
buttonsSpacing: toolbarButtonSpacing, | ||
attribute: AttributesM.strikeThrough, | ||
icon: Icons.format_strikethrough, | ||
iconSize: toolbarIconSize, | ||
controller: _controller!, | ||
), | ||
// Our embed buttons | ||
ImageButton( | ||
icon: Icons.image, | ||
iconSize: toolbarIconSize, | ||
buttonsSpacing: toolbarButtonSpacing, | ||
controller: _controller!, | ||
onImagePickCallback: _onImagePickCallback, | ||
webImagePickImpl: _webImagePickImpl, | ||
mediaPickSettingSelector: (context) { | ||
return Future.value(MediaPickSettingE.Gallery); | ||
}, | ||
), | ||
], | ||
); | ||
``` | ||
|
||
Here's a list of relevant changes we've made: | ||
|
||
- removed `FlutterQuillEmbeds.buttons` - we don't need to use `FlutterQuillEmbeds` to create embed buttons any more. | ||
We simply create them normally in the children field. | ||
- removed the `afterButtonPressed` field from `EditorToolbar` constructor. | ||
- added `buttonsSpacing` field to all buttons, as it's required. | ||
- `Attribute` is now renamed to `AttributesM` | ||
(which is why we imported it in the beginning of this guide). | ||
- `MediaPickSetting` is now renamed to `MediaPickSettingE`. | ||
|
||
|
||
Each button we add needs to have the `buttonsSpacing` field defined. | ||
But now can simply define our array of buttons, | ||
display them in the order we like, | ||
and not have to worry about web embeds or anything like that! | ||
All the necessary callbacks (like `onImagePickCallback`) | ||
are related to relevant buttons (`CameraButton`, for example). | ||
So we don't add this behaviour to the definition of the `toolbar`, | ||
but **to the adequate button**. | ||
Much simpler, right? | ||
|
||
|
||
# 5. Changing tests | ||
|
||
Let's fix the compiling errors on our tests. | ||
Luckily, it's simple. | ||
Just change the imports like we've done at the beginning of this guide, | ||
and replace `QuillEditor` with `VisualEditor` | ||
(and other necessary classes). | ||
|
||
The method `tester.quillEnterText()` no longer exists, | ||
so you can safely delete it. | ||
|
||
|
||
# 6. You're done! 🎉 | ||
|
||
Congratulations, you've successfully migrated | ||
the app from `flutter-quill` to `visual-editor`! | ||
|
||
Give yourself a pat on the back! 👏 |