Version 9.0.0 (#1566)

* Prepare for Version 9.0.0
pull/1577/head
Ellet 1 year ago committed by GitHub
parent 363437deaf
commit c02699071a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/PULL_REQUEST_TEMPLATE.md
  2. 3
      .github/workflows/build.yml
  3. 3
      .github/workflows/main.yml
  4. 23
      .github/workflows/publish.yml
  5. 5
      .pubignore
  6. 52
      CHANGELOG.md
  7. 2
      CONTRIBUTING.md
  8. 22
      README.md
  9. 6
      doc/development_notes.md
  10. 431
      doc/migration.md
  11. 429
      doc/migration/7_8.md
  12. 83
      doc/migration/8_9.md
  13. 11
      doc/todo.md
  14. 2
      doc/translation.md
  15. 2
      example/android/app/build.gradle
  16. 16
      example/android/app/src/main/AndroidManifest.xml
  17. 2
      example/android/build.gradle
  18. 2
      example/android/gradle/wrapper/gradle-wrapper.properties
  19. 3
      example/lib/presentation/quill/my_quill_editor.dart
  20. 163
      example/lib/presentation/quill/my_quill_toolbar.dart
  21. 98
      example/lib/presentation/quill/quill_screen.dart
  22. 6
      example/lib/presentation/quill/samples/quill_images_sample.dart
  23. 36
      example/lib/presentation/simple/simple_screen.dart
  24. 12
      example/linux/flutter/generated_plugin_registrant.cc
  25. 3
      example/linux/flutter/generated_plugins.cmake
  26. 6
      example/macos/Flutter/GeneratedPluginRegistrant.swift
  27. 16
      example/macos/Podfile.lock
  28. 15
      example/pubspec.yaml
  29. 9
      example/windows/flutter/generated_plugin_registrant.cc
  30. 3
      example/windows/flutter/generated_plugins.cmake
  31. 1672
      flutter_quill_extensions/CHANGELOG.md
  32. 26
      flutter_quill_extensions/README.md
  33. 13
      flutter_quill_extensions/lib/embeds/formula/toolbar/formula_button.dart
  34. 28
      flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart
  35. 3
      flutter_quill_extensions/lib/embeds/image/editor/image_embed_types.dart
  36. 102
      flutter_quill_extensions/lib/embeds/image/editor/image_menu.dart
  37. 25
      flutter_quill_extensions/lib/embeds/image/toolbar/image_button.dart
  38. 8
      flutter_quill_extensions/lib/embeds/image/toolbar/select_image_source.dart
  39. 34
      flutter_quill_extensions/lib/embeds/others/camera_button/camera_button.dart
  40. 56
      flutter_quill_extensions/lib/embeds/others/camera_button/select_camera_action.dart
  41. 36
      flutter_quill_extensions/lib/embeds/others/image_video_utils.dart
  42. 4
      flutter_quill_extensions/lib/embeds/others/media_button/media_button.dart
  43. 5
      flutter_quill_extensions/lib/embeds/video/editor/video_embed.dart
  44. 3
      flutter_quill_extensions/lib/embeds/video/toolbar/select_video_source.dart
  45. 31
      flutter_quill_extensions/lib/embeds/video/toolbar/video_button.dart
  46. 2
      flutter_quill_extensions/lib/embeds/video/video.dart
  47. 7
      flutter_quill_extensions/lib/embeds/widgets/image.dart
  48. 0
      flutter_quill_extensions/lib/extensions/controller_ext.dart
  49. 8
      flutter_quill_extensions/lib/flutter_quill_extensions.dart
  50. 46
      flutter_quill_extensions/lib/models/config/shared_configurations.dart
  51. 73
      flutter_quill_extensions/lib/utils/element_utils/element_shared_utils.dart
  52. 24
      flutter_quill_extensions/lib/utils/element_utils/element_utils.dart
  53. 17
      flutter_quill_extensions/lib/utils/patterns.dart
  54. 28
      flutter_quill_extensions/lib/utils/utils.dart
  55. 8
      flutter_quill_extensions/pubspec.yaml
  56. 1622
      flutter_quill_test/CHANGELOG.md
  57. 4
      flutter_quill_test/pubspec.yaml
  58. 20
      lib/flutter_quill.dart
  59. 5
      lib/markdown_quill.dart
  60. 93
      lib/src/extensions/quill_configurations_ext.dart
  61. 6
      lib/src/extensions/quill_controller_ext.dart
  62. 160
      lib/src/extensions/quill_provider.dart
  63. 11
      lib/src/extensions/uri_ext.dart
  64. 28
      lib/src/l10n/generated/quill_localizations.dart
  65. 18
      lib/src/l10n/generated/quill_localizations_ar.dart
  66. 18
      lib/src/l10n/generated/quill_localizations_bg.dart
  67. 18
      lib/src/l10n/generated/quill_localizations_bn.dart
  68. 18
      lib/src/l10n/generated/quill_localizations_cs.dart
  69. 18
      lib/src/l10n/generated/quill_localizations_da.dart
  70. 18
      lib/src/l10n/generated/quill_localizations_de.dart
  71. 18
      lib/src/l10n/generated/quill_localizations_en.dart
  72. 18
      lib/src/l10n/generated/quill_localizations_es.dart
  73. 18
      lib/src/l10n/generated/quill_localizations_fa.dart
  74. 18
      lib/src/l10n/generated/quill_localizations_fr.dart
  75. 18
      lib/src/l10n/generated/quill_localizations_he.dart
  76. 18
      lib/src/l10n/generated/quill_localizations_hi.dart
  77. 18
      lib/src/l10n/generated/quill_localizations_id.dart
  78. 18
      lib/src/l10n/generated/quill_localizations_it.dart
  79. 18
      lib/src/l10n/generated/quill_localizations_ja.dart
  80. 18
      lib/src/l10n/generated/quill_localizations_ko.dart
  81. 18
      lib/src/l10n/generated/quill_localizations_ms.dart
  82. 18
      lib/src/l10n/generated/quill_localizations_nl.dart
  83. 18
      lib/src/l10n/generated/quill_localizations_no.dart
  84. 18
      lib/src/l10n/generated/quill_localizations_pl.dart
  85. 18
      lib/src/l10n/generated/quill_localizations_pt.dart
  86. 18
      lib/src/l10n/generated/quill_localizations_ru.dart
  87. 18
      lib/src/l10n/generated/quill_localizations_sr.dart
  88. 18
      lib/src/l10n/generated/quill_localizations_sw.dart
  89. 18
      lib/src/l10n/generated/quill_localizations_tk.dart
  90. 18
      lib/src/l10n/generated/quill_localizations_tr.dart
  91. 18
      lib/src/l10n/generated/quill_localizations_uk.dart
  92. 18
      lib/src/l10n/generated/quill_localizations_ur.dart
  93. 18
      lib/src/l10n/generated/quill_localizations_vi.dart
  94. 18
      lib/src/l10n/generated/quill_localizations_zh.dart
  95. 8
      lib/src/l10n/quill_en.arb
  96. 132
      lib/src/l10n/untranslated.json
  97. 4
      lib/src/l10n/widgets/localizations.dart
  98. 21
      lib/src/models/config/editor/editor_configurations.dart
  99. 9
      lib/src/models/config/editor/element_options.dart
  100. 14
      lib/src/models/config/editor/elements/list/ordered_list.dart
  101. Some files were not shown because too many files have changed in this diff Show More

@ -28,7 +28,7 @@
- [ ] I titled the PR using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0). - [ ] I titled the PR using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0).
- [ ] I did not modify the `CHANGELOG.md` nor the plugin version in `pubspec.yaml` files. - [ ] I did not modify the `CHANGELOG.md` nor the plugin version in `pubspec.yaml` files.
- [ ] All existing and new tests are passing. - [ ] All existing and new tests are passing.
- [ ] I have run the commands in `./scripts/before-push.sh` and it all passed successfully - [ ] I have run the commands in `./scripts/before_push.sh` and it all passed successfully
## Breaking Change ## Breaking Change

@ -17,6 +17,9 @@ jobs:
- name: Check flutter version - name: Check flutter version
run: flutter --version run: flutter --version
- name: Enable Local Dev
run: ./scripts/enable_local_dev.sh
- name: Install dependencies - name: Install dependencies
run: flutter pub get run: flutter pub get

@ -20,6 +20,9 @@ jobs:
- name: Check flutter version - name: Check flutter version
run: flutter --version run: flutter --version
- name: Enable Local Dev
run: ./scripts/enable_local_dev.sh
- name: Install dependencies - name: Install dependencies
run: flutter pub get run: flutter pub get

@ -16,26 +16,39 @@ jobs:
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
channel: 'stable' channel: 'stable'
cache: true
- name: Check flutter version - name: Check flutter version
run: flutter --version run: flutter --version
- name: Enable Local Dev
run: ./scripts/enable_local_dev.sh
- name: Install dependencies - name: Install dependencies
run: flutter pub get run: flutter pub get
# Here you can insert custom steps you need # Here you can insert custom steps you need
# - run: dart tool/generate-code.dart # - run: dart tool/generate-code.dart
- name: Re-generate the translations
run: ./scripts/regenerate-translations.sh
# This is needed in order for the authentication to success # This is needed in order for the authentication to success
# dart pub token add https://pub.dev --env-var PUB_TOKEN # dart pub token add https://pub.dev --env-var PUB_TOKEN
# Requests to "https://pub.dev" will now be authenticated using the secret token stored in the environment variable "PUB_TOKEN". # Requests to "https://pub.dev" will now be authenticated using the secret token stored in the environment variable "PUB_TOKEN".
- uses: dart-lang/setup-dart@v1 - uses: dart-lang/setup-dart@v1
## dart-lang/setup-dart/.github/workflows/publish.yml@v1
# - name: Update the authorization requests to "https://pub.dev" to use the environment variable "PUB_TOKEN". # - name: Update the authorization requests to "https://pub.dev" to use the environment variable "PUB_TOKEN".
# run: dart pub token add https://pub.dev --env-var PUB_TOKEN # run: dart pub token add https://pub.dev --env-var PUB_TOKEN
- name: Publish - name: Publish flutter_quill
run: flutter pub publish --force
- name: Publish flutter_quill_extensions
run: flutter pub publish --force
working-directory: ./flutter_quill_extensions/
- name: Publish flutter_quill_test
run: flutter pub publish --force
working-directory: ./flutter_quill_test/
- name: Publish quill_html_converter
run: flutter pub publish --force run: flutter pub publish --force
working-directory: ./packages/quill_html_converter/

@ -10,7 +10,4 @@ example/.fvm/
example/build/ example/build/
example/.dart_tool/ example/.dart_tool/
scripts/ scripts/
<!-- flutter_quill_extensions/
flutter_quill_test/
packages/ -->

@ -2,6 +2,58 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## 9.0.0-dev-8
* Better support for pasting HTML contents from external websites to the editor
* The experimental support of converting the HTML from `quill_html_converter` is now built-in in the `flutter_quill` and removed from there (Breaking change for `quill_html_converter`)
## 9.0.0-dev-7
* Fix a bug in chaning the background/font color of ol/ul list
* Flutter Quill Extensions:
* Fix link bug in the video url
* Fix patterns
## 9.0.0-dev-6
* Move the `child` from `QuillToolbarConfigurations` into `QuillToolbar` directly
* Bug fixes
* Add the ability to change the background and font color of the ol/ul elements dots and numbers
* Flutter Quill Extensions:
* **Breaking Change**: The `imageProviderBuilder`is now providing the context and image url
## 9.0.0-dev-5
* The `QuillToolbar` is now accepting only `child` with no configurations so you can customize everything you wants, the `QuillToolbar.simple()` or `QuillSimpleToolbar` implements a simple toolbar that is based on `QuillToolbar`, you are free to use it but it just an example and not standard
* Flutter Quill Extensions:
* Improve the camera button
## 9.0.0-dev-4
* The options parameter in all of the buttons is no longer required which can be useful to create custom toolbar with minimal efforts
* Toolbar buttons fixes in both `flutter_quill` and `flutter_quill_extensions`
* The `QuillProvider` has been dropped and no longer used, the providers will be used only internally from now on and we will not using them as much as possible
## 9.0.0-dev-3
* Breaking Changes:
* Rename `QuillToolbar` to `QuillSimpleToolbar`
* Rename `QuillBaseToolbar` to `QuillToolbar`
* Replace `pasteboard` with `rich_cliboard`
* Fix a bug in the example when inserting an image from url
* Flutter Quill Extensions:
* Add support for copying the image to the system cliboard
## 9.0.0-dev-2
* An attemp to fix CI automated publishing
## 9.0.0-dev-1
* An attemp to fix CI automated publishing
## 9.0.0-dev
* **Major Breaking change**: The `QuillProvider` is now optional, the `controller` parameter has been moved to the `QuillEditor` and `QuillToolbar` once again.
* Flutter Quill Extensions;
* **Breaking Change**: Completly change the way how the source code structured to more basic and simple way, organize folders and file names, if you use the library
from `flutter_quill_extensions.dart` then there is nothing you need to do, but if you are using any other import then you need to re-imports
embed, this won't affect how quill js work
* Improvemenets to the image embed
* Add support for `margin` for web
* Add untranslated strings to the `quill_en.arb`
## 8.6.4 ## 8.6.4
* The default value of `keyboardAppearance` for the iOS will be the one from the App/System theme mode instead of always using the `Brightness.light` * The default value of `keyboardAppearance` for the iOS will be the one from the App/System theme mode instead of always using the `Brightness.light`
* Fix typos in `README.md` * Fix typos in `README.md`

@ -39,7 +39,7 @@ to `pubspec_overrides.yaml` which will be ignored by `.gitignore` and will be us
9. Mention the new changes in the [CHANGELOG.md](../CHANGELOG.md) in the next block 9. Mention the new changes in the [CHANGELOG.md](../CHANGELOG.md) in the next block
10. Run the following script if possible 10. Run the following script if possible
``` ```
./scripts/before-push.sh ./scripts/before_push.sh
``` ```
11. When you are done sending your pull request, run: 11. When you are done sending your pull request, run:
``` ```

@ -94,17 +94,27 @@ dependencies:
> Your input and insights are valuable in shaping a stable and reliable version for all our users. Thank you for being part of the open-source community! > Your input and insights are valuable in shaping a stable and reliable version for all our users. Thank you for being part of the open-source community!
> >
Compatible versions: <!-- Compatible versions:
| flutter_quill | flutter_quill_extensions | flutter_quill_test | | flutter_quill | flutter_quill_extensions | flutter_quill_test |
|-------------------------|--------------------------|-------------------------| |-------------------------|--------------------------|-------------------------|
| 8.6.x | 0.7.x | 0.0.5 | | 8.6.x | 0.7.x | 0.0.5 |
| 8.5.x | 0.6.x | 0.0.5 | | 8.5.x | 0.6.x | 0.0.5 |
These versions are tested and well-supported, you shouldn't get a build failure These versions are tested and well-supported, you shouldn't get a build failure -->
## Usage ## Usage
Before using the package, we must inform you the package use the following plugins:
```
url_launcher
flutter_keyboard_visibility
device_info_plus
super_clipboard
```
All of them doesn't require any platform spesefic setup, except [super_clipboard](https://pub.dev/packages/super_clipboard) which needs some setup on Android only, it's optional but to support copying images and pasting them into editor then you must setup it, open the page in pub.dev and read the `README.md` to get the instructions.
First, you need to instantiate a controller First, you need to instantiate a controller
```dart ```dart
@ -228,11 +238,13 @@ To see how to use the extension package, please take a look at the [README](./fl
Having your document stored in Quill Delta format is sometimes not enough. Often you'll need to convert Having your document stored in Quill Delta format is sometimes not enough. Often you'll need to convert
it to other formats such as HTML to publish it, or send an email. it to other formats such as HTML to publish it, or send an email.
**Note**: This package support converting from HTML back to Quill delta but it's experimental and used internally when pasting Html content from the cliboard to the Quill Editor
You have two options: You have two options:
1. Using [quill_html_converter](./packages/quill_html_converter/) to convert to/from HTML, the package can convert the Quill delta to HTML well 1. Using [quill_html_converter](./packages/quill_html_converter/) to convert to HTML, the package can convert the Quill delta to HTML well
(it uses [vsc_quill_delta_to_html](https://pub.dev/packages/vsc_quill_delta_to_html)) but the converting from HTML back to Quill delta is experimental (it uses [vsc_quill_delta_to_html](https://pub.dev/packages/vsc_quill_delta_to_html)), it just a handy extension to do it more quickly
2. Another option is to use 1. Another option is to use
[vsc_quill_delta_to_html](https://pub.dev/packages/vsc_quill_delta_to_html) to convert your document [vsc_quill_delta_to_html](https://pub.dev/packages/vsc_quill_delta_to_html) to convert your document
to HTML. to HTML.
This package has full support for all Quill operations—including images, videos, formulas, This package has full support for all Quill operations—including images, videos, formulas,

@ -1,3 +1,9 @@
# Development notes # Development notes
- When updating the translations or localizations in the app, please take a look at the [Translation](./translation.md) page as it has important notes in order to work, if you also add a feature that adds new localizations then you need to the instructions of it in order for the translations to take effect - When updating the translations or localizations in the app, please take a look at the [Translation](./translation.md) page as it has important notes in order to work, if you also add a feature that adds new localizations then you need to the instructions of it in order for the translations to take effect
- Only update the `version.dart` and `CHANGELOG.md` at the root folder of the repo, then run the script:
```console
dart ./scripts/regenerate_versions.dart
```
You must mention the changes of the other packages in the repo in the root `CHANGELOG.md` only and the script will replace the `CHANGELOG.md` in the other packages with the root one, and change the version in `pubspec.yaml` with the one in `version.dart` in the root folder

@ -5,435 +5,12 @@ Here you can find the migration guide between different versions, you can contri
- [Migration guide](#migration-guide) - [Migration guide](#migration-guide)
- [from 7.0.0 to 8.0.0](#from-700-to-800) - [from 7.0.0 to 8.0.0](#from-700-to-800)
- [from 8.0.0 to 9.0.0](#from-800-to-900)
## from 7.0.0 to 8.0.0 ## 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 allows 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 Open [this](./migration/7_8.md) md file
1. Passing the controller ## from 8.0.0 to 9.0.0
The controller code (should be the same) Open [this](./migration/8_9.md) md file
```dart
QuillController _controller = QuillController.basic();
```
**Old code**:
```dart
Column(
children: [
QuillToolbar.basic(controller: _controller),
Expanded(
child: QuillEditor.basic(
controller: _controller,
readOnly: false, // true for view only mode
),
)
],
)
```
**New code**:
```dart
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 an inherited widget that allows you to 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 exist 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`
2. Regarding 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`, for example the type for the buttons
- `QuillToolbarHistoryButton` have `QuillToolbarHistoryButtonOptions`
- `QuillToolbarIndentButton` have `QuillToolbarIndentButtonOptions`
- `QuillToolbarClearFormatButton` have `QuillToolbarClearFormatButtonOptions`
All the options have parent `QuillToolbarBaseButtonOptions` which have common things like
```dart
/// By default it will use Icon data from Icons that come 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 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;
/// The factor of how much larger the button is in relation to the icon,
/// by default it will be [kIconButtonFactor].
final double globalIconButtonFactor;
/// 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`:
```dart
/// The [T] is the option for the button, usually should reference itself
/// it's used in [childBuilder] so the developer can customize this when using it
/// The [I] is an extra option for the button, usually for its state
@immutable
class QuillToolbarBaseButtonOptions<T, I> extends Equatable
```
Example for the clear format button:
```dart
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:
```dart
@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 is 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 an extra property which was not exist, which is `childBuilder` which allow to rendering of custom widget based on the state of the button and the options it
```dart
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 events 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
3. 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 their 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` 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 a custom toolbar:
```dart
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),
),
),
)
],
),
)
```
4. The `QuillEditor` and `QuillEditor.basic()`
since the `QuillEditor.basic()` is a lighter version than the original `QuillEditor` since it has fewer required configurations we didn't change much, other than the configuration class, but we must inform you if you 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` (using IDE extension or plugin) 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 following:
```dart
QuillEditor.basic(
configurations: const QuillEditorConfigurations(
elementOptions: QuillEditorElementOptions(
codeBlock: QuillEditorCodeBlockElementOptions(
enableLineNumbers: true,
),
),
),
)
```
5. `QuillCustomButton`:
We have renamed the property `icon` to `iconData` to indicate it an icon data and not an icon widget
```dart
QuillCustomButton(
iconData: Icons.ac_unit,
onTap: () {
debugPrint('snowflake');
}
),
```
6. Using custom local for both `QuillEditor` and `QuillToolbar`
We have added shared configurations property for shared things
```dart
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(),
),
)
],
),
)
```
7. Image size for all platforms
We have added new properties `width`, `height`, `margin`, `alignment` for all platforms other than mobile and web for the images for example
```dart
{
"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"
}
}
```
8. Other Improvements
You don't need anything to get this done, we have used const more when possible, removed unused events, flutter best practices, converted to stateless widgets when possible, and used better ways to listen for changes example:
instead of
```dart
MediaQuery.of(context).size;
```
we will use
```dart
MediaQuery.sizeOf(context);
```
We also minimized the number of rebuilds using more efficient logic and there is more.
9. More options
We have added more options in the extension package, for all the buttons, configurations, animations, enable and disable things
If you are facing any issues or questions feel free to ask us on GitHub issues

@ -0,0 +1,429 @@
We have refactored a lot of the base code to allow you to customize everything you want, and it allows 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)
```dart
QuillController _controller = QuillController.basic();
```
**Old code**:
```dart
Column(
children: [
QuillToolbar.basic(controller: _controller),
Expanded(
child: QuillEditor.basic(
controller: _controller,
readOnly: false, // true for view only mode
),
)
],
)
```
**New code**:
```dart
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 an inherited widget that allows you to 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 exist 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`
2. Regarding 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`, for example the type for the buttons
- `QuillToolbarHistoryButton` have `QuillToolbarHistoryButtonOptions`
- `QuillToolbarIndentButton` have `QuillToolbarIndentButtonOptions`
- `QuillToolbarClearFormatButton` have `QuillToolbarClearFormatButtonOptions`
All the options have parent `QuillToolbarBaseButtonOptions` which have common things like
```dart
/// By default it will use Icon data from Icons that come 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 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;
/// The factor of how much larger the button is in relation to the icon,
/// by default it will be [kIconButtonFactor].
final double globalIconButtonFactor;
/// 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`:
```dart
/// The [T] is the option for the button, usually should reference itself
/// it's used in [childBuilder] so the developer can customize this when using it
/// The [I] is an extra option for the button, usually for its state
@immutable
class QuillToolbarBaseButtonOptions<T, I> extends Equatable
```
Example for the clear format button:
```dart
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:
```dart
@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 is 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 an extra property which was not exist, which is `childBuilder` which allow to rendering of custom widget based on the state of the button and the options it
```dart
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 events 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
3. 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 their 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` 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 a custom toolbar:
```dart
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),
),
),
)
],
),
)
```
4. The `QuillEditor` and `QuillEditor.basic()`
since the `QuillEditor.basic()` is a lighter version than the original `QuillEditor` since it has fewer required configurations we didn't change much, other than the configuration class, but we must inform you if you 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` (using IDE extension or plugin) 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 following:
```dart
QuillEditor.basic(
configurations: const QuillEditorConfigurations(
elementOptions: QuillEditorElementOptions(
codeBlock: QuillEditorCodeBlockElementOptions(
enableLineNumbers: true,
),
),
),
)
```
5. `QuillCustomButton`:
We have renamed the property `icon` to `iconData` to indicate it an icon data and not an icon widget
```dart
QuillCustomButton(
iconData: Icons.ac_unit,
onTap: () {
debugPrint('snowflake');
}
),
```
6. Using custom local for both `QuillEditor` and `QuillToolbar`
We have added shared configurations property for shared things
```dart
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(),
),
)
],
),
)
```
7. Image size for all platforms
We have added new properties `width`, `height`, `margin`, `alignment` for all platforms other than mobile and web for the images for example
```dart
{
"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"
}
}
```
8. Other Improvements
You don't need anything to get this done, we have used const more when possible, removed unused events, flutter best practices, converted to stateless widgets when possible, and used better ways to listen for changes example:
instead of
```dart
MediaQuery.of(context).size;
```
we will use
```dart
MediaQuery.sizeOf(context);
```
We also minimized the number of rebuilds using more efficient logic and there is more.
9. More options
We have added more options in the extension package, for all the buttons, configurations, animations, enable and disable things
If you are facing any issues or questions feel free to ask us on GitHub issues

@ -0,0 +1,83 @@
1. Removing the `QuillProvider`
We got a lot of feedbacks about `QuillProvider`, while the provider help removing duplicate lines for simple usage, for more advance usage it become very messy
So from now on we will use providers for the `QuillToolbar` and `QuillEditor` only internally, you don't need it anymore
Instead you will need to pass the configurations directly in the `QuillToolbar` and `QuillEditor`
**Old code**:
```dart
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
),
),
)
],
),
)
```
**New code**:
```dart
Column(
children: [
QuillToolbar.simple(
QuillSimpleToolbarConfigurations(controller: _controller)),
Expanded(
child: QuillEditor.basic(
configurations: QuillEditorConfigurations(controller: _controller),
),
)
],
)
```
2. Refactoring the Base Toolbar
From now on, the `QuillToolbar` will be a widget that only provides the things that the buttons needs like localizations and `QuillToolbarProvider`
So you can define your own toolbar from scratch just like in Quill JS
The `QuillToolbar` is now accepting only `child` with no configurations so you can customize everything you wants, the `QuillToolbar.simple()` or `QuillSimpleToolbar` implements a simple toolbar that is based on `QuillToolbar`, you are free to use it but it just an example and not standard
1. Source Code Structure
Completly changed the way how the source code structured to more basic and simple way, organize folders and file names, if you use the library
from `flutter_quill_extensions.dart` then there is nothing you need to do, but if you are using any other import then you need to re-imports
4. Change the version system
For [more details](https://github.com/singerdmx/flutter-quill/discussions/1560)
5. Dependencies changes
1. Add `gal_linux` in `flutter_quill_extensions`
2. Replace `pasteboard` with `rich_cliboard`
3. Remove `flutter_animate`
6. Optional options for the buttons
All the buttons from now on, have optional options parameter
7. Improve Flutter Quill Extensions
Bug fixes and new features, the extensions package keep getting better thanks to the community.
8. Migrate to Material 3
We have migrated all of the buttons to material 3, removed a lot of old parameters, if you want to customize one or all the buttons to replacing it with completly different widget with the same state use the `base` in the button options for all or the button name for one
We have also replaced the header style buttons with one dropdown button as a default, replaced the alignment buttons with less code and a lot more

@ -29,6 +29,10 @@ This is a todo list page that added recently and will be updated soon.
- Extract the shared properties between `QuillRawEditorConfigurations` and `QuillEditorConfigurations` - Extract the shared properties between `QuillRawEditorConfigurations` and `QuillEditorConfigurations`
- The todo in the this [commit](https://github.com/singerdmx/flutter-quill/commit/79597ea6425357795c0663588ac079665241f23a) needs to be checked - The todo in the this [commit](https://github.com/singerdmx/flutter-quill/commit/79597ea6425357795c0663588ac079665241f23a) needs to be checked
- use `maybeOf` and of instead `ofNotNull` in the providers to follow flutter offical convenstion, completly rework the providers and update the build context extensions - use `maybeOf` and of instead `ofNotNull` in the providers to follow flutter offical convenstion, completly rework the providers and update the build context extensions
- Add line through to the text when the check point checked is true
- Change the color of the numbers and dots in ol/ul to match the ones in the item list
- Fix the bugs of the font family and font size
- Try to update Quill Html Converter
### Bugs ### Bugs
@ -39,12 +43,7 @@ Please go to the [issues](https://github.com/singerdmx/flutter-quill/issues)
## Flutter Quill Extensions ## Flutter Quill Extensions
### Features ### Features
- Add support for copying images to the Clipboard
### Improvemenets ### Improvemenets
Please check the todos, this list will be updated soon. ### Bugs
### Bugs
Please check the todos, this list will be updated soon.

@ -56,7 +56,7 @@ flutter gen-l10n
or: or:
``` ```
./scripts/regenerate-translations.sh ./scripts/regenerate_translations.sh
``` ```

@ -24,7 +24,7 @@ if (flutterVersionName == null) {
android { android {
namespace "com.example.example" namespace "com.example.example"
compileSdk flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion ndkVersion flutter.ndkVersion
compileOptions { compileOptions {

@ -1,10 +1,11 @@
<manifest xmlns:tools="http://schemas.android.com/tools" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" android:maxSdkVersion="32"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
@ -43,7 +44,7 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<!-- For `image_cropper` plugin --> <!-- For `image_cropper` plugin https://pub.dev/packages/image_cropper -->
<activity <activity
android:name="com.yalantis.ucrop.UCropActivity" android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
@ -54,5 +55,12 @@
<meta-data <meta-data
android:name="flutterEmbedding" android:name="flutterEmbedding"
android:value="2" /> android:value="2" />
<!-- For `super_clipboard` plugin https://pub.dev/packages/super_clipboard -->
<provider
android:name="com.superlist.super_native_extensions.DataProvider"
android:authorities="com.example.example.SuperClipboardDataProvider"
android:exported="true"
android:grantUriPermissions="true" />
</application> </application>
</manifest> </manifest>

@ -8,7 +8,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.1.4' classpath 'com.android.tools.build:gradle:8.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip

@ -82,7 +82,7 @@ class MyQuillEditor extends StatelessWidget {
'Error while loading an image: ${error.toString()}', 'Error while loading an image: ${error.toString()}',
); );
}, },
imageProviderBuilder: (imageUrl) { imageProviderBuilder: (context, imageUrl) {
// cached_network_image is supported // cached_network_image is supported
// only for Android, iOS and web // only for Android, iOS and web
@ -99,6 +99,7 @@ class MyQuillEditor extends StatelessWidget {
return getImageProviderByImageSource( return getImageProviderByImageSource(
imageUrl, imageUrl,
imageProviderBuilder: null, imageProviderBuilder: null,
context: context,
assetsPrefix: QuillSharedExtensionsConfigurations.get( assetsPrefix: QuillSharedExtensionsConfigurations.get(
context: context) context: context)
.assetsPrefix, .assetsPrefix,

@ -10,16 +10,17 @@ import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' import 'package:path_provider/path_provider.dart'
show getApplicationDocumentsDirectory; show getApplicationDocumentsDirectory;
import '../extensions/scaffold_messenger.dart';
import '../settings/cubit/settings_cubit.dart'; import '../settings/cubit/settings_cubit.dart';
import 'embeds/timestamp_embed.dart'; import 'embeds/timestamp_embed.dart';
class MyQuillToolbar extends StatelessWidget { class MyQuillToolbar extends StatelessWidget {
const MyQuillToolbar({ const MyQuillToolbar({
required this.controller,
required this.focusNode, required this.focusNode,
super.key, super.key,
}); });
final QuillController controller;
final FocusNode focusNode; final FocusNode focusNode;
Future<void> onImageInsertWithCropping( Future<void> onImageInsertWithCropping(
@ -65,7 +66,7 @@ class MyQuillToolbar extends StatelessWidget {
} }
Future<void> onImageInsert(String image, QuillController controller) async { Future<void> onImageInsert(String image, QuillController controller) async {
if (isWeb()) { if (isWeb() || isHttpBasedUrl(image)) {
controller.insertImageBlock(imageSource: image); controller.insertImageBlock(imageSource: image);
return; return;
} }
@ -98,132 +99,114 @@ class MyQuillToolbar extends StatelessWidget {
if (state.useCustomQuillToolbar) { if (state.useCustomQuillToolbar) {
// For more info // For more info
// https://github.com/singerdmx/flutter-quill/blob/master/doc/custom_toolbar.md // https://github.com/singerdmx/flutter-quill/blob/master/doc/custom_toolbar.md
return QuillBaseToolbar( return QuillToolbar(
configurations: QuillBaseToolbarConfigurations( configurations: const QuillToolbarConfigurations(
toolbarSize: 15 * 2, buttonOptions: QuillToolbarButtonOptions(
multiRowsDisplay: false,
buttonOptions: const QuillToolbarButtonOptions(
base: QuillToolbarBaseButtonOptions( base: QuillToolbarBaseButtonOptions(
globalIconSize: 30, globalIconSize: 20,
globalIconButtonFactor: 1.4,
), ),
), ),
childrenBuilder: (context) { ),
final controller = context.requireQuillController; child: SingleChildScrollView(
return [ scrollDirection: Axis.horizontal,
QuillToolbarImageButton( child: Row(
controller: controller, children: [
options: const QuillToolbarImageButtonOptions(), IconButton(
onPressed: () => context
.read<SettingsCubit>()
.updateSettings(
state.copyWith(useCustomQuillToolbar: false)),
icon: const Icon(
Icons.width_normal,
),
), ),
QuillToolbarHistoryButton( QuillToolbarHistoryButton(
isUndo: true,
controller: controller, controller: controller,
options:
const QuillToolbarHistoryButtonOptions(isUndo: true),
), ),
QuillToolbarHistoryButton( QuillToolbarHistoryButton(
isUndo: false,
controller: controller, controller: controller,
options:
const QuillToolbarHistoryButtonOptions(isUndo: false),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.bold, options: const QuillToolbarToggleStyleButtonOptions(),
controller: controller, controller: controller,
options: QuillToolbarToggleStyleButtonOptions( attribute: Attribute.bold,
childBuilder: (options, extraOptions) {
if (extraOptions.isToggled) {
return IconButton.filled(
onPressed: extraOptions.onPressed,
icon: Icon(options.iconData),
);
}
return IconButton(
onPressed: extraOptions.onPressed,
icon: Icon(options.iconData),
);
},
),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.italic, options: const QuillToolbarToggleStyleButtonOptions(),
controller: controller, controller: controller,
options: const QuillToolbarToggleStyleButtonOptions( attribute: Attribute.italic,
iconData: Icons.format_italic,
),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.underline,
controller: controller, controller: controller,
options: const QuillToolbarToggleStyleButtonOptions( attribute: Attribute.underline,
iconData: Icons.format_underline,
iconSize: 20,
),
), ),
QuillToolbarClearFormatButton( QuillToolbarClearFormatButton(
controller: controller, controller: controller,
options: const QuillToolbarClearFormatButtonOptions(
iconData: Icons.format_clear,
),
), ),
VerticalDivider( const VerticalDivider(),
indent: 12, QuillToolbarImageButton(
endIndent: 12, controller: controller,
color: Colors.grey.shade400,
), ),
QuillToolbarSelectHeaderStyleButtons( QuillToolbarCameraButton(
controller: controller,
),
QuillToolbarVideoButton(
controller: controller,
),
const VerticalDivider(),
QuillToolbarColorButton(
controller: controller,
isBackground: false,
),
QuillToolbarColorButton(
controller: controller,
isBackground: true,
),
const VerticalDivider(),
QuillToolbarSelectHeaderStyleButton(
controller: controller,
),
const VerticalDivider(),
QuillToolbarToggleCheckListButton(
controller: controller, controller: controller,
options: const QuillToolbarSelectHeaderStyleButtonsOptions(
iconSize: 20,
),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.ol,
controller: controller, controller: controller,
options: const QuillToolbarToggleStyleButtonOptions( attribute: Attribute.ol,
iconData: Icons.format_list_numbered,
iconSize: 39,
),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.ul,
controller: controller, controller: controller,
options: const QuillToolbarToggleStyleButtonOptions( attribute: Attribute.ul,
iconData: Icons.format_list_bulleted,
),
), ),
QuillToolbarToggleStyleButton( QuillToolbarToggleStyleButton(
attribute: Attribute.blockQuote,
controller: controller, controller: controller,
options: const QuillToolbarToggleStyleButtonOptions( attribute: Attribute.inlineCode,
iconData: Icons.format_quote,
iconSize: 15,
),
), ),
VerticalDivider( QuillToolbarToggleStyleButton(
indent: 12, controller: controller,
endIndent: 12, attribute: Attribute.blockQuote,
color: Colors.grey.shade400,
), ),
QuillToolbarIndentButton( QuillToolbarIndentButton(
controller: controller, controller: controller,
isIncrease: true, isIncrease: true,
options: const QuillToolbarIndentButtonOptions( ),
iconData: Icons.format_indent_increase,
iconSize: 20,
)),
QuillToolbarIndentButton( QuillToolbarIndentButton(
controller: controller, controller: controller,
isIncrease: false, isIncrease: false,
options: const QuillToolbarIndentButtonOptions(
iconData: Icons.format_indent_decrease,
iconSize: 20,
),
), ),
]; const VerticalDivider(),
}, QuillToolbarLinkStyleButton(controller: controller),
],
),
), ),
); );
} }
return QuillToolbar( return QuillSimpleToolbar(
configurations: QuillToolbarConfigurations( configurations: QuillSimpleToolbarConfigurations(
controller: controller,
showAlignmentButtons: true, showAlignmentButtons: true,
buttonOptions: QuillToolbarButtonOptions( buttonOptions: QuillToolbarButtonOptions(
base: QuillToolbarBaseButtonOptions( base: QuillToolbarBaseButtonOptions(
@ -235,7 +218,6 @@ class MyQuillToolbar extends StatelessWidget {
QuillToolbarCustomButtonOptions( QuillToolbarCustomButtonOptions(
icon: const Icon(Icons.add_alarm_rounded), icon: const Icon(Icons.add_alarm_rounded),
onPressed: () { onPressed: () {
final controller = context.requireQuillController;
controller.document controller.document
.insert(controller.selection.extentOffset, '\n'); .insert(controller.selection.extentOffset, '\n');
controller.updateSelection( controller.updateSelection(
@ -279,13 +261,10 @@ class MyQuillToolbar extends StatelessWidget {
}, },
), ),
QuillToolbarCustomButtonOptions( QuillToolbarCustomButtonOptions(
icon: const Icon(Icons.ac_unit), icon: const Icon(Icons.dashboard_customize),
onPressed: () { onPressed: () {
ScaffoldMessenger.of(context) context.read<SettingsCubit>().updateSettings(
..clearSnackBars() state.copyWith(useCustomQuillToolbar: true));
..showText(
'Custom button!',
);
}, },
), ),
], ],

@ -4,14 +4,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill_extensions/flutter_quill_extensions.dart' import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'
show FlutterQuillEmbeds, QuillSharedExtensionsConfigurations; show FlutterQuillEmbeds, QuillSharedExtensionsConfigurations;
import 'package:quill_html_converter/quill_html_converter.dart'; import 'package:quill_html_converter/quill_html_converter.dart';
import 'package:share_plus/share_plus.dart' show Share; import 'package:share_plus/share_plus.dart' show Share;
import '../extensions/scaffold_messenger.dart'; import '../extensions/scaffold_messenger.dart';
import '../shared/widgets/home_screen_button.dart'; import '../shared/widgets/home_screen_button.dart';
import 'quill_editor.dart'; import 'my_quill_editor.dart';
import 'quill_toolbar.dart'; import 'my_quill_toolbar.dart';
@immutable @immutable
class QuillScreenArgs { class QuillScreenArgs {
@ -46,6 +45,18 @@ class _QuillScreenState extends State<QuillScreen> {
_controller.document = widget.args.document; _controller.document = widget.args.document;
} }
// Future<void> _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 @override
void dispose() { void dispose() {
_controller.dispose(); _controller.dispose();
@ -65,7 +76,7 @@ class _QuillScreenState extends State<QuillScreen> {
onPressed: () { onPressed: () {
final html = _controller.document.toDelta().toHtml(); final html = _controller.document.toDelta().toHtml();
_controller.document = _controller.document =
Document.fromDelta(DeltaHtmlExt.fromHtml(html)); Document.fromDelta(QuillController.fromHtml(html));
}, },
icon: const Icon(Icons.html), icon: const Icon(Icons.html),
), ),
@ -100,40 +111,43 @@ class _QuillScreenState extends State<QuillScreen> {
const HomeScreenButton(), const HomeScreenButton(),
], ],
), ),
body: QuillProvider( body: Column(
configurations: QuillConfigurations( children: [
controller: _controller, if (!_isReadOnly)
sharedConfigurations: QuillSharedConfigurations( MyQuillToolbar(
animationConfigurations: QuillAnimationConfigurations.disableAll(), controller: _controller,
extraConfigurations: const { focusNode: _editorFocusNode,
QuillSharedExtensionsConfigurations.key: ),
QuillSharedExtensionsConfigurations( Builder(
assetsPrefix: 'assets', builder: (context) {
), return Expanded(
}, child: MyQuillEditor(
), configurations: QuillEditorConfigurations(
), sharedConfigurations: _sharedConfigurations,
child: Column( controller: _controller,
children: [ readOnly: _isReadOnly,
if (!_isReadOnly) customStyles: const DefaultStyles(),
MyQuillToolbar( elementOptions: const QuillEditorElementOptions(
focusNode: _editorFocusNode, codeBlock: QuillEditorCodeBlockElementOptions(
), enableLineNumbers: true,
Builder( ),
builder: (context) { // orderedList: QuillEditorOrderedListElementOptions(
return Expanded( // backgroundColor: Colors.amber,
child: MyQuillEditor( // fontColor: Colors.black,
configurations: QuillEditorConfigurations( // ),
readOnly: _isReadOnly, // unorderedList: QuillEditorUnOrderedListElementOptions(
// backgroundColor: Colors.green,
// fontColor: Colors.red,
// ),
), ),
scrollController: _editorScrollController,
focusNode: _editorFocusNode,
), ),
); scrollController: _editorScrollController,
}, focusNode: _editorFocusNode,
), ),
], );
), },
),
],
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
child: Icon(_isReadOnly ? Icons.lock : Icons.edit), child: Icon(_isReadOnly ? Icons.lock : Icons.edit),
@ -141,4 +155,16 @@ class _QuillScreenState extends State<QuillScreen> {
), ),
); );
} }
QuillSharedConfigurations get _sharedConfigurations {
return const QuillSharedConfigurations(
// locale: Locale('en'),
extraConfigurations: {
QuillSharedExtensionsConfigurations.key:
QuillSharedExtensionsConfigurations(
assetsPrefix: 'assets', // Defaults to assets
),
},
);
}
} }

@ -5,11 +5,7 @@ final quillImagesSample = [
{'insert': '\n'}, {'insert': '\n'},
{ {
'insert': {'image': Assets.images.screenshot1.path}, 'insert': {'image': Assets.images.screenshot1.path},
'attributes': { 'attributes': {'style': 'width: 40vh; height:350px; margin: 20px;'}
'width': '200',
'height': '500',
'style': 'width:500px; height:350px; margin: 20px;'
}
}, },
{'insert': '\n'}, {'insert': '\n'},
{'insert': 'Here is a network image: \n'}, {'insert': 'Here is a network image: \n'},

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart';
class SimpleScreen extends StatefulWidget {
const SimpleScreen({super.key});
@override
State<SimpleScreen> createState() => _SimpleScreenState();
}
class _SimpleScreenState extends State<SimpleScreen> {
final _controller = QuillController.basic();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
QuillToolbar.simple(
configurations:
QuillSimpleToolbarConfigurations(controller: _controller),
),
Expanded(
child: QuillEditor.basic(
configurations: QuillEditorConfigurations(
controller: _controller,
padding: const EdgeInsets.all(16),
),
),
),
],
),
);
}
}

@ -8,7 +8,8 @@
#include <desktop_drop/desktop_drop_plugin.h> #include <desktop_drop/desktop_drop_plugin.h>
#include <file_selector_linux/file_selector_plugin.h> #include <file_selector_linux/file_selector_plugin.h>
#include <pasteboard/pasteboard_plugin.h> #include <irondash_engine_context/irondash_engine_context_plugin.h>
#include <super_native_extensions/super_native_extensions_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
@ -18,9 +19,12 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar); file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) pasteboard_registrar = g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin");
pasteboard_plugin_register_with_registrar(pasteboard_registrar); irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar);
g_autoptr(FlPluginRegistrar) super_native_extensions_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SuperNativeExtensionsPlugin");
super_native_extensions_plugin_register_with_registrar(super_native_extensions_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

@ -5,7 +5,8 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop desktop_drop
file_selector_linux file_selector_linux
pasteboard irondash_engine_context
super_native_extensions
url_launcher_linux url_launcher_linux
) )

@ -9,10 +9,11 @@ import desktop_drop
import device_info_plus import device_info_plus
import file_selector_macos import file_selector_macos
import gal import gal
import pasteboard import irondash_engine_context
import path_provider_foundation import path_provider_foundation
import share_plus import share_plus
import sqflite import sqflite
import super_native_extensions
import url_launcher_macos import url_launcher_macos
import video_player_avfoundation import video_player_avfoundation
@ -21,10 +22,11 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
} }

@ -12,7 +12,7 @@ PODS:
- gal (1.0.0): - gal (1.0.0):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- pasteboard (0.0.1): - irondash_engine_context (0.0.1):
- FlutterMacOS - FlutterMacOS
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
@ -22,6 +22,8 @@ PODS:
- sqflite (0.0.2): - sqflite (0.0.2):
- FlutterMacOS - FlutterMacOS
- FMDB (>= 2.7.5) - FMDB (>= 2.7.5)
- super_native_extensions (0.0.1):
- FlutterMacOS
- url_launcher_macos (0.0.1): - url_launcher_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- video_player_avfoundation (0.0.1): - video_player_avfoundation (0.0.1):
@ -34,10 +36,11 @@ DEPENDENCIES:
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- gal (from `Flutter/ephemeral/.symlinks/plugins/gal/darwin`) - gal (from `Flutter/ephemeral/.symlinks/plugins/gal/darwin`)
- pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`) - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
- super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`) - video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`)
@ -56,14 +59,16 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral :path: Flutter/ephemeral
gal: gal:
:path: Flutter/ephemeral/.symlinks/plugins/gal/darwin :path: Flutter/ephemeral/.symlinks/plugins/gal/darwin
pasteboard: irondash_engine_context:
:path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos :path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos
path_provider_foundation: path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
share_plus: share_plus:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
sqflite: sqflite:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
super_native_extensions:
:path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos
url_launcher_macos: url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
video_player_avfoundation: video_player_avfoundation:
@ -76,10 +81,11 @@ SPEC CHECKSUMS:
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1 gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1
pasteboard: 9b69dba6fedbb04866be632205d532fe2f6b1d99 irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7 share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
super_native_extensions: 85efee3a7495b46b04befcfc86ed12069264ebf3
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1 video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1

@ -13,8 +13,8 @@ dependencies:
cupertino_icons: ^1.0.6 cupertino_icons: ^1.0.6
# Flutter Quill Packages # Flutter Quill Packages
flutter_quill: ^8.6.2 flutter_quill: ^8.6.4
flutter_quill_extensions: ^0.7.0 flutter_quill_extensions: ^0.7.2
flutter_quill_test: ^0.0.5 flutter_quill_test: ^0.0.5
quill_html_converter: ^0.0.1-experimental.1 quill_html_converter: ^0.0.1-experimental.1
@ -24,11 +24,6 @@ dependencies:
cross_file: ^0.3.3+6 cross_file: ^0.3.3+6
cached_network_image: ^3.3.0 cached_network_image: ^3.3.0
gal_linux:
git:
url: https://github.com/freshtechtips/gal-linux.git
ref: main
# Bloc libraries # Bloc libraries
bloc: ^8.1.2 bloc: ^8.1.2
flutter_bloc: ^8.1.3 flutter_bloc: ^8.1.3
@ -49,6 +44,7 @@ dependencies:
file_picker: ^6.1.1 file_picker: ^6.1.1
# For sharing text # For sharing text
share_plus: ^7.2.1 share_plus: ^7.2.1
super_clipboard: ^0.7.3
dependency_overrides: dependency_overrides:
flutter_quill: flutter_quill:
@ -60,11 +56,6 @@ dependency_overrides:
quill_html_converter: quill_html_converter:
path: ../packages/quill_html_converter path: ../packages/quill_html_converter
gal:
git:
url: https://github.com/natsuk4ze/gal.git
ref: plugin_platform_interface
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

@ -9,8 +9,9 @@
#include <desktop_drop/desktop_drop_plugin.h> #include <desktop_drop/desktop_drop_plugin.h>
#include <file_selector_windows/file_selector_windows.h> #include <file_selector_windows/file_selector_windows.h>
#include <gal/gal_plugin_c_api.h> #include <gal/gal_plugin_c_api.h>
#include <pasteboard/pasteboard_plugin.h> #include <irondash_engine_context/irondash_engine_context_plugin_c_api.h>
#include <share_plus/share_plus_windows_plugin_c_api.h> #include <share_plus/share_plus_windows_plugin_c_api.h>
#include <super_native_extensions/super_native_extensions_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
@ -20,10 +21,12 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FileSelectorWindows")); registry->GetRegistrarForPlugin("FileSelectorWindows"));
GalPluginCApiRegisterWithRegistrar( GalPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GalPluginCApi")); registry->GetRegistrarForPlugin("GalPluginCApi"));
PasteboardPluginRegisterWithRegistrar( IrondashEngineContextPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PasteboardPlugin")); registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi"));
SharePlusWindowsPluginCApiRegisterWithRegistrar( SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
SuperNativeExtensionsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SuperNativeExtensionsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
} }

@ -6,8 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop desktop_drop
file_selector_windows file_selector_windows
gal gal
pasteboard irondash_engine_context
share_plus share_plus
super_native_extensions
url_launcher_windows url_launcher_windows
) )

File diff suppressed because it is too large Load Diff

@ -16,6 +16,7 @@ to support embedding widgets like images, formulas, videos, and more.
- [Embed Blocks](#embed-blocks) - [Embed Blocks](#embed-blocks)
- [Element properties](#element-properties) - [Element properties](#element-properties)
- [Custom Element properties](#custom-element-properties) - [Custom Element properties](#custom-element-properties)
- [Image Assets](#image-assets)
- [Drag and drop feature](#drag-and-drop-feature) - [Drag and drop feature](#drag-and-drop-feature)
- [Features](#features) - [Features](#features)
- [Contributing](#contributing) - [Contributing](#contributing)
@ -52,8 +53,7 @@ dependencies:
> >
> 1. We are using the [`gal`](https://github.com/natsuk4ze/) plugin to save images. > 1. We are using the [`gal`](https://github.com/natsuk4ze/) plugin to save images.
> For this to work, you need to add the appropriate permissions > For this to work, you need to add the appropriate configurations
> to your `Info.plist` and `AndroidManifest.xml` files.
> See <https://github.com/natsuk4ze/gal#-get-started> to add the needed lines. > See <https://github.com/natsuk4ze/gal#-get-started> to add the needed lines.
> >
> 2. We also use [`image_picker`](https://pub.dev/packages/image_picker) plugin for picking images so please make sure to follow the instructions > 2. We also use [`image_picker`](https://pub.dev/packages/image_picker) plugin for picking images so please make sure to follow the instructions
@ -165,6 +165,28 @@ Define flutterAlignment` as follows:
This works for all platforms except Web This works for all platforms except Web
### Image Assets
If you want to use image assets in the Quill Editor, you need to make sure your assets folder is `assets` otherwise:
```dart
QuillEditor.basic(
configurations: const QuillEditorConfigurations(
// ...
sharedConfigurations: QuillSharedConfigurations(
extraConfigurations: {
QuillSharedExtensionsConfigurations.key:
QuillSharedExtensionsConfigurations(
assetsPrefix: 'your-assets-folder-name', // Defaults to `assets`
),
},
),
),
);
```
This info is needed by the package to check if it asset image to use the `AssetImage` provider
### Drag and drop feature ### Drag and drop feature
Currently, the drag-and-drop feature is not officially supported, but you can achieve this very easily in the following steps: Currently, the drag-and-drop feature is not officially supported, but you can achieve this very easily in the following steps:

@ -6,7 +6,7 @@ import '../../../models/config/toolbar/buttons/formula.dart';
class QuillToolbarFormulaButton extends StatelessWidget { class QuillToolbarFormulaButton extends StatelessWidget {
const QuillToolbarFormulaButton({ const QuillToolbarFormulaButton({
required this.controller, required this.controller,
required this.options, this.options = const QuillToolbarFormulaButtonOptions(),
super.key, super.key,
}); });
@ -71,14 +71,11 @@ class QuillToolbarFormulaButton extends StatelessWidget {
options.childBuilder ?? baseButtonExtraOptions(context).childBuilder; options.childBuilder ?? baseButtonExtraOptions(context).childBuilder;
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color; final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor = iconTheme?.iconUnselectedFillColor ??
(options.fillColor ?? theme.canvasColor);
if (childBuilder != null) { if (childBuilder != null) {
return childBuilder( return childBuilder(
QuillToolbarFormulaButtonOptions( QuillToolbarFormulaButtonOptions(
afterButtonPressed: _afterButtonPressed(context), afterButtonPressed: _afterButtonPressed(context),
fillColor: iconFillColor,
iconData: iconData, iconData: iconData,
iconSize: iconSize, iconSize: iconSize,
iconButtonFactor: iconButtonFactor, iconButtonFactor: iconButtonFactor,
@ -94,14 +91,10 @@ class QuillToolbarFormulaButton extends StatelessWidget {
} }
return QuillToolbarIconButton( return QuillToolbarIconButton(
icon: Icon(iconData, size: iconSize, color: iconColor), icon: Icon(iconData, size: iconSize * iconButtonFactor, color: iconColor),
tooltip: tooltip, tooltip: tooltip,
highlightElevation: 0,
hoverElevation: 0,
size: iconSize * 1.77,
fillColor: iconFillColor,
borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: () => _sharedOnPressed(context), onPressed: () => _sharedOnPressed(context),
isFilled: false,
); );
} }

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart' hide OptionalSize; import 'package:flutter_quill/flutter_quill.dart' hide OptionalSize;
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
@ -30,15 +29,19 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
bool inline, bool inline,
TextStyle textStyle, TextStyle textStyle,
) { ) {
assert(!kIsWeb, 'Please provide image EmbedBuilder for Web'); // assert(!kIsWeb, 'Please provide image EmbedBuilder for Web');
final imageSource = standardizeImageUrl(node.value.data); final imageSource = standardizeImageUrl(node.value.data);
final ((imageSize), margin, alignment) = getElementAttributes(node); final ((imageSize), margin, alignment) = getElementAttributes(
node,
context,
);
final width = imageSize.width; final width = imageSize.width;
final height = imageSize.height; final height = imageSize.height;
final image = getImageWidgetByImageSource( final image = getImageWidgetByImageSource(
context: context,
imageSource, imageSource,
imageProviderBuilder: configurations.imageProviderBuilder, imageProviderBuilder: configurations.imageProviderBuilder,
imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder, imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder,
@ -56,17 +59,14 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
onTap: configurations.onImageClicked ?? onTap: configurations.onImageClicked ??
() => showDialog( () => showDialog(
context: context, context: context,
builder: (_) => QuillProvider.value( builder: (_) => FlutterQuillLocalizationsWidget(
value: context.requireQuillProvider, child: ImageOptionsMenu(
child: FlutterQuillLocalizationsWidget( controller: controller,
child: ImageOptionsMenu( configurations: configurations,
controller: controller, imageSource: imageSource,
configurations: configurations, imageSize: imageSize,
imageSource: imageSource, isReadOnly: readOnly,
imageSize: imageSize, imageSaverService: imageSaverService,
isReadOnly: readOnly,
imageSaverService: imageSaverService,
),
), ),
), ),
), ),

@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart' show BuildContext;
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import 'package:meta/meta.dart' show immutable; import 'package:meta/meta.dart' show immutable;
import '../../../extensions/controller.dart'; import '../../../extensions/controller_ext.dart';
import '../../../services/image_picker/s_image_picker.dart'; import '../../../services/image_picker/s_image_picker.dart';
/// When request picking an image, for example when the image button toolbar /// When request picking an image, for example when the image button toolbar
@ -76,6 +76,7 @@ typedef ImageEmbedBuilderOnRemovedCallback = Future<void> Function(
); );
typedef ImageEmbedBuilderProviderBuilder = ImageProvider Function( typedef ImageEmbedBuilderProviderBuilder = ImageProvider Function(
BuildContext context,
String imageUrl, String imageUrl,
); );

@ -1,14 +1,10 @@
import 'package:flutter/cupertino.dart' show showCupertinoModalPopup; import 'package:flutter/cupertino.dart' show showCupertinoModalPopup;
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart' import 'package:flutter_quill/flutter_quill.dart'
show show ImageUrl, QuillController, StyleAttribute, getEmbedNode;
ImageUrl,
QuillController,
QuillProvider,
QuillProviderExt,
StyleAttribute,
getEmbedNode;
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
import 'package:super_clipboard/super_clipboard.dart';
import '../../../models/config/editor/image/image.dart'; import '../../../models/config/editor/image/image.dart';
import '../../../models/config/shared_configurations.dart'; import '../../../models/config/shared_configurations.dart';
@ -55,34 +51,31 @@ class ImageOptionsMenu extends StatelessWidget {
context: context, context: context,
builder: (modalContext) { builder: (modalContext) {
final screenSize = MediaQuery.sizeOf(modalContext); final screenSize = MediaQuery.sizeOf(modalContext);
return QuillProvider.value( return FlutterQuillLocalizationsWidget(
value: context.requireQuillProvider, child: ImageResizer(
child: FlutterQuillLocalizationsWidget( onImageResize: (width, height) {
child: ImageResizer( final res = getEmbedNode(
onImageResize: (width, height) { controller,
final res = getEmbedNode( controller.selection.start,
controller, );
controller.selection.start,
);
final attr = replaceStyleStringWithSize( final attr = replaceStyleStringWithSize(
getImageStyleString(controller), getImageStyleString(controller),
width: width, width: width,
height: height, height: height,
);
controller
..skipRequestKeyboard = true
..formatText(
res.offset,
1,
StyleAttribute(attr),
); );
controller },
..skipRequestKeyboard = true imageWidth: imageSize.width,
..formatText( imageHeight: imageSize.height,
res.offset, maxWidth: screenSize.width,
1, maxHeight: screenSize.height,
StyleAttribute(attr),
);
},
imageWidth: imageSize.width,
imageHeight: imageSize.height,
maxWidth: screenSize.width,
maxHeight: screenSize.height,
),
), ),
); );
}, },
@ -96,15 +89,17 @@ class ImageOptionsMenu extends StatelessWidget {
final navigator = Navigator.of(context); final navigator = Navigator.of(context);
final imageNode = final imageNode =
getEmbedNode(controller, controller.selection.start).value; getEmbedNode(controller, controller.selection.start).value;
final imageUrl = imageNode.value.data; final image = imageNode.value.data;
controller.copiedImageUrl = ImageUrl( controller.copiedImageUrl = ImageUrl(
imageUrl, image,
getImageStyleString(controller), getImageStyleString(controller),
); );
// TODO: Implement the copy image
// await Clipboard.setData( final data = await convertImageToUint8List(image);
// ClipboardData(), if (data != null) {
// ); final item = DataWriterItem()..add(Formats.png(data));
await ClipboardWriter.instance.write([item]);
}
navigator.pop(); navigator.pop();
}, },
), ),
@ -139,7 +134,7 @@ class ImageOptionsMenu extends StatelessWidget {
await configurations.onImageRemovedCallback.call(imageSource); await configurations.onImageRemovedCallback.call(imageSource);
}, },
), ),
...[ if (!kIsWeb)
ListTile( ListTile(
leading: const Icon(Icons.save), leading: const Icon(Icons.save),
title: Text(context.loc.save), title: Text(context.loc.save),
@ -181,23 +176,22 @@ class ImageOptionsMenu extends StatelessWidget {
); );
}, },
), ),
ListTile( ListTile(
leading: const Icon(Icons.zoom_in), leading: const Icon(Icons.zoom_in),
title: Text(context.loc.zoom), title: Text(context.loc.zoom),
onTap: () => Navigator.pushReplacement( onTap: () => Navigator.pushReplacement(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (_) => ImageTapWrapper( builder: (_) => ImageTapWrapper(
assetsPrefix: QuillSharedExtensionsConfigurations.get( assetsPrefix:
context: context) QuillSharedExtensionsConfigurations.get(context: context)
.assetsPrefix, .assetsPrefix,
imageUrl: imageSource, imageUrl: imageSource,
configurations: configurations, configurations: configurations,
),
), ),
), ),
), ),
], ),
], ],
), ),
); );

@ -14,7 +14,7 @@ import 'select_image_source.dart';
class QuillToolbarImageButton extends StatelessWidget { class QuillToolbarImageButton extends StatelessWidget {
const QuillToolbarImageButton({ const QuillToolbarImageButton({
required this.controller, required this.controller,
required this.options, this.options = const QuillToolbarImageButtonOptions(),
super.key, super.key,
}); });
@ -101,21 +101,15 @@ class QuillToolbarImageButton extends StatelessWidget {
final iconTheme = _iconTheme(context); final iconTheme = _iconTheme(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color; final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor = iconTheme?.iconUnselectedFillColor ??
(options.fillColor ?? theme.canvasColor);
return QuillToolbarIconButton( return QuillToolbarIconButton(
icon: Icon( icon: Icon(
iconData, iconData,
size: iconSize, size: iconButtonFactor * iconSize,
color: iconColor, color: iconColor,
), ),
tooltip: tooltip, tooltip: tooltip,
highlightElevation: 0, isFilled: false,
hoverElevation: 0,
size: iconSize * 1.77,
fillColor: iconFillColor,
borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: () => _sharedOnPressed(context), onPressed: () => _sharedOnPressed(context),
); );
} }
@ -172,14 +166,11 @@ class QuillToolbarImageButton extends StatelessWidget {
Future<String?> _typeLink(BuildContext context) async { Future<String?> _typeLink(BuildContext context) async {
final value = await showDialog<String>( final value = await showDialog<String>(
context: context, context: context,
builder: (_) => QuillProvider.value( builder: (_) => FlutterQuillLocalizationsWidget(
value: context.requireQuillProvider, child: TypeLinkDialog(
child: FlutterQuillLocalizationsWidget( dialogTheme: options.dialogTheme,
child: TypeLinkDialog( linkRegExp: options.linkRegExp,
dialogTheme: options.dialogTheme, linkType: LinkType.image,
linkRegExp: options.linkRegExp,
linkType: LinkType.image,
),
), ),
), ),
); );

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_quill/extensions.dart' show isDesktop; import 'package:flutter_quill/extensions.dart' show isDesktop;
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
import '../editor/image_embed_types.dart'; import '../editor/image_embed_types.dart';
@ -55,11 +54,8 @@ Future<InsertImageSource?> showSelectImageSourceDialog({
showDragHandle: true, showDragHandle: true,
context: context, context: context,
constraints: const BoxConstraints(maxWidth: 640), constraints: const BoxConstraints(maxWidth: 640),
builder: (_) => QuillProvider.value( builder: (_) => const FlutterQuillLocalizationsWidget(
value: context.requireQuillProvider, child: SelectImageSourceDialog(),
child: const FlutterQuillLocalizationsWidget(
child: SelectImageSourceDialog(),
),
), ),
); );
return imageSource; return imageSource;

@ -3,7 +3,7 @@ import 'package:flutter_quill/flutter_quill.dart'
show show
QuillController, QuillController,
QuillIconTheme, QuillIconTheme,
QuillProviderExt, QuillSimpleToolbarExt,
QuillToolbarBaseButtonOptions, QuillToolbarBaseButtonOptions,
QuillToolbarIconButton; QuillToolbarIconButton;
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
@ -17,7 +17,7 @@ import 'select_camera_action.dart';
class QuillToolbarCameraButton extends StatelessWidget { class QuillToolbarCameraButton extends StatelessWidget {
const QuillToolbarCameraButton({ const QuillToolbarCameraButton({
required this.controller, required this.controller,
required this.options, this.options = const QuillToolbarCameraButtonOptions(),
super.key, super.key,
}); });
@ -30,6 +30,13 @@ class QuillToolbarCameraButton extends StatelessWidget {
return iconSize ?? baseFontSize; return iconSize ?? baseFontSize;
} }
double _iconButtonFactor(BuildContext context) {
final baseIconFactor =
baseButtonExtraOptions(context).globalIconButtonFactor;
final iconButtonFactor = options.iconButtonFactor;
return iconButtonFactor ?? baseIconFactor;
}
VoidCallback? _afterButtonPressed(BuildContext context) { VoidCallback? _afterButtonPressed(BuildContext context) {
return options.afterButtonPressed ?? return options.afterButtonPressed ??
baseButtonExtraOptions(context).afterButtonPressed; baseButtonExtraOptions(context).afterButtonPressed;
@ -69,6 +76,7 @@ class QuillToolbarCameraButton extends StatelessWidget {
final tooltip = _tooltip(context); final tooltip = _tooltip(context);
final iconSize = _iconSize(context); final iconSize = _iconSize(context);
final iconData = _iconData(context); final iconData = _iconData(context);
final iconButtonFactor = _iconButtonFactor(context);
final childBuilder = final childBuilder =
options.childBuilder ?? baseButtonExtraOptions(context).childBuilder; options.childBuilder ?? baseButtonExtraOptions(context).childBuilder;
@ -80,7 +88,7 @@ class QuillToolbarCameraButton extends StatelessWidget {
iconData: options.iconData, iconData: options.iconData,
fillColor: options.fillColor, fillColor: options.fillColor,
iconSize: options.iconSize, iconSize: options.iconSize,
iconButtonFactor: options.iconButtonFactor, iconButtonFactor: iconButtonFactor,
iconTheme: options.iconTheme, iconTheme: options.iconTheme,
tooltip: options.tooltip, tooltip: options.tooltip,
cameraConfigurations: options.cameraConfigurations, cameraConfigurations: options.cameraConfigurations,
@ -96,17 +104,11 @@ class QuillToolbarCameraButton extends StatelessWidget {
final theme = Theme.of(context); final theme = Theme.of(context);
final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color; final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color;
final iconFillColor = iconTheme?.iconUnselectedFillColor ??
(options.fillColor ?? theme.canvasColor);
return QuillToolbarIconButton( return QuillToolbarIconButton(
icon: Icon(iconData, size: iconSize, color: iconColor), icon: Icon(iconData, size: iconButtonFactor * iconSize, color: iconColor),
tooltip: tooltip, tooltip: tooltip,
highlightElevation: 0, isFilled: false,
hoverElevation: 0,
size: iconSize * 1.77,
fillColor: iconFillColor,
borderRadius: iconTheme?.borderRadius ?? 2,
// isDesktop(supportWeb: false) ? null : // isDesktop(supportWeb: false) ? null :
onPressed: () => _sharedOnPressed(context), onPressed: () => _sharedOnPressed(context),
); );
@ -118,9 +120,8 @@ class QuillToolbarCameraButton extends StatelessWidget {
if (customCallback != null) { if (customCallback != null) {
return await customCallback(context); return await customCallback(context);
} }
final cameraAction = await showDialog<CameraAction>( final cameraAction = await showSelectCameraActionDialog(
context: context, context: context,
builder: (ctx) => const SelectCameraActionDialog(),
); );
return cameraAction; return cameraAction;
@ -168,12 +169,5 @@ class QuillToolbarCameraButton extends StatelessWidget {
await options.cameraConfigurations.onImageInsertedCallback await options.cameraConfigurations.onImageInsertedCallback
?.call(imageFile.path); ?.call(imageFile.path);
} }
// final file = await switch (cameraAction) {
// CameraAction.image =>
// imagePickerService.pickImage(source: ImageSource.camera),
// CameraAction.video =>
// imagePickerService.pickVideo(source: ImageSource.camera),
// };
} }
} }

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_quill/extensions.dart';
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
import 'camera_types.dart'; import 'camera_types.dart';
@ -8,27 +9,46 @@ class SelectCameraActionDialog extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return SizedBox(
contentPadding: EdgeInsets.zero, height: 150,
content: Column( width: double.infinity,
mainAxisSize: MainAxisSize.min, child: SingleChildScrollView(
children: [ child: Column(
TextButton.icon( children: [
icon: const Icon( ListTile(
Icons.camera, title: Text(context.loc.photo),
subtitle: Text(
context.loc.takeAPhotoUsingYourCamera,
),
leading: const Icon(Icons.photo_sharp),
enabled: !isDesktop(supportWeb: false),
onTap: () => Navigator.of(context).pop(CameraAction.image),
), ),
label: Text(context.loc.photo), ListTile(
onPressed: () => Navigator.pop(context, CameraAction.image), title: Text(context.loc.video),
), subtitle: Text(
TextButton.icon( context.loc.recordAVideoUsingYourCamera,
icon: const Icon( ),
Icons.video_call, leading: const Icon(Icons.camera),
enabled: !isDesktop(supportWeb: false),
onTap: () => Navigator.of(context).pop(CameraAction.video),
), ),
label: Text(context.loc.video), ],
onPressed: () => Navigator.pop(context, CameraAction.video), ),
)
],
), ),
); );
} }
} }
Future<CameraAction?> showSelectCameraActionDialog({
required BuildContext context,
}) async {
final imageSource = await showModalBottomSheet<CameraAction>(
showDragHandle: true,
context: context,
constraints: const BoxConstraints(maxWidth: 640),
builder: (context) => const FlutterQuillLocalizationsWidget(
child: SelectCameraActionDialog()),
);
return imageSource;
}

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart' show QuillDialogTheme; import 'package:flutter_quill/flutter_quill.dart' show QuillDialogTheme;
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
import '../../utils/patterns.dart';
enum LinkType { enum LinkType {
video, video,
image, image,
@ -28,7 +30,7 @@ class TypeLinkDialog extends StatefulWidget {
class TypeLinkDialogState extends State<TypeLinkDialog> { class TypeLinkDialogState extends State<TypeLinkDialog> {
late String _link; late String _link;
late TextEditingController _controller; late TextEditingController _controller;
late RegExp _linkRegExp; RegExp? _linkRegExp;
@override @override
void initState() { void initState() {
@ -36,15 +38,7 @@ class TypeLinkDialogState extends State<TypeLinkDialog> {
_link = widget.link ?? ''; _link = widget.link ?? '';
_controller = TextEditingController(text: _link); _controller = TextEditingController(text: _link);
final defaultLinkNonSecureRegExp = RegExp( _linkRegExp = widget.linkRegExp;
r'https?://.*?\.(?:png|jpe?g|gif|bmp|webp|tiff?)',
caseSensitive: false,
); // Not secure
// final defaultLinkRegExp = RegExp(
// r'https://.*?\.(?:png|jpe?g|gif|bmp|webp|tiff?)',
// caseSensitive: false,
// ); // Secure
_linkRegExp = widget.linkRegExp ?? defaultLinkNonSecureRegExp;
} }
@override @override
@ -102,8 +96,28 @@ class TypeLinkDialogState extends State<TypeLinkDialog> {
Navigator.pop(context, _link.trim()); Navigator.pop(context, _link.trim());
} }
RegExp get linkRegExp {
final customRegExp = _linkRegExp;
if (customRegExp != null) {
return customRegExp;
}
switch (widget.linkType) {
case LinkType.video:
if (youtubeRegExp.hasMatch(_link)) {
return youtubeRegExp;
}
return videoRegExp;
case LinkType.image:
return imageRegExp;
}
}
bool _canPress() { bool _canPress() {
return _link.isNotEmpty && _linkRegExp.hasMatch(_link); if (_link.isEmpty) {
return false;
}
if (widget.linkType == LinkType.image) {}
return _link.isNotEmpty && linkRegExp.hasMatch(_link);
} }
} }

@ -20,7 +20,7 @@
// class QuillToolbarMediaButton extends StatelessWidget { // class QuillToolbarMediaButton extends StatelessWidget {
// QuillToolbarMediaButton({ // QuillToolbarMediaButton({
// required this.controller, // required this.controller,
// required this.options, // this.options,
// super.key, // super.key,
// }) : assert(options.type == QuillMediaType.image, // }) : assert(options.type == QuillMediaType.image,
// 'Video selection is not supported yet'); // 'Video selection is not supported yet');
@ -135,7 +135,7 @@
// tooltip: tooltip, // tooltip: tooltip,
// highlightElevation: 0, // highlightElevation: 0,
// hoverElevation: 0, // hoverElevation: 0,
// size: iconSize * 1.77, // size: iconSize * iconButtonFactor,
// fillColor: iconFillColor, // fillColor: iconFillColor,
// borderRadius: iconTheme?.borderRadius ?? 2, // borderRadius: iconTheme?.borderRadius ?? 2,
// onPressed: () => _sharedOnPressed(context), // onPressed: () => _sharedOnPressed(context),

@ -37,7 +37,10 @@ class QuillEditorVideoEmbedBuilder extends EmbedBuilder {
readOnly: readOnly, readOnly: readOnly,
); );
} }
final ((elementSize), margin, alignment) = getElementAttributes(node); final ((elementSize), margin, alignment) = getElementAttributes(
node,
context,
);
final width = elementSize.width; final width = elementSize.width;
final height = elementSize.height; final height = elementSize.height;

@ -52,7 +52,8 @@ Future<InsertVideoSource?> showSelectVideoSourceDialog({
showDragHandle: true, showDragHandle: true,
context: context, context: context,
constraints: const BoxConstraints(maxWidth: 640), constraints: const BoxConstraints(maxWidth: 640),
builder: (context) => const SelectVideoSourceDialog(), builder: (context) =>
const FlutterQuillLocalizationsWidget(child: SelectVideoSourceDialog()),
); );
return imageSource; return imageSource;
} }

@ -13,8 +13,8 @@ import 'select_video_source.dart';
class QuillToolbarVideoButton extends StatelessWidget { class QuillToolbarVideoButton extends StatelessWidget {
const QuillToolbarVideoButton({ const QuillToolbarVideoButton({
required this.options,
required this.controller, required this.controller,
this.options = const QuillToolbarVideoButtonOptions(),
super.key, super.key,
}); });
@ -28,6 +28,13 @@ class QuillToolbarVideoButton extends StatelessWidget {
return iconSize ?? baseFontSize; return iconSize ?? baseFontSize;
} }
double _iconButtonFactor(BuildContext context) {
final baseIconFactor =
baseButtonExtraOptions(context).globalIconButtonFactor;
final iconButtonFactor = options.iconButtonFactor;
return iconButtonFactor ?? baseIconFactor;
}
VoidCallback? _afterButtonPressed(BuildContext context) { VoidCallback? _afterButtonPressed(BuildContext context) {
return options.afterButtonPressed ?? return options.afterButtonPressed ??
baseButtonExtraOptions(context).afterButtonPressed; baseButtonExtraOptions(context).afterButtonPressed;
@ -67,6 +74,7 @@ class QuillToolbarVideoButton extends StatelessWidget {
final tooltip = _tooltip(context); final tooltip = _tooltip(context);
final iconSize = _iconSize(context); final iconSize = _iconSize(context);
final iconButtonFactor = _iconButtonFactor(context);
final iconData = _iconData(context); final iconData = _iconData(context);
final childBuilder = final childBuilder =
options.childBuilder ?? baseButtonExtraOptions(context).childBuilder; options.childBuilder ?? baseButtonExtraOptions(context).childBuilder;
@ -83,7 +91,7 @@ class QuillToolbarVideoButton extends StatelessWidget {
dialogTheme: options.dialogTheme, dialogTheme: options.dialogTheme,
fillColor: iconFillColor, fillColor: iconFillColor,
iconSize: options.iconSize, iconSize: options.iconSize,
iconButtonFactor: options.iconButtonFactor, iconButtonFactor: iconButtonFactor,
linkRegExp: options.linkRegExp, linkRegExp: options.linkRegExp,
tooltip: options.tooltip, tooltip: options.tooltip,
iconTheme: options.iconTheme, iconTheme: options.iconTheme,
@ -98,13 +106,9 @@ class QuillToolbarVideoButton extends StatelessWidget {
} }
return QuillToolbarIconButton( return QuillToolbarIconButton(
icon: Icon(iconData, size: iconSize, color: iconColor), icon: Icon(iconData, size: iconSize * iconButtonFactor, color: iconColor),
tooltip: tooltip, tooltip: tooltip,
highlightElevation: 0, isFilled: false,
hoverElevation: 0,
size: iconSize * 1.77,
fillColor: iconFillColor,
borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: () => _sharedOnPressed(context), onPressed: () => _sharedOnPressed(context),
); );
} }
@ -165,13 +169,10 @@ class QuillToolbarVideoButton extends StatelessWidget {
Future<String?> _typeLink(BuildContext context) async { Future<String?> _typeLink(BuildContext context) async {
final value = await showDialog<String>( final value = await showDialog<String>(
context: context, context: context,
builder: (_) => QuillProvider.value( builder: (_) => FlutterQuillLocalizationsWidget(
value: context.requireQuillProvider, child: TypeLinkDialog(
child: FlutterQuillLocalizationsWidget( dialogTheme: options.dialogTheme,
child: TypeLinkDialog( linkType: LinkType.video,
dialogTheme: options.dialogTheme,
linkType: LinkType.video,
),
), ),
), ),
); );

@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart' show BuildContext;
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import 'package:meta/meta.dart' show immutable; import 'package:meta/meta.dart' show immutable;
import '../../extensions/controller.dart'; import '../../extensions/controller_ext.dart';
import '../../services/image_picker/s_image_picker.dart'; import '../../services/image_picker/s_image_picker.dart';
/// When request picking an video, for example when the video button toolbar /// When request picking an video, for example when the video button toolbar

@ -36,9 +36,10 @@ ImageProvider getImageProviderByImageSource(
String imageSource, { String imageSource, {
required ImageEmbedBuilderProviderBuilder? imageProviderBuilder, required ImageEmbedBuilderProviderBuilder? imageProviderBuilder,
required String assetsPrefix, required String assetsPrefix,
required BuildContext context,
}) { }) {
if (imageProviderBuilder != null) { if (imageProviderBuilder != null) {
return imageProviderBuilder(imageSource); return imageProviderBuilder(context, imageSource);
} }
if (isImageBase64(imageSource)) { if (isImageBase64(imageSource)) {
@ -50,7 +51,6 @@ ImageProvider getImageProviderByImageSource(
} }
if (imageSource.startsWith(assetsPrefix)) { if (imageSource.startsWith(assetsPrefix)) {
// TODO: This impl could be improved
return AssetImage(imageSource); return AssetImage(imageSource);
} }
return FileImage(File(imageSource)); return FileImage(File(imageSource));
@ -58,6 +58,7 @@ ImageProvider getImageProviderByImageSource(
Image getImageWidgetByImageSource( Image getImageWidgetByImageSource(
String imageSource, { String imageSource, {
required BuildContext context,
required ImageEmbedBuilderProviderBuilder? imageProviderBuilder, required ImageEmbedBuilderProviderBuilder? imageProviderBuilder,
required ImageErrorWidgetBuilder? imageErrorWidgetBuilder, required ImageErrorWidgetBuilder? imageErrorWidgetBuilder,
required String assetsPrefix, required String assetsPrefix,
@ -67,6 +68,7 @@ Image getImageWidgetByImageSource(
}) { }) {
return Image( return Image(
image: getImageProviderByImageSource( image: getImageProviderByImageSource(
context: context,
imageSource, imageSource,
imageProviderBuilder: imageProviderBuilder, imageProviderBuilder: imageProviderBuilder,
assetsPrefix: assetsPrefix, assetsPrefix: assetsPrefix,
@ -127,6 +129,7 @@ class ImageTapWrapper extends StatelessWidget {
children: [ children: [
PhotoView( PhotoView(
imageProvider: getImageProviderByImageSource( imageProvider: getImageProviderByImageSource(
context: context,
imageUrl, imageUrl,
imageProviderBuilder: configurations.imageProviderBuilder, imageProviderBuilder: configurations.imageProviderBuilder,
assetsPrefix: assetsPrefix, assetsPrefix: assetsPrefix,

@ -36,7 +36,7 @@ export 'embeds/video/editor/video_embed.dart';
export 'embeds/video/editor/video_web_embed.dart'; export 'embeds/video/editor/video_web_embed.dart';
export 'embeds/video/toolbar/video_button.dart'; export 'embeds/video/toolbar/video_button.dart';
export 'embeds/video/video.dart'; export 'embeds/video/video.dart';
export 'extensions/controller.dart'; export 'extensions/controller_ext.dart';
export 'models/config/editor/image/image.dart'; export 'models/config/editor/image/image.dart';
export 'models/config/editor/image/image_web.dart'; export 'models/config/editor/image/image_web.dart';
export 'models/config/editor/video/video.dart'; export 'models/config/editor/video/video.dart';
@ -113,8 +113,8 @@ class FlutterQuillEmbeds {
/// videos iframe on the web. /// videos iframe on the web.
/// ///
static List<EmbedBuilder> editorWebBuilders( static List<EmbedBuilder> editorWebBuilders(
{QuillEditorWebImageEmbedConfigurations? imageEmbedConfigurations = {QuillEditorImageEmbedConfigurations? imageEmbedConfigurations =
const QuillEditorWebImageEmbedConfigurations(), const QuillEditorImageEmbedConfigurations(),
QuillEditorWebVideoEmbedConfigurations? videoEmbedConfigurations = QuillEditorWebVideoEmbedConfigurations? videoEmbedConfigurations =
const QuillEditorWebVideoEmbedConfigurations()}) { const QuillEditorWebVideoEmbedConfigurations()}) {
if (!kIsWeb) { if (!kIsWeb) {
@ -125,7 +125,7 @@ class FlutterQuillEmbeds {
} }
return [ return [
if (imageEmbedConfigurations != null) if (imageEmbedConfigurations != null)
QuillEditorWebImageEmbedBuilder( QuillEditorImageEmbedBuilder(
configurations: imageEmbedConfigurations, configurations: imageEmbedConfigurations,
), ),
if (videoEmbedConfigurations != null) if (videoEmbedConfigurations != null)

@ -5,34 +5,8 @@ import 'package:meta/meta.dart' show immutable;
import '../../services/image_picker/s_image_picker.dart'; import '../../services/image_picker/s_image_picker.dart';
import '../../services/image_saver/s_image_saver.dart'; import '../../services/image_saver/s_image_saver.dart';
/// Configurations for Flutter Quill Extensions /// Configurations for Flutter Editor Extensions
/// that is shared between the toolbar and editor for the extensions package /// shared between toolbar and editor
///
/// Example on how to setup it:
///
/// ```dart
/// QuillProvider(
/// configurations: QuillConfigurations(
/// sharedConfigurations: const QuillSharedConfigurations(
/// extraConfigurations: {
/// QuillSharedExtensionsConfigurations.key:
/// QuillSharedExtensionsConfigurations(
/// // Feel free to explore it
/// ),
/// },
/// ),
/// controller: _controller,
/// ),
/// child: const Column(
/// children: [
/// // QuillToolbar
/// // QuillEditor
/// // ...
/// ],
// ),
/// )
/// ```
///
@immutable @immutable
class QuillSharedExtensionsConfigurations { class QuillSharedExtensionsConfigurations {
const QuillSharedExtensionsConfigurations({ const QuillSharedExtensionsConfigurations({
@ -47,17 +21,15 @@ class QuillSharedExtensionsConfigurations {
factory QuillSharedExtensionsConfigurations.get({ factory QuillSharedExtensionsConfigurations.get({
required BuildContext context, required BuildContext context,
}) { }) {
final quillSharedExtensionsConfigurations = final value = context.quillSharedConfigurations?.extraConfigurations[key];
context.requireQuillSharedConfigurations.extraConfigurations[key]; if (value != null) {
if (quillSharedExtensionsConfigurations != null) { if (value is! QuillSharedExtensionsConfigurations) {
if (quillSharedExtensionsConfigurations
is! QuillSharedExtensionsConfigurations) {
throw ArgumentError( throw ArgumentError(
'The value of key `$key` should be of type ' 'The value of key `$key` should be of type '
'QuillSharedExtensionsConfigurations', '$key',
); );
} }
return quillSharedExtensionsConfigurations; return value;
} }
return const QuillSharedExtensionsConfigurations(); return const QuillSharedExtensionsConfigurations();
} }
@ -66,8 +38,8 @@ class QuillSharedExtensionsConfigurations {
/// which can be found in the [QuillSharedConfigurations] /// which can be found in the [QuillSharedConfigurations]
/// which lives in the [QuillConfigurations] /// which lives in the [QuillConfigurations]
/// ///
/// which exists in the [QuillProvider] /// which exists in the [QuillEditorConfigurations]
static const String key = 'quillSharedExtensionsConfigurations'; static const String key = 'QuillSharedExtensionsConfigurations';
/// Defaults to [ImagePickerService.defaultImpl] /// Defaults to [ImagePickerService.defaultImpl]
final ImagePickerService? _imagePickerService; final ImagePickerService? _imagePickerService;

@ -1,3 +1,5 @@
import 'package:flutter/widgets.dart' show BuildContext, MediaQuery;
Map<String, String> parseCssString(String cssString) { Map<String, String> parseCssString(String cssString) {
final result = <String, String>{}; final result = <String, String>{};
final declarations = cssString.split(';'); final declarations = cssString.split(';');
@ -14,16 +16,71 @@ Map<String, String> parseCssString(String cssString) {
return result; return result;
} }
double? parseCssPropertyAsDouble(String value) { enum _CssUnit {
px('px'),
percentage('%'),
viewportWidth('vw'),
viewportHeight('vh'),
em('em'),
rem('rem'),
invalid('invalid');
const _CssUnit(this.cssName);
final String cssName;
}
double? parseCssPropertyAsDouble(
String value, {
required BuildContext context,
}) {
if (value.trim().isEmpty) { if (value.trim().isEmpty) {
return null; return null;
} }
final list = [
'px', // Try to parse it in case it's a valid double already
// '%', 'vw', 'vh', 'em', 'rem' var doubleValue = double.tryParse(value);
];
for (final element in list) { if (doubleValue != null) {
value = value.replaceFirst(element, ''); return doubleValue;
}
// If not then if it's a css numberic value then we will try to parse it
final unit = _CssUnit.values
.where((element) => value.endsWith(element.cssName))
.firstOrNull;
if (unit == null) {
return null;
}
value = value.replaceFirst(unit.cssName, '');
doubleValue = double.tryParse(value);
if (doubleValue != null) {
switch (unit) {
case _CssUnit.px:
// Do nothing
break;
case _CssUnit.percentage:
// Not supported yet
doubleValue = null;
break;
case _CssUnit.viewportWidth:
doubleValue = (doubleValue / 100) * MediaQuery.sizeOf(context).width;
break;
case _CssUnit.viewportHeight:
doubleValue = (doubleValue / 100) * MediaQuery.sizeOf(context).height;
break;
case _CssUnit.em:
doubleValue = MediaQuery.textScalerOf(context).scale(doubleValue);
break;
case _CssUnit.rem:
// Not fully supported yet
doubleValue = MediaQuery.textScalerOf(context).scale(doubleValue);
break;
case _CssUnit.invalid:
// Ignore
doubleValue = null;
break;
}
} }
return double.tryParse(value); return doubleValue;
} }

@ -1,5 +1,5 @@
import 'package:flutter/foundation.dart' show immutable; import 'package:flutter/foundation.dart' show immutable;
import 'package:flutter/widgets.dart' show Alignment; import 'package:flutter/widgets.dart' show Alignment, BuildContext;
import 'package:flutter_quill/extensions.dart'; import 'package:flutter_quill/extensions.dart';
import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node; import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node;
@ -18,15 +18,20 @@ enum ExtraElementProperties {
Alignment alignment, Alignment alignment,
) getElementAttributes( ) getElementAttributes(
Node node, Node node,
BuildContext context,
) { ) {
var elementSize = const ElementSize(null, null); var elementSize = const ElementSize(null, null);
var elementAlignment = Alignment.center; var elementAlignment = Alignment.center;
double? elementMargin; double? elementMargin;
final heightValue = parseCssPropertyAsDouble( final heightValue = parseCssPropertyAsDouble(
node.style.attributes[Attribute.height.key]?.value.toString() ?? ''); node.style.attributes[Attribute.height.key]?.value.toString() ?? '',
context: context,
);
final widthValue = parseCssPropertyAsDouble( final widthValue = parseCssPropertyAsDouble(
node.style.attributes[Attribute.width.key]?.value.toString() ?? ''); node.style.attributes[Attribute.width.key]?.value.toString() ?? '',
context: context,
);
if (heightValue != null) { if (heightValue != null) {
elementSize = elementSize.copyWith( elementSize = elementSize.copyWith(
@ -46,11 +51,14 @@ enum ExtraElementProperties {
final cssAttrs = parseCssString(cssStyle.value.toString()); final cssAttrs = parseCssString(cssStyle.value.toString());
// todo: This could be improved much better final cssHeightValue = parseCssPropertyAsDouble(
final cssHeightValue = (cssAttrs[Attribute.height.key]) ?? '',
parseCssPropertyAsDouble((cssAttrs[Attribute.height.key]) ?? ''); context: context,
final cssWidthValue = );
parseCssPropertyAsDouble((cssAttrs[Attribute.width.key]) ?? ''); final cssWidthValue = parseCssPropertyAsDouble(
(cssAttrs[Attribute.width.key]) ?? '',
context: context,
);
// cssHeightValue != null && elementSize.height == null // cssHeightValue != null && elementSize.height == null
if (cssHeightValue != null) { if (cssHeightValue != null) {

@ -0,0 +1,17 @@
RegExp base64RegExp = RegExp(
r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$',
);
final imageRegExp = RegExp(
r'https?://.*?\.(?:png|jpe?g|gif|bmp|webp|tiff?)',
caseSensitive: false,
);
final videoRegExp = RegExp(
r'\bhttps?://\S+\.(mp4|mov|avi|mkv|flv|wmv|webm)\b',
caseSensitive: false,
);
final youtubeRegExp = RegExp(
r'^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(-nocookie)?\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|live\/|v\/)?)([\w\-]+)(\S+)?$',
caseSensitive: false,
);

@ -1,16 +1,15 @@
import 'dart:io' show File; import 'dart:io' show File;
import 'package:flutter/foundation.dart' show immutable; import 'package:cross_file/cross_file.dart';
import 'package:flutter/foundation.dart' show Uint8List, immutable;
import 'package:http/http.dart' as http;
import '../embeds/widgets/image.dart'; import '../embeds/widgets/image.dart';
import '../services/image_saver/s_image_saver.dart'; import '../services/image_saver/s_image_saver.dart';
import 'patterns.dart';
RegExp _base64 = RegExp(
r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$',
);
bool isBase64(String str) { bool isBase64(String str) {
return _base64.hasMatch(str); return base64RegExp.hasMatch(str);
} }
bool isHttpBasedUrl(String url) { bool isHttpBasedUrl(String url) {
@ -48,6 +47,23 @@ class SaveImageResult {
final SaveImageResultMethod method; final SaveImageResultMethod method;
} }
Future<Uint8List?> convertImageToUint8List(String image) async {
if (isHttpBasedUrl(image)) {
final response = await http.get(Uri.parse(image));
if (response.statusCode == 200) {
return Uint8List.fromList(response.bodyBytes);
}
return null;
}
// TODO: Add support for all image providers like AssetImage
try {
final file = XFile(image);
return await file.readAsBytes();
} catch (e) {
return null;
}
}
Future<SaveImageResult> saveImage({ Future<SaveImageResult> saveImage({
required String imageUrl, required String imageUrl,
required ImageSaverService imageSaverService, required ImageSaverService imageSaverService,

@ -1,6 +1,6 @@
name: flutter_quill_extensions name: flutter_quill_extensions
description: Embed extensions for flutter_quill including image, video, formula and etc. description: Embed extensions for flutter_quill including image, video, formula and etc.
version: 0.8.0-dev version: 9.0.0-dev-8
homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/ homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/
repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/ repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/
issue_tracker: https://github.com/singerdmx/flutter-quill/issues/ issue_tracker: https://github.com/singerdmx/flutter-quill/issues/
@ -35,15 +35,17 @@ dependencies:
universal_html: ^2.2.4 universal_html: ^2.2.4
cross_file: ^0.3.3+6 cross_file: ^0.3.3+6
flutter_quill: ^8.6.0 flutter_quill: ^9.0.0-dev
photo_view: ^0.14.0 photo_view: ^0.14.0
# Plugins # Plugins
video_player: ^2.8.1 video_player: ^2.8.1
youtube_player_flutter: ^8.1.2 youtube_player_flutter: ^8.1.2
url_launcher: ^6.2.1
super_clipboard: ^0.7.3
gal: ^2.1.3 gal: ^2.1.3
gal_linux: ^0.0.1-dev-3
image_picker: ^1.0.4 image_picker: ^1.0.4
url_launcher: ^6.2.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
name: flutter_quill_test name: flutter_quill_test
description: Test utilities for flutter_quill which includes methods to simplify interacting with the editor in test cases. description: Test utilities for flutter_quill which includes methods to simplify interacting with the editor in test cases.
version: 0.0.5 version: 9.0.0-dev-8
homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_test/ homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_test/
repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_test/ repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_test/
issue_tracker: https://github.com/singerdmx/flutter-quill/issues/ issue_tracker: https://github.com/singerdmx/flutter-quill/issues/
@ -28,7 +28,7 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_quill: ^8.2.5 flutter_quill: ^9.0.0-dev-6
flutter_test: flutter_test:
sdk: flutter sdk: flutter

@ -1,9 +1,9 @@
library flutter_quill; library flutter_quill;
export 'src/extensions/quill_provider.dart'; export 'src/extensions/quill_configurations_ext.dart';
export 'src/models/config/quill_configurations.dart'; export 'src/models/config/quill_configurations.dart';
export 'src/models/config/raw_editor/configurations.dart'; export 'src/models/config/raw_editor/raw_editor_configurations.dart';
export 'src/models/config/toolbar/base_toolbar_configurations.dart'; export 'src/models/config/toolbar/toolbar_configurations.dart';
export 'src/models/documents/attribute.dart'; export 'src/models/documents/attribute.dart';
export 'src/models/documents/document.dart'; export 'src/models/documents/document.dart';
export 'src/models/documents/nodes/block.dart'; export 'src/models/documents/nodes/block.dart';
@ -22,15 +22,17 @@ export 'src/models/structs/vertical_spacing.dart';
export 'src/models/themes/quill_dialog_theme.dart'; export 'src/models/themes/quill_dialog_theme.dart';
export 'src/models/themes/quill_icon_theme.dart'; export 'src/models/themes/quill_icon_theme.dart';
export 'src/utils/embeds.dart'; export 'src/utils/embeds.dart';
export 'src/widgets/controller.dart';
export 'src/widgets/cursor.dart';
export 'src/widgets/default_styles.dart';
export 'src/widgets/editor/editor.dart'; export 'src/widgets/editor/editor.dart';
export 'src/widgets/embeds.dart'; export 'src/widgets/others/cursor.dart';
export 'src/widgets/link.dart' show LinkActionPickerDelegate, LinkMenuAction; export 'src/widgets/others/default_styles.dart';
export 'src/widgets/others/link.dart'
show LinkActionPickerDelegate, LinkMenuAction;
export 'src/widgets/quill/embeds.dart';
export 'src/widgets/quill/quill_controller.dart';
export 'src/widgets/raw_editor/raw_editor.dart'; export 'src/widgets/raw_editor/raw_editor.dart';
export 'src/widgets/raw_editor/raw_editor_state.dart'; export 'src/widgets/raw_editor/raw_editor_state.dart';
export 'src/widgets/style_widgets/style_widgets.dart'; export 'src/widgets/style_widgets/style_widgets.dart';
export 'src/widgets/toolbar/base_toolbar.dart'; export 'src/widgets/toolbar/base_toolbar.dart';
export 'src/widgets/toolbar/toolbar.dart'; export 'src/widgets/toolbar/buttons/select_header_style_button.dart';
export 'src/widgets/toolbar/simple_toolbar.dart';
export 'src/widgets/utils/provider.dart'; export 'src/widgets/utils/provider.dart';

@ -0,0 +1,5 @@
library quill_markdown;
export 'src/packages/quill_markdown/delta_to_markdown.dart';
export 'src/packages/quill_markdown/embeddable_table_syntax.dart';
export 'src/packages/quill_markdown/markdown_to_delta.dart';

@ -0,0 +1,93 @@
import 'package:flutter/widgets.dart' show BuildContext;
import '../../flutter_quill.dart';
extension QuillControllerExt on BuildContext {
/// return nullable [QuillController]
QuillController? get quilController {
return quillSimpleToolbarConfigurations?.controller ??
quillEditorConfigurations?.controller;
}
/// return [QuillController] as not null
QuillController get requireQuillController {
return quillSimpleToolbarConfigurations?.controller ??
quillEditorConfigurations?.controller ??
(throw ArgumentError(
'The quill provider is required, you must only call requireQuillController inside the QuillToolbar and QuillEditor'));
}
}
extension QuillSharedExt on BuildContext {
/// return nullable [QuillSharedConfigurations]
QuillSharedConfigurations? get quillSharedConfigurations {
return quillSimpleToolbarConfigurations?.sharedConfigurations ??
quillEditorConfigurations?.sharedConfigurations;
}
}
extension QuillEditorExt on BuildContext {
/// return [QuillEditorConfigurations] as not null
QuillEditorConfigurations get requireQuillEditorConfigurations {
return QuillEditorProvider.of(this).editorConfigurations;
}
/// return nullable [QuillEditorConfigurations]
QuillEditorConfigurations? get quillEditorConfigurations {
return QuillEditorProvider.maybeOf(this)?.editorConfigurations;
}
/// return nullable [QuillToolbarBaseButtonOptions]. Since the quill
/// quill editor block options is in the [QuillEditorProvider] then we need to
/// get the provider widget first and then we will return block options
/// throw exception if [QuillEditorProvider] is not in the widget tree
QuillEditorElementOptions? get quillEditorElementOptions {
return quillEditorConfigurations?.elementOptions;
}
/// return [QuillToolbarBaseButtonOptions] as not null. Since the quill
/// quill editor block options is in the [QuillEditorProvider] then we need to
/// get the provider widget first and then we will return block options
/// don't throw exception if [QuillEditorProvider] is not in the widget tree
QuillEditorElementOptions get requireQuillEditorElementOptions {
return requireQuillEditorConfigurations.elementOptions;
}
}
extension QuillSimpleToolbarExt on BuildContext {
/// return [QuillSimpleToolbarConfigurations] as not null
QuillSimpleToolbarConfigurations get requireQuillSimpleToolbarConfigurations {
return QuillSimpleToolbarProvider.of(this).toolbarConfigurations;
}
/// return nullable [QuillSimpleToolbarConfigurations]
QuillSimpleToolbarConfigurations? get quillSimpleToolbarConfigurations {
return QuillSimpleToolbarProvider.maybeOf(this)?.toolbarConfigurations;
}
/// return nullable [QuillToolbarBaseButtonOptions].
QuillToolbarBaseButtonOptions? get quillToolbarBaseButtonOptions {
return quillSimpleToolbarConfigurations?.buttonOptions.base;
}
/// return [QuillToolbarBaseButtonOptions] as not null.
QuillToolbarBaseButtonOptions get requireQuillToolbarBaseButtonOptions {
return quillSimpleToolbarConfigurations?.buttonOptions.base ??
quillToolbarConfigurations?.buttonOptions.base ??
(throw ArgumentError(
"The buttonOptions is required and it's null because the toolbar configurations is.",
));
}
}
extension QuillToolbarExt on BuildContext {
/// return [QuillToolbarConfigurations] as not null
QuillToolbarConfigurations get requireQuillToolbarConfigurations {
return QuillToolbarProvider.of(this).toolbarConfigurations;
}
/// return nullable [QuillToolbarConfigurations].
QuillToolbarConfigurations? get quillToolbarConfigurations {
return QuillToolbarProvider.maybeOf(this)?.toolbarConfigurations;
}
}

@ -1,11 +1,11 @@
import 'package:flutter/widgets.dart' show BuildContext; import 'package:flutter/widgets.dart' show BuildContext;
import '../../flutter_quill.dart' show QuillController, QuillProvider; import '../../flutter_quill.dart' show QuillController;
import 'quill_provider.dart'; import 'quill_configurations_ext.dart';
extension QuillControllerNullableExt on QuillController? { extension QuillControllerNullableExt on QuillController? {
/// Simple logic to use the current passed controller if not null /// Simple logic to use the current passed controller if not null
/// if null then we will have to use the default one from [QuillProvider] /// if null then we will have to use the default one
/// using the [context] /// using the [context]
QuillController notNull(BuildContext context) { QuillController notNull(BuildContext context) {
final controller = this; final controller = this;

@ -1,160 +0,0 @@
import 'package:flutter/widgets.dart' show BuildContext;
import '../../flutter_quill.dart';
// TODO: The comments of this file is outdated and needs to be updated
/// Public shared extension
extension QuillProviderExt on BuildContext {
/// return [QuillProvider] as not null
/// throw exception if it's not in the widget tree
QuillProvider get requireQuillProvider {
return QuillProvider.ofNotNull(this);
}
/// return nullable [QuillProvider]
/// don't throw exception if it's not in the widget tree
/// instead it will be null
QuillProvider? get quillProvider {
return QuillProvider.of(this);
}
/// return nullable [QuillController]
/// since the quill controller is in the [QuillProvider] then we need to get
/// the provider widget first and then we will return the controller
/// don't throw exception if [QuillProvider] is not in the widget tree
/// instead it will be null
QuillController? get quilController {
return quillProvider?.configurations.controller;
}
/// return [QuillController] as not null
/// since the quill controller is in the [QuillProvider] then we need to get
/// the provider widget first and then we will return the controller
/// throw exception if [QuillProvider] is not in the widget tree
QuillController get requireQuillController {
return requireQuillProvider.configurations.controller;
}
/// return [QuillConfigurations] as not null
/// since the quill configurations is in the [QuillProvider] then we need to
/// get the provider widget first and then we will return quill configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillConfigurations get requireQuillConfigurations {
return requireQuillProvider.configurations;
}
/// return nullable [QuillConfigurations]
/// since the quill configurations is in the [QuillProvider] then we need to
/// get the provider widget first and then we will return quill configurations
/// don't throw exception if [QuillProvider] is not in the widget tree
QuillConfigurations? get quillConfigurations {
return quillProvider?.configurations;
}
/// return [QuillSharedConfigurations] as not null. Since the quill
/// shared configurations is in the [QuillProvider] then we need to get the
/// provider widget first and then we will return shared configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillSharedConfigurations get requireQuillSharedConfigurations {
return requireQuillConfigurations.sharedConfigurations;
}
/// return nullable [QuillSharedConfigurations] . Since the quill
/// shared configurations is in the [QuillProvider] then we need to get the
/// provider widget first and then we will return shared configurations
/// don't throw exception if [QuillProvider] is not in the widget tree
QuillSharedConfigurations? get quillSharedConfigurations {
return quillConfigurations?.sharedConfigurations;
}
/// return [QuillEditorConfigurations] as not null . Since the quill
/// editor configurations is in the [QuillEditorProvider]
/// then we need to get the
/// provider widget first and then we will return editor configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillEditorConfigurations get requireQuillEditorConfigurations {
return QuillEditorProvider.ofNotNull(this).editorConfigurations;
}
/// return nullable [QuillEditorConfigurations]. Since the quill
/// editor configurations is in the [QuillEditorProvider]
/// then we need to get the
/// provider widget first and then we will return editor configurations
/// don't throw exception if [QuillProvider] is not in the widget tree
QuillEditorConfigurations? get quillEditorConfigurations {
return QuillEditorProvider.of(this)?.editorConfigurations;
}
/// return [QuillToolbarConfigurations] as not null . Since the quill
/// toolbar configurations is in the [QuillToolbarProvider]
/// then we need to get the
/// provider widget first and then we will return toolbar configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillToolbarConfigurations get requireQuillToolbarConfigurations {
return QuillToolbarProvider.ofNotNull(this).toolbarConfigurations;
}
/// return nullable [QuillToolbarConfigurations]. Since the quill
/// toolbar configurations is in the [QuillToolbarProvider]
/// then we need to get the
/// provider widget first and then we will return toolbar configurations
/// don't throw exception if [QuillProvider] is not in the widget tree
QuillToolbarConfigurations? get quillToolbarConfigurations {
return QuillToolbarProvider.of(this)?.toolbarConfigurations;
}
/// return [QuillBaseToolbarConfigurations] as not null . Since the quill
/// toolbar configurations is in the [QuillBaseToolbarProvider]
/// then we need to get the
/// provider widget first and then we will return toolbar configurations
/// throw exception if [QuillBaseToolbarProvider] is not in the widget tree
QuillBaseToolbarConfigurations get requireQuillBaseToolbarConfigurations {
return QuillBaseToolbarProvider.ofNotNull(this).toolbarConfigurations;
}
/// return nullable [QuillBaseToolbarConfigurations]. Since the quill
/// toolbar configurations is in the [QuillBaseToolbarProvider]
/// then we need to get the
/// provider widget first and then we will return toolbar configurations
/// don't throw exception if [QuillBaseToolbarProvider] is not in the widget tree
QuillBaseToolbarConfigurations? get quillBaseToolbarConfigurations {
return QuillBaseToolbarProvider.of(this)?.toolbarConfigurations;
}
/// return nullable [QuillToolbarBaseButtonOptions]. Since the quill
/// toolbar base button options is in the [QuillProvider] then we need to
/// get the provider widget first and then we will return base button
/// don't throw exception if [QuillProvider] is not in the widget tree
QuillToolbarBaseButtonOptions? get quillToolbarBaseButtonOptions {
return quillToolbarConfigurations?.buttonOptions.base;
}
/// return [QuillToolbarBaseButtonOptions] as not null. Since the quill
/// toolbar base button options is in the [QuillProvider] then we need to
/// get the provider widget first and then we will return base button
/// throw exception if [QuillProvider] is not in the widget tree
QuillToolbarBaseButtonOptions get requireQuillToolbarBaseButtonOptions {
return quillToolbarConfigurations?.buttonOptions.base ??
quillBaseToolbarConfigurations?.buttonOptions.base ??
(throw ArgumentError(
"The buttonOptions is required and it's null because the toolbar configurations is.",
));
}
/// return nullable [QuillToolbarBaseButtonOptions]. Since the quill
/// quill editor block options is in the [QuillEditorProvider] then we need to
/// get the provider widget first and then we will return block options
/// throw exception if [QuillEditorProvider] is not in the widget tree
QuillEditorElementOptions? get quillEditorElementOptions {
return quillEditorConfigurations?.elementOptions;
}
/// return [QuillToolbarBaseButtonOptions] as not null. Since the quill
/// quill editor block options is in the [QuillEditorProvider] then we need to
/// get the provider widget first and then we will return block options
/// don't throw exception if [QuillEditorProvider] is not in the widget tree
QuillEditorElementOptions get requireQuillEditorElementOptions {
return requireQuillEditorConfigurations.elementOptions;
}
}

@ -0,0 +1,11 @@
extension UriExt on Uri {
bool isHttpBasedUrl() {
final uri = this;
return uri.isScheme('HTTP') || uri.isScheme('HTTPS');
}
bool isHttpsBasedUrl() {
final uri = this;
return uri.isScheme('HTTPS');
}
}

@ -421,6 +421,30 @@ abstract class FlutterQuillLocalizations {
/// **'Header style'** /// **'Header style'**
String get headerStyle; String get headerStyle;
/// No description provided for @normal.
///
/// In en, this message translates to:
/// **'Normal'**
String get normal;
/// No description provided for @heading1.
///
/// In en, this message translates to:
/// **'Heading 1'**
String get heading1;
/// No description provided for @heading2.
///
/// In en, this message translates to:
/// **'Heading 2'**
String get heading2;
/// No description provided for @heading3.
///
/// In en, this message translates to:
/// **'Heading 3'**
String get heading3;
/// No description provided for @numberedList. /// No description provided for @numberedList.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -610,7 +634,7 @@ abstract class FlutterQuillLocalizations {
/// No description provided for @takeAPhotoUsingYourCamera. /// No description provided for @takeAPhotoUsingYourCamera.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Take a photo using your phone camera'** /// **'Take a photo using your camera'**
String get takeAPhotoUsingYourCamera; String get takeAPhotoUsingYourCamera;
/// No description provided for @pasteAPhotoUsingALink. /// No description provided for @pasteAPhotoUsingALink.
@ -628,7 +652,7 @@ abstract class FlutterQuillLocalizations {
/// No description provided for @recordAVideoUsingYourCamera. /// No description provided for @recordAVideoUsingYourCamera.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Record a video using your phone camera'** /// **'Record a video using your camera'**
String get recordAVideoUsingYourCamera; String get recordAVideoUsingYourCamera;
/// No description provided for @pasteAVideoUsingALink. /// No description provided for @pasteAVideoUsingALink.

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsAr extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'ستايل العنوان'; String get headerStyle => 'ستايل العنوان';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'قائمة مرقمة'; String get numberedList => 'قائمة مرقمة';
@ -231,8 +243,7 @@ class FlutterQuillLocalizationsAr extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -241,8 +252,7 @@ class FlutterQuillLocalizationsAr extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsBg extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Стил на заглавието'; String get headerStyle => 'Стил на заглавието';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Номериран списък'; String get numberedList => 'Номериран списък';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsBg extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsBg extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsBn extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'র সইল'; String get headerStyle => 'র সইল';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'ত তি'; String get numberedList => 'ত তি';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsBn extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsBn extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsCs extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Styl záhlaví'; String get headerStyle => 'Styl záhlaví';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Číslovaný seznam'; String get numberedList => 'Číslovaný seznam';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsCs extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsCs extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsDa extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -231,8 +243,7 @@ class FlutterQuillLocalizationsDa extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -241,8 +252,7 @@ class FlutterQuillLocalizationsDa extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsDe extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Überschrift-Stil'; String get headerStyle => 'Überschrift-Stil';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Nummerierte Liste'; String get numberedList => 'Nummerierte Liste';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsDe extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsDe extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsEn extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsEn extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsEn extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsEs extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsEs extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsEs extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsFa extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'سبک هدر'; String get headerStyle => 'سبک هدر';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'لیست شمارهدار'; String get numberedList => 'لیست شمارهدار';
@ -234,8 +246,7 @@ class FlutterQuillLocalizationsFa extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -244,8 +255,7 @@ class FlutterQuillLocalizationsFa extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsFr extends FlutterQuillLocalizations {
@override @override
String get headerStyle => "Style d'en-tête"; String get headerStyle => "Style d'en-tête";
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Liste numérotée'; String get numberedList => 'Liste numérotée';
@ -235,8 +247,7 @@ class FlutterQuillLocalizationsFr extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -245,8 +256,7 @@ class FlutterQuillLocalizationsFr extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsHe extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'סגנון הכותרת'; String get headerStyle => 'סגנון הכותרת';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'רשימה ממוספרת'; String get numberedList => 'רשימה ממוספרת';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsHe extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsHe extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsHi extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'डर श'; String get headerStyle => 'डर श';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'बदध स'; String get numberedList => 'बदध स';
@ -234,8 +246,7 @@ class FlutterQuillLocalizationsHi extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -244,8 +255,7 @@ class FlutterQuillLocalizationsHi extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsId extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Gaya Header'; String get headerStyle => 'Gaya Header';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Daftar Bernomor'; String get numberedList => 'Daftar Bernomor';
@ -235,8 +247,7 @@ class FlutterQuillLocalizationsId extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -245,8 +256,7 @@ class FlutterQuillLocalizationsId extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsIt extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Stile intestazione'; String get headerStyle => 'Stile intestazione';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Elenco numerato'; String get numberedList => 'Elenco numerato';
@ -235,8 +247,7 @@ class FlutterQuillLocalizationsIt extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -245,8 +256,7 @@ class FlutterQuillLocalizationsIt extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsJa extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'タイトルスタイル'; String get headerStyle => 'タイトルスタイル';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => '順序付きリスト'; String get numberedList => '順序付きリスト';
@ -230,8 +242,7 @@ class FlutterQuillLocalizationsJa extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -240,8 +251,7 @@ class FlutterQuillLocalizationsJa extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsKo extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -230,8 +242,7 @@ class FlutterQuillLocalizationsKo extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -240,8 +251,7 @@ class FlutterQuillLocalizationsKo extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsMs extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsMs extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsMs extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsNl extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -235,8 +247,7 @@ class FlutterQuillLocalizationsNl extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -245,8 +256,7 @@ class FlutterQuillLocalizationsNl extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsNo extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Overskriftsstil'; String get headerStyle => 'Overskriftsstil';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Nummerert liste'; String get numberedList => 'Nummerert liste';
@ -235,8 +247,7 @@ class FlutterQuillLocalizationsNo extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -245,8 +256,7 @@ class FlutterQuillLocalizationsNo extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsPl extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsPl extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsPl extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsPt extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsPt extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsPt extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsRu extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Header style'; String get headerStyle => 'Header style';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numbered list'; String get numberedList => 'Numbered list';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsRu extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsRu extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsSr extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Stil zaglavlja'; String get headerStyle => 'Stil zaglavlja';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numerisana lista'; String get numberedList => 'Numerisana lista';
@ -234,8 +246,7 @@ class FlutterQuillLocalizationsSr extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -244,8 +255,7 @@ class FlutterQuillLocalizationsSr extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsSw extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Mtindo wa Mada'; String get headerStyle => 'Mtindo wa Mada';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Orodha ya Nambari'; String get numberedList => 'Orodha ya Nambari';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsSw extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsSw extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsTk extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Sözbaşy stili'; String get headerStyle => 'Sözbaşy stili';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Sanly sanaw'; String get numberedList => 'Sanly sanaw';
@ -231,8 +243,7 @@ class FlutterQuillLocalizationsTk extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -241,8 +252,7 @@ class FlutterQuillLocalizationsTk extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsTr extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Başlık Stili'; String get headerStyle => 'Başlık Stili';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Numaralı Liste'; String get numberedList => 'Numaralı Liste';
@ -232,8 +244,7 @@ class FlutterQuillLocalizationsTr extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -242,8 +253,7 @@ class FlutterQuillLocalizationsTr extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsUk extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Стиль заголовка'; String get headerStyle => 'Стиль заголовка';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Нумерований список'; String get numberedList => 'Нумерований список';
@ -234,8 +246,7 @@ class FlutterQuillLocalizationsUk extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -244,8 +255,7 @@ class FlutterQuillLocalizationsUk extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsUr extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'ہیڈر کا انداز'; String get headerStyle => 'ہیڈر کا انداز';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'مرقم فہرست'; String get numberedList => 'مرقم فہرست';
@ -236,8 +248,7 @@ class FlutterQuillLocalizationsUr extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -246,8 +257,7 @@ class FlutterQuillLocalizationsUr extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsVi extends FlutterQuillLocalizations {
@override @override
String get headerStyle => 'Kiểu tiêu đề'; String get headerStyle => 'Kiểu tiêu đề';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => 'Danh sách có số'; String get numberedList => 'Danh sách có số';
@ -233,8 +245,7 @@ class FlutterQuillLocalizationsVi extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -243,8 +254,7 @@ class FlutterQuillLocalizationsVi extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -136,6 +136,18 @@ class FlutterQuillLocalizationsZh extends FlutterQuillLocalizations {
@override @override
String get headerStyle => '标题样式'; String get headerStyle => '标题样式';
@override
String get normal => 'Normal';
@override
String get heading1 => 'Heading 1';
@override
String get heading2 => 'Heading 2';
@override
String get heading3 => 'Heading 3';
@override @override
String get numberedList => '编号列表'; String get numberedList => '编号列表';
@ -230,8 +242,7 @@ class FlutterQuillLocalizationsZh extends FlutterQuillLocalizations {
String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery'; String get pickAPhotoFromYourGallery => 'Pick a photo from your gallery';
@override @override
String get takeAPhotoUsingYourCamera => String get takeAPhotoUsingYourCamera => 'Take a photo using your camera';
'Take a photo using your phone camera';
@override @override
String get pasteAPhotoUsingALink => 'Paste a photo using a link'; String get pasteAPhotoUsingALink => 'Paste a photo using a link';
@ -240,8 +251,7 @@ class FlutterQuillLocalizationsZh extends FlutterQuillLocalizations {
String get pickAVideoFromYourGallery => 'Pick a video from your gallery'; String get pickAVideoFromYourGallery => 'Pick a video from your gallery';
@override @override
String get recordAVideoUsingYourCamera => String get recordAVideoUsingYourCamera => 'Record a video using your camera';
'Record a video using your phone camera';
@override @override
String get pasteAVideoUsingALink => 'Paste a video using a link'; String get pasteAVideoUsingALink => 'Paste a video using a link';

@ -44,6 +44,10 @@
"justifyWinWidth": "Justify win width", "justifyWinWidth": "Justify win width",
"textDirection": "Text direction", "textDirection": "Text direction",
"headerStyle": "Header style", "headerStyle": "Header style",
"normal": "Normal",
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"numberedList": "Numbered list", "numberedList": "Numbered list",
"bulletList": "Bullet list", "bulletList": "Bullet list",
"checkedList": "Checked list", "checkedList": "Checked list",
@ -75,9 +79,9 @@
"caseSensitivityAndWholeWordSearch": "Case sensitivity and whole word search", "caseSensitivityAndWholeWordSearch": "Case sensitivity and whole word search",
"insertImage": "Insert image", "insertImage": "Insert image",
"pickAPhotoFromYourGallery": "Pick a photo from your gallery", "pickAPhotoFromYourGallery": "Pick a photo from your gallery",
"takeAPhotoUsingYourCamera": "Take a photo using your phone camera", "takeAPhotoUsingYourCamera": "Take a photo using your camera",
"pasteAPhotoUsingALink": "Paste a photo using a link", "pasteAPhotoUsingALink": "Paste a photo using a link",
"pickAVideoFromYourGallery": "Pick a video from your gallery", "pickAVideoFromYourGallery": "Pick a video from your gallery",
"recordAVideoUsingYourCamera": "Record a video using your phone camera", "recordAVideoUsingYourCamera": "Record a video using your camera",
"pasteAVideoUsingALink": "Paste a video using a link" "pasteAVideoUsingALink": "Paste a video using a link"
} }

@ -1,5 +1,9 @@
{ {
"ar": [ "ar": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -9,6 +13,10 @@
], ],
"bg": [ "bg": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -18,6 +26,10 @@
], ],
"bn": [ "bn": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -27,6 +39,10 @@
], ],
"cs": [ "cs": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -36,6 +52,10 @@
], ],
"da": [ "da": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -45,6 +65,10 @@
], ],
"de": [ "de": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -54,6 +78,10 @@
], ],
"en_US": [ "en_US": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -63,6 +91,10 @@
], ],
"es": [ "es": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -72,6 +104,10 @@
], ],
"fa": [ "fa": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -81,6 +117,10 @@
], ],
"fr": [ "fr": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -90,6 +130,10 @@
], ],
"he": [ "he": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -99,6 +143,10 @@
], ],
"hi": [ "hi": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -108,6 +156,10 @@
], ],
"id": [ "id": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -117,6 +169,10 @@
], ],
"it": [ "it": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -126,6 +182,10 @@
], ],
"ja": [ "ja": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -135,6 +195,10 @@
], ],
"ko": [ "ko": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -144,6 +208,10 @@
], ],
"ms": [ "ms": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -153,6 +221,10 @@
], ],
"nl": [ "nl": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -162,6 +234,10 @@
], ],
"no": [ "no": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -171,6 +247,10 @@
], ],
"pl": [ "pl": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -180,6 +260,10 @@
], ],
"pt": [ "pt": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -189,6 +273,10 @@
], ],
"pt_BR": [ "pt_BR": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -198,6 +286,10 @@
], ],
"ru": [ "ru": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -207,6 +299,10 @@
], ],
"sr": [ "sr": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -216,6 +312,10 @@
], ],
"sw": [ "sw": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -225,6 +325,10 @@
], ],
"tk": [ "tk": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -234,6 +338,10 @@
], ],
"tr": [ "tr": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -243,6 +351,10 @@
], ],
"uk": [ "uk": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -252,6 +364,10 @@
], ],
"ur": [ "ur": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -261,6 +377,10 @@
], ],
"vi": [ "vi": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -270,6 +390,10 @@
], ],
"zh": [ "zh": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -279,6 +403,10 @@
], ],
"zh_CN": [ "zh_CN": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",
@ -288,6 +416,10 @@
], ],
"zh_HK": [ "zh_HK": [
"normal",
"heading1",
"heading2",
"heading3",
"pickAPhotoFromYourGallery", "pickAPhotoFromYourGallery",
"takeAPhotoUsingYourCamera", "takeAPhotoUsingYourCamera",
"pasteAPhotoUsingALink", "pasteAPhotoUsingALink",

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../../extensions/quill_provider.dart'; import '../../extensions/quill_configurations_ext.dart';
import '../extensions/localizations.dart'; import '../extensions/localizations.dart';
class FlutterQuillLocalizationsWidget extends StatelessWidget { class FlutterQuillLocalizationsWidget extends StatelessWidget {
@ -19,7 +19,7 @@ class FlutterQuillLocalizationsWidget extends StatelessWidget {
return child; return child;
} }
return Localizations( return Localizations(
locale: context.requireQuillSharedConfigurations.locale ?? locale: context.quillSharedConfigurations?.locale ??
Localizations.localeOf(context), Localizations.localeOf(context),
delegates: FlutterQuillLocalizations.localizationsDelegates, delegates: FlutterQuillLocalizations.localizationsDelegates,
child: child, child: child,

@ -6,14 +6,15 @@ import 'package:flutter/material.dart'
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart' show experimental; import 'package:meta/meta.dart' show experimental;
import '../../../widgets/default_styles.dart';
import '../../../widgets/delegate.dart';
import '../../../widgets/editor/editor.dart';
import '../../../widgets/editor/editor_builder.dart'; import '../../../widgets/editor/editor_builder.dart';
import '../../../widgets/embeds.dart'; import '../../../widgets/others/default_styles.dart';
import '../../../widgets/link.dart'; import '../../../widgets/others/delegate.dart';
import '../../../widgets/others/link.dart';
import '../../../widgets/quill/embeds.dart';
import '../../../widgets/quill/quill_controller.dart';
import '../../../widgets/raw_editor/raw_editor.dart'; import '../../../widgets/raw_editor/raw_editor.dart';
import '../../themes/quill_dialog_theme.dart'; import '../../themes/quill_dialog_theme.dart';
import '../quill_shared_configurations.dart';
import 'element_options.dart'; import 'element_options.dart';
export 'element_options.dart'; export 'element_options.dart';
@ -24,6 +25,8 @@ class QuillEditorConfigurations extends Equatable {
/// Important note for the maintainers /// Important note for the maintainers
/// When editing this class please update the [copyWith] function too. /// When editing this class please update the [copyWith] function too.
const QuillEditorConfigurations({ const QuillEditorConfigurations({
required this.controller,
this.sharedConfigurations = const QuillSharedConfigurations(),
this.scrollable = true, this.scrollable = true,
this.padding = EdgeInsets.zero, this.padding = EdgeInsets.zero,
this.autoFocus = false, this.autoFocus = false,
@ -74,6 +77,10 @@ class QuillEditorConfigurations extends Equatable {
this.textInputAction = TextInputAction.newline, this.textInputAction = TextInputAction.newline,
}); });
final QuillSharedConfigurations sharedConfigurations;
final QuillController controller;
/// The text placeholder in the quill editor /// The text placeholder in the quill editor
final String? placeholder; final String? placeholder;
@ -331,6 +338,8 @@ class QuillEditorConfigurations extends Equatable {
// regenerate this function using extension in vs code or plugin in intellij // regenerate this function using extension in vs code or plugin in intellij
QuillEditorConfigurations copyWith({ QuillEditorConfigurations copyWith({
QuillSharedConfigurations? sharedConfigurations,
QuillController? controller,
String? placeholder, String? placeholder,
bool? readOnly, bool? readOnly,
bool? scrollable, bool? scrollable,
@ -376,6 +385,8 @@ class QuillEditorConfigurations extends Equatable {
TextInputAction? textInputAction, TextInputAction? textInputAction,
}) { }) {
return QuillEditorConfigurations( return QuillEditorConfigurations(
sharedConfigurations: sharedConfigurations ?? this.sharedConfigurations,
controller: controller ?? this.controller,
placeholder: placeholder ?? this.placeholder, placeholder: placeholder ?? this.placeholder,
readOnly: readOnly ?? this.readOnly, readOnly: readOnly ?? this.readOnly,
scrollable: scrollable ?? this.scrollable, scrollable: scrollable ?? this.scrollable,

@ -2,16 +2,25 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart' show immutable; import 'package:flutter/foundation.dart' show immutable;
import 'elements/code_block.dart'; import 'elements/code_block.dart';
import 'elements/list/ordered_list.dart';
import 'elements/list/unordered_list.dart';
export 'elements/code_block.dart'; export 'elements/code_block.dart';
export 'elements/list/ordered_list.dart';
export 'elements/list/unordered_list.dart';
@immutable @immutable
class QuillEditorElementOptions extends Equatable { class QuillEditorElementOptions extends Equatable {
const QuillEditorElementOptions({ const QuillEditorElementOptions({
this.codeBlock = const QuillEditorCodeBlockElementOptions(), this.codeBlock = const QuillEditorCodeBlockElementOptions(),
this.orderedList = const QuillEditorOrderedListElementOptions(),
this.unorderedList = const QuillEditorUnOrderedListElementOptions(),
}); });
final QuillEditorCodeBlockElementOptions codeBlock; final QuillEditorCodeBlockElementOptions codeBlock;
final QuillEditorOrderedListElementOptions orderedList;
final QuillEditorUnOrderedListElementOptions unorderedList;
@override @override
List<Object?> get props => [ List<Object?> get props => [
codeBlock, codeBlock,

@ -0,0 +1,14 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart' show immutable;
import 'package:flutter/widgets.dart' show Color;
@immutable
class QuillEditorOrderedListElementOptions extends Equatable {
const QuillEditorOrderedListElementOptions(
{this.backgroundColor, this.fontColor});
final Color? backgroundColor;
final Color? fontColor;
@override
List<Object?> get props => [];
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save