Skip to content

Commit 2104514

Browse files
author
Ellet
authored
Update flutter_quill and flutter_quill_extensions (#1520)
* Update flutter_quill and flutter_quill_extensions
1 parent 700f003 commit 2104514

File tree

28 files changed

+642
-478
lines changed

28 files changed

+642
-478
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## [8.4.2]
2+
- **Breaking change**: The `QuillRawEditor` configurations has been moved to a seperated class, also the `readOnly` has been renamed to `isReadOnly`, if you are using the `QuillEditor` you don't have to change anything
3+
- Allow the developer to use override the `TextInputAction` in both `QuillRawEditor` and `QuillEditor`
4+
- You can use now the `QuillRawEditor` without `QuillEditorProvider`
5+
- Bug fixes
6+
- Add implementation of image cropping in the `example`
7+
- Update the `QuillToolbarIconButton` to use the material 3 buttons
8+
19
## [8.4.1]
210
- Add `copyWith` in `OptionalSize` class
311

doc/todo.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ This is a todo list page that added recently and will be updated soon.
2727

2828
1. Improve the Raw Quill Editor, for more [info](https://github.com/singerdmx/flutter-quill/issues/1509)
2929
2. Provide more support to all the platforms
30+
3. Extract the shared properties between `QuillRawEditorConfigurations` and `QuillEditorConfigurations`
3031

3132
### Bugs
3233

example/android/app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@
4242
<category android:name="android.intent.category.LAUNCHER" />
4343
</intent-filter>
4444
</activity>
45+
46+
<activity
47+
android:name="com.yalantis.ucrop.UCropActivity"
48+
android:screenOrientation="portrait"
49+
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
50+
4551
<!-- Don't delete the meta-data below.
4652
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
4753
<meta-data

example/lib/pages/home_page.dart

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:flutter_quill/flutter_quill.dart';
1515
import 'package:flutter_quill_extensions/flutter_quill_extensions.dart';
1616
import 'package:flutter_quill_extensions/logic/services/image_picker/image_picker.dart';
1717
import 'package:flutter_quill_extensions/presentation/embeds/widgets/image.dart';
18+
import 'package:image_cropper/image_cropper.dart';
1819
import 'package:path/path.dart' as path;
1920
import 'package:path_provider/path_provider.dart';
2021

@@ -455,6 +456,42 @@ class _HomePageState extends State<HomePage> {
455456
);
456457
}
457458

459+
/// When inserting an image
460+
OnImageInsertCallback get onImageInsert {
461+
return (image, controller) async {
462+
final croppedFile = await ImageCropper().cropImage(
463+
sourcePath: image,
464+
aspectRatioPresets: [
465+
CropAspectRatioPreset.square,
466+
CropAspectRatioPreset.ratio3x2,
467+
CropAspectRatioPreset.original,
468+
CropAspectRatioPreset.ratio4x3,
469+
CropAspectRatioPreset.ratio16x9
470+
],
471+
uiSettings: [
472+
AndroidUiSettings(
473+
toolbarTitle: 'Cropper',
474+
toolbarColor: Colors.deepOrange,
475+
toolbarWidgetColor: Colors.white,
476+
initAspectRatio: CropAspectRatioPreset.original,
477+
lockAspectRatio: false,
478+
),
479+
IOSUiSettings(
480+
title: 'Cropper',
481+
),
482+
WebUiSettings(
483+
context: context,
484+
),
485+
],
486+
);
487+
final newImage = croppedFile?.path;
488+
if (newImage == null) {
489+
return;
490+
}
491+
controller.insertImageBlock(imageSource: newImage);
492+
};
493+
}
494+
458495
QuillToolbar get quillToolbar {
459496
final customButtons = [
460497
QuillToolbarCustomButtonOptions(
@@ -481,13 +518,14 @@ class _HomePageState extends State<HomePage> {
481518
configurations: QuillToolbarConfigurations(
482519
customButtons: customButtons,
483520
embedButtons: FlutterQuillEmbeds.toolbarButtons(
521+
cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
484522
imageButtonOptions: QuillToolbarImageButtonOptions(
485523
imageButtonConfigurations: QuillToolbarImageConfigurations(
486524
onImageInsertedCallback: (image) async {
487525
_onImagePickCallback(File(image));
488526
},
527+
onImageInsertCallback: onImageInsert,
489528
),
490-
// webImagePickImpl: _webImagePickImpl,
491529
),
492530
),
493531
buttonOptions: QuillToolbarButtonOptions(
@@ -496,14 +534,14 @@ class _HomePageState extends State<HomePage> {
496534
),
497535
),
498536
),
499-
// afterButtonPressed: _focusNode.requestFocus,
500537
);
501538
}
502539
if (isDesktop(supportWeb: false)) {
503540
return QuillToolbar(
504541
configurations: QuillToolbarConfigurations(
505542
customButtons: customButtons,
506543
embedButtons: FlutterQuillEmbeds.toolbarButtons(
544+
cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
507545
imageButtonOptions: QuillToolbarImageButtonOptions(
508546
imageButtonConfigurations: QuillToolbarImageConfigurations(
509547
onImageInsertedCallback: (image) async {
@@ -525,6 +563,7 @@ class _HomePageState extends State<HomePage> {
525563
configurations: QuillToolbarConfigurations(
526564
customButtons: customButtons,
527565
embedButtons: FlutterQuillEmbeds.toolbarButtons(
566+
cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
528567
videoButtonOptions: QuillToolbarVideoButtonOptions(
529568
videoConfigurations: QuillToolbarVideoConfigurations(
530569
onVideoInsertedCallback: (video) =>
@@ -533,6 +572,7 @@ class _HomePageState extends State<HomePage> {
533572
),
534573
imageButtonOptions: QuillToolbarImageButtonOptions(
535574
imageButtonConfigurations: QuillToolbarImageConfigurations(
575+
onImageInsertCallback: onImageInsert,
536576
onImageInsertedCallback: (image) async {
537577
_onImagePickCallback(File(image));
538578
},

example/pubspec.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ dependencies:
1717
path_provider: ^2.1.1
1818
# filesystem_picker: ^4.0.0
1919
file_picker: ^6.1.1
20-
flutter_quill: ^8.2.5
21-
flutter_quill_extensions: ^0.6.3
20+
flutter_quill: ^8.4.1
21+
flutter_quill_extensions: ^0.6.5
2222
path: ^1.8.3
2323
desktop_drop: ^0.4.4
24+
image_cropper: ^5.0.0
2425

2526
dependency_overrides:
2627
flutter_quill:

example/web/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
<title>example</title>
3333
<link rel="manifest" href="manifest.json">
3434

35+
<!-- Croppie -->
36+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.css" />
37+
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.js"></script>
38+
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"></script>
39+
3540
<script>
3641
// The value below is injected by flutter build, do not touch.
3742
const serviceWorkerVersion = null;

flutter_quill_extensions/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.6
2+
- Add `onImageClicked` in the `QuillEditorImageEmbedConfigurations`
3+
- Fix image resizing on mobile
4+
15
## 0.6.5
26
- Support the new improved platform checking of `flutter_quill`
37
- Update the Image embed builder logic

flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,20 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
112112
QuillSharedExtensionsConfigurations.get(context: context)
113113
.imageSaverService;
114114
return GestureDetector(
115+
onTap: configurations.onImageClicked ??
116+
() => showDialog(
117+
context: context,
118+
builder: (context) {
119+
return ImageOptionsMenu(
120+
controller: controller,
121+
configurations: configurations,
122+
imageSource: imageSource,
123+
imageSize: imageSize,
124+
isReadOnly: readOnly,
125+
imageSaverService: imageSaverService,
126+
);
127+
},
128+
),
115129
child: Builder(
116130
builder: (context) {
117131
if (margin != null) {
@@ -123,19 +137,6 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
123137
return image;
124138
},
125139
),
126-
onTap: () => showDialog(
127-
context: context,
128-
builder: (context) {
129-
return ImageOptionsMenu(
130-
controller: controller,
131-
configurations: configurations,
132-
imageSource: imageSource,
133-
imageSize: imageSize,
134-
isReadOnly: readOnly,
135-
imageSaverService: imageSaverService,
136-
);
137-
},
138-
),
139140
);
140141
}
141142
}
@@ -191,10 +192,16 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
191192
// It css value as string but we will try to support it anyway
192193

193194
// TODO: This could be improved much better
194-
final cssHeightValue = double.tryParse(
195-
(attrs[Attribute.height.key] ?? '').replaceFirst('px', ''));
196-
final cssWidthValue = double.tryParse(
197-
(attrs[Attribute.width.key] ?? '').replaceFirst('px', ''));
195+
final cssHeightValue = double.tryParse(((base.isMobile(supportWeb: false)
196+
? attrs[Attribute.mobileHeight]
197+
: attrs[Attribute.height.key]) ??
198+
'')
199+
.replaceFirst('px', ''));
200+
final cssWidthValue = double.tryParse(((!base.isMobile(supportWeb: false)
201+
? attrs[Attribute.width.key]
202+
: attrs[Attribute.mobileWidth]) ??
203+
'')
204+
.replaceFirst('px', ''));
198205

199206
if (cssHeightValue != null) {
200207
imageSize = imageSize.copyWith(height: cssHeightValue);

flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'package:flutter/cupertino.dart' show showCupertinoModalPopup;
22
import 'package:flutter/material.dart';
3-
// import 'package:flutter/services.dart' show Clipboard, ClipboardData;
43
import 'package:flutter_quill/extensions.dart'
54
show isDesktop, isMobile, replaceStyleStringWithSize;
65
import 'package:flutter_quill/flutter_quill.dart'
@@ -51,16 +50,16 @@ class ImageOptionsMenu extends StatelessWidget {
5150
builder: (context) {
5251
final screenSize = MediaQuery.sizeOf(context);
5352
return ImageResizer(
54-
onImageResize: (w, h) {
53+
onImageResize: (width, height) {
5554
final res = getEmbedNode(
5655
controller,
5756
controller.selection.start,
5857
);
5958

6059
final attr = replaceStyleStringWithSize(
6160
getImageStyleString(controller),
62-
width: w,
63-
height: h,
61+
width: width,
62+
height: height,
6463
isMobile: isMobile(supportWeb: false),
6564
);
6665
controller
@@ -94,7 +93,7 @@ class ImageOptionsMenu extends StatelessWidget {
9493
);
9594
// TODO: Implement the copy image
9695
// await Clipboard.setData(
97-
// ClipboardData(text: '$imageUrl'),
96+
// ClipboardData(),
9897
// );
9998
navigator.pop();
10099
},

flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// ignore_for_file: use_build_context_synchronously
2-
31
import 'package:flutter/material.dart';
42
import 'package:flutter_quill/flutter_quill.dart';
53
import 'package:flutter_quill/translations.dart';
@@ -104,6 +102,7 @@ class QuillToolbarCameraButton extends StatelessWidget {
104102
size: iconSize * 1.77,
105103
fillColor: iconFillColor,
106104
borderRadius: iconTheme?.borderRadius ?? 2,
105+
// isDesktop(supportWeb: false) ? null :
107106
onPressed: () => _sharedOnPressed(context),
108107
);
109108
}
@@ -126,22 +125,16 @@ class QuillToolbarCameraButton extends StatelessWidget {
126125
BuildContext context,
127126
QuillController controller,
128127
) async {
129-
// if (onVideoPickCallback == null && onImagePickCallback == null) {
130-
// throw ArgumentError(
131-
// 'onImagePickCallback and onVideoPickCallback are both null',
132-
// );
133-
// }
128+
final imagePickerService =
129+
QuillSharedExtensionsConfigurations.get(context: context)
130+
.imagePickerService;
134131

135132
final cameraAction = await _getCameraAction(context);
136133

137134
if (cameraAction == null) {
138135
return;
139136
}
140137

141-
final imagePickerService =
142-
QuillSharedExtensionsConfigurations.get(context: context)
143-
.imagePickerService;
144-
145138
switch (cameraAction) {
146139
case CameraAction.video:
147140
final videoFile = await imagePickerService.pickVideo(

0 commit comments

Comments
 (0)