Quick fixes and changes

pull/1507/head
Ellet 1 year ago
parent 7fab7b8d71
commit 72a16b608c
No known key found for this signature in database
GPG Key ID: C488CC70BBCEF0D1
  1. 3
      CONTRIBUTING.md
  2. 4
      README.md
  3. 50
      example/lib/pages/home_page.dart
  4. 3
      flutter_quill_extensions/CHANGELOG.md
  5. 27
      flutter_quill_extensions/README.md
  6. 12
      flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart
  7. 52
      flutter_quill_extensions/lib/presentation/embeds/embed_types.dart
  8. 17
      flutter_quill_extensions/lib/presentation/embeds/embed_types/image.dart
  9. 2
      flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart
  10. 1
      flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/video_button.dart
  11. 2
      flutter_quill_extensions/lib/presentation/embeds/widgets/image.dart
  12. 16
      flutter_quill_extensions/lib/presentation/models/config/editor/image.dart
  13. 7
      flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/camera.dart
  14. 7
      flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/media_button.dart
  15. 4
      flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/video.dart

@ -0,0 +1,3 @@
# Contributing
We welcome contributions!

@ -668,6 +668,10 @@ Special thanks for everyone that have contributed to this project...
Made with [contrib.rocks](https://contrib.rocks). Made with [contrib.rocks](https://contrib.rocks).
We welcome contributions!
Please follow these guidelines when contributing to our project. See [CONTRIBUTING.md](./../CONTRIBUTING.md) for more details.
[Quill]: https://quilljs.com/docs/formats [Quill]: https://quilljs.com/docs/formats
[Flutter]: https://github.com/flutter/flutter [Flutter]: https://github.com/flutter/flutter
[FlutterQuill]: https://pub.dev/packages/flutter_quill [FlutterQuill]: https://pub.dev/packages/flutter_quill

@ -2,7 +2,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io' show File, Platform; import 'dart:io' show File;
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -35,6 +35,7 @@ class _HomePageState extends State<HomePage> {
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
Timer? _selectAllTimer; Timer? _selectAllTimer;
_SelectionType _selectionType = _SelectionType.none; _SelectionType _selectionType = _SelectionType.none;
var _isReadOnly = false;
@override @override
void dispose() { void dispose() {
@ -85,6 +86,13 @@ class _HomePageState extends State<HomePage> {
'Flutter Quill', 'Flutter Quill',
), ),
actions: [ actions: [
IconButton(
onPressed: () {
setState(() => _isReadOnly = !_isReadOnly);
},
icon: Icon(
_isReadOnly ? Icons.lock : Icons.edit,
)),
IconButton( IconButton(
onPressed: () => _insertTimeStamp( onPressed: () => _insertTimeStamp(
_controller, _controller,
@ -219,7 +227,7 @@ class _HomePageState extends State<HomePage> {
return QuillEditor( return QuillEditor(
configurations: QuillEditorConfigurations( configurations: QuillEditorConfigurations(
placeholder: 'Add content', placeholder: 'Add content',
readOnly: false, readOnly: _isReadOnly,
autoFocus: false, autoFocus: false,
enableSelectionToolbar: isMobile(), enableSelectionToolbar: isMobile(),
expands: false, expands: false,
@ -250,7 +258,11 @@ class _HomePageState extends State<HomePage> {
), ),
), ),
embedBuilders: [ embedBuilders: [
...FlutterQuillEmbeds.editorBuilders(), ...FlutterQuillEmbeds.editorBuilders(
imageEmbedConfigurations: const QuillEditorImageEmbedConfigurations(
forceUseMobileOptionMenuForImageClick: true,
),
),
TimeStampEmbedBuilderWidget() TimeStampEmbedBuilderWidget()
], ],
), ),
@ -282,7 +294,7 @@ class _HomePageState extends State<HomePage> {
// afterButtonPressed: _focusNode.requestFocus, // afterButtonPressed: _focusNode.requestFocus,
); );
} }
if (_isDesktop()) { if (isDesktop()) {
return QuillToolbar( return QuillToolbar(
configurations: QuillToolbarConfigurations( configurations: QuillToolbarConfigurations(
embedButtons: FlutterQuillEmbeds.toolbarButtons( embedButtons: FlutterQuillEmbeds.toolbarButtons(
@ -292,8 +304,6 @@ class _HomePageState extends State<HomePage> {
_onImagePickCallback(File(image)); _onImagePickCallback(File(image));
}, },
), ),
// onImagePickCallback: _onImagePickCallback,
// filePickImpl: openFileSystemPickerForDesktop,
), ),
), ),
showAlignmentButtons: true, showAlignmentButtons: true,
@ -303,7 +313,6 @@ class _HomePageState extends State<HomePage> {
), ),
), ),
), ),
// afterButtonPressed: _focusNode.requestFocus,
); );
} }
return QuillToolbar( return QuillToolbar(
@ -385,24 +394,23 @@ class _HomePageState extends State<HomePage> {
child: quillEditor, child: quillEditor,
), ),
), ),
kIsWeb if (!_isReadOnly)
? Expanded( kIsWeb
child: Container( ? Expanded(
padding: child: Container(
const EdgeInsets.symmetric(vertical: 16, horizontal: 8), padding: const EdgeInsets.symmetric(
child: quillToolbar, vertical: 16, horizontal: 8),
)) child: quillToolbar,
: Container( ))
child: quillToolbar, : Container(
) child: quillToolbar,
)
], ],
), ),
), ),
); );
} }
bool _isDesktop() => !kIsWeb && !Platform.isAndroid && !Platform.isIOS;
// Future<String?> _openFileSystemPickerForDesktop(BuildContext context) // Future<String?> _openFileSystemPickerForDesktop(BuildContext context)
// async { // async {
// return await FilesystemPicker.open( // return await FilesystemPicker.open(
@ -515,7 +523,7 @@ class _HomePageState extends State<HomePage> {
)), )),
dense: true, dense: true,
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
onTap: _readOnly, onTap: _openReadOnlyPage,
), ),
Divider( Divider(
thickness: 2, thickness: 2,
@ -526,7 +534,7 @@ class _HomePageState extends State<HomePage> {
); );
} }
void _readOnly() { void _openReadOnlyPage() {
Navigator.pop(super.context); Navigator.pop(super.context);
Navigator.push( Navigator.push(
super.context, super.context,

@ -1,5 +1,8 @@
## 0.6.0-dev.4 ## 0.6.0-dev.4
- Add more exports - Add more exports
- Update `README.md``
- Fix save image bug
- Quick fixes
## 0.6.0-dev.3 ## 0.6.0-dev.3
- Disable the camera option by default on desktop - Disable the camera option by default on desktop

@ -59,17 +59,11 @@ Before starting using this package you must follow the setup
Set the `embedBuilders` and `embedToolbar` params in configurations of `QuillEditor` and `QuillToolbar` with the Set the `embedBuilders` and `embedToolbar` params in configurations of `QuillEditor` and `QuillToolbar` with the
values provided by this repository. values provided by this repository.
**Quill toolbar**: **Quill Toolbar**:
```dart ```dart
QuillToolbar( QuillToolbar(
configurations: QuillToolbarConfigurations( configurations: QuillToolbarConfigurations(
embedButtons: FlutterQuillEmbeds.toolbarButtons( embedButtons: FlutterQuillEmbeds.toolbarButtons(),
imageButtonOptions: QuillToolbarImageButtonOptions(
onImagePickCallback: (file) async {
return file.path;
},
),
),
), ),
), ),
``` ```
@ -79,13 +73,7 @@ QuillToolbar(
Expanded( Expanded(
child: QuillEditor.basic( child: QuillEditor.basic(
configurations: QuillEditorConfigurations( configurations: QuillEditorConfigurations(
readOnly: true, embedBuilders: kIsWeb ? FlutterQuillEmbeds.editorsWebBuilders() : FlutterQuillEmbeds.editorBuilders(),
embedBuilders: FlutterQuillEmbeds.editorBuilders(
imageEmbedConfigurations:
const QuillEditorImageEmbedConfigurations(
forceUseMobileOptionMenuForImageClick: true,
),
),
), ),
), ),
) )
@ -113,7 +101,7 @@ QuillProvider(
child: QuillEditor.basic( child: QuillEditor.basic(
configurations: QuillEditorConfigurations( configurations: QuillEditorConfigurations(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
embedBuilders: FlutterQuillEmbeds.editorBuilders(), embedBuilders: kIsWeb ? FlutterQuillEmbeds.editorsWebBuilders() : FlutterQuillEmbeds.editorBuilders(),
), ),
), ),
) )
@ -122,11 +110,6 @@ QuillProvider(
) )
``` ```
For web, use:
```dart
FlutterQuillEmbeds.editorsWebBuilders()
```
## Features ## Features
```markdown ```markdown
@ -142,7 +125,7 @@ FlutterQuillEmbeds.editorsWebBuilders()
We welcome contributions! We welcome contributions!
Please follow these guidelines when contributing to our project. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. Please follow these guidelines when contributing to our project. See [CONTRIBUTING.md](./../CONTRIBUTING.md) for more details.
## License ## License

@ -1,5 +1,3 @@
import 'dart:io' show File;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -8,7 +6,7 @@ import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/translations.dart'; import 'package:flutter_quill/translations.dart';
import '../../../models/config/editor/image.dart'; import '../../../models/config/editor/image.dart';
import '../../embed_types.dart'; import '../../embed_types/image.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../widgets/image.dart'; import '../../widgets/image.dart';
import '../../widgets/image_resizer.dart'; import '../../widgets/image_resizer.dart';
@ -138,11 +136,9 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
onPressed: () async { onPressed: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
final imageFile = File(imageUrl);
// Call the remove check callback if set // Call the remove check callback if set
if (await configurations.shouldRemoveImageCallback if (await configurations.shouldRemoveImageCallback
?.call(imageFile) == ?.call(imageUrl) ==
false) { false) {
return; return;
} }
@ -158,7 +154,7 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
TextSelection.collapsed(offset: offset), TextSelection.collapsed(offset: offset),
); );
// Call the post remove callback if set // Call the post remove callback if set
await configurations.onImageRemovedCallback.call(imageFile); await configurations.onImageRemovedCallback.call(imageUrl);
}, },
); );
return Padding( return Padding(
@ -259,7 +255,7 @@ Widget _menuOptionsForReadonlyImage({
onTap: () { onTap: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (_) {
final saveOption = SimpleDialogItem( final saveOption = SimpleDialogItem(
icon: Icons.save, icon: Icons.save,
color: Colors.greenAccent, color: Colors.greenAccent,

@ -1,25 +1,8 @@
import 'dart:io' show File; import 'package:cross_file/cross_file.dart' show XFile;
import 'dart:typed_data';
import 'package:flutter/material.dart'
show ImageErrorWidgetBuilder, BuildContext, ImageProvider;
typedef OnVideoPickCallback = Future<String?> Function(File file);
/// [FilePickImpl] is an implementation for picking files.
typedef FilePickImpl = Future<String?> Function(BuildContext context);
/// [WebImagePickImpl] is an implementation for picking web images.
// typedef WebImagePickImpl = Future<String?> Function(
// OnImagePickCallback onImagePickCallback,
// );
typedef WebVideoPickImpl = Future<String?> Function(
OnVideoPickCallback onImagePickCallback,
);
typedef MediaFileUrl = String; typedef MediaFileUrl = String;
typedef MediaFilePicker = Future<QuillFile?> Function(QuillMediaType mediaType); typedef MediaFilePicker = Future<XFile?> Function(QuillMediaType mediaType);
typedef MediaPickedCallback = Future<MediaFileUrl> Function(QuillFile file); typedef MediaPickedCallback = Future<MediaFileUrl> Function(XFile file);
enum QuillMediaType { image, video } enum QuillMediaType { image, video }
@ -27,32 +10,3 @@ extension QuillMediaTypeX on QuillMediaType {
bool get isImage => this == QuillMediaType.image; bool get isImage => this == QuillMediaType.image;
bool get isVideo => this == QuillMediaType.video; bool get isVideo => this == QuillMediaType.video;
} }
/// Represents a file data which returned by file picker.
class QuillFile {
QuillFile({
required this.name,
this.path = '',
Uint8List? bytes,
}) : assert(name.isNotEmpty),
bytes = bytes ?? Uint8List(0);
final String name;
final String path;
final Uint8List bytes;
}
typedef ImageEmbedBuilderWillRemoveCallback = Future<bool> Function(
File imageFile,
);
typedef ImageEmbedBuilderOnRemovedCallback = Future<void> Function(
File imageFile,
);
typedef ImageEmbedBuilderProviderBuilder = ImageProvider Function(
String imageUrl,
// {required bool isLocalImage}
);
typedef ImageEmbedBuilderErrorWidgetBuilder = ImageErrorWidgetBuilder;

@ -1,6 +1,9 @@
import 'package:flutter/widgets.dart'
show ImageErrorWidgetBuilder, ImageProvider;
import 'package:flutter/widgets.dart' show BuildContext; 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 '../../../logic/extensions/controller.dart'; import '../../../logic/extensions/controller.dart';
import '../../../logic/services/image_picker/s_image_picker.dart'; import '../../../logic/services/image_picker/s_image_picker.dart';
@ -63,3 +66,17 @@ class QuillToolbarImageConfigurations {
return _onImageInsertCallback ?? defaultOnImageInsertCallback(); return _onImageInsertCallback ?? defaultOnImageInsertCallback();
} }
} }
typedef ImageEmbedBuilderWillRemoveCallback = Future<bool> Function(
String imageUrl,
);
typedef ImageEmbedBuilderOnRemovedCallback = Future<void> Function(
String imageUrl,
);
typedef ImageEmbedBuilderProviderBuilder = ImageProvider Function(
String imageUrl,
);
typedef ImageEmbedBuilderErrorWidgetBuilder = ImageErrorWidgetBuilder;

@ -73,7 +73,6 @@ class QuillToolbarCameraButton extends StatelessWidget {
if (childBuilder != null) { if (childBuilder != null) {
childBuilder( childBuilder(
QuillToolbarCameraButtonOptions( QuillToolbarCameraButtonOptions(
onVideoPickCallback: options.onVideoPickCallback,
afterButtonPressed: _afterButtonPressed(context), afterButtonPressed: _afterButtonPressed(context),
iconData: options.iconData, iconData: options.iconData,
fillColor: options.fillColor, fillColor: options.fillColor,
@ -81,7 +80,6 @@ class QuillToolbarCameraButton extends StatelessWidget {
iconTheme: options.iconTheme, iconTheme: options.iconTheme,
tooltip: options.tooltip, tooltip: options.tooltip,
cameraConfigurations: options.cameraConfigurations, cameraConfigurations: options.cameraConfigurations,
webVideoPickImpl: options.webVideoPickImpl,
), ),
QuillToolbarCameraButtonExtraOptions( QuillToolbarCameraButtonExtraOptions(
controller: controller, controller: controller,

@ -85,7 +85,6 @@ class QuillToolbarVideoButton extends StatelessWidget {
linkRegExp: options.linkRegExp, linkRegExp: options.linkRegExp,
tooltip: options.tooltip, tooltip: options.tooltip,
iconTheme: options.iconTheme, iconTheme: options.iconTheme,
webVideoPickImpl: options.webVideoPickImpl,
videoConfigurations: options.videoConfigurations, videoConfigurations: options.videoConfigurations,
), ),
QuillToolbarVideoButtonExtraOptions( QuillToolbarVideoButtonExtraOptions(

@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
import '../embed_types.dart'; import '../embed_types/image.dart';
import '../utils.dart'; import '../utils.dart';
const List<String> imageFileExtensions = [ const List<String> imageFileExtensions = [

@ -1,7 +1,9 @@
import 'dart:io' show File;
import 'package:flutter_quill/extensions.dart'; import 'package:flutter_quill/extensions.dart';
import 'package:meta/meta.dart' show immutable; import 'package:meta/meta.dart' show immutable;
import '../../../embeds/embed_types.dart'; import '../../../embeds/embed_types/image.dart';
/// [QuillEditorImageEmbedConfigurations] for desktop, mobile and /// [QuillEditorImageEmbedConfigurations] for desktop, mobile and
/// other platforms /// other platforms
@ -109,7 +111,7 @@ class QuillEditorImageEmbedConfigurations {
final bool forceUseMobileOptionMenuForImageClick; final bool forceUseMobileOptionMenuForImageClick;
static ImageEmbedBuilderOnRemovedCallback get defaultOnImageRemovedCallback { static ImageEmbedBuilderOnRemovedCallback get defaultOnImageRemovedCallback {
return (imageFile) async { return (imageUrl) async {
final mobile = isMobile(); final mobile = isMobile();
// If the platform is not mobile, return void; // If the platform is not mobile, return void;
// Since the mobile OS gives us a copy of the image // Since the mobile OS gives us a copy of the image
@ -132,9 +134,15 @@ class QuillEditorImageEmbedConfigurations {
// it without // it without
// permission // permission
final isFileExists = await imageFile.exists(); if (isWeb()) {
return;
}
final dartIoImageFile = File(imageUrl);
final isFileExists = await dartIoImageFile.exists();
if (isFileExists) { if (isFileExists) {
await imageFile.delete(); await dartIoImageFile.delete();
} }
}; };
} }

@ -1,7 +1,6 @@
import 'package:flutter/widgets.dart' show Color; import 'package:flutter/widgets.dart' show Color;
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import '../../../../embeds/embed_types.dart';
import '../../../../embeds/embed_types/camera.dart'; import '../../../../embeds/embed_types/camera.dart';
class QuillToolbarCameraButtonExtraOptions class QuillToolbarCameraButtonExtraOptions
@ -16,9 +15,7 @@ class QuillToolbarCameraButtonExtraOptions
class QuillToolbarCameraButtonOptions extends QuillToolbarBaseButtonOptions< class QuillToolbarCameraButtonOptions extends QuillToolbarBaseButtonOptions<
QuillToolbarCameraButtonOptions, QuillToolbarCameraButtonExtraOptions> { QuillToolbarCameraButtonOptions, QuillToolbarCameraButtonExtraOptions> {
const QuillToolbarCameraButtonOptions({ const QuillToolbarCameraButtonOptions({
required this.onVideoPickCallback,
this.cameraConfigurations = const QuillToolbarCameraConfigurations(), this.cameraConfigurations = const QuillToolbarCameraConfigurations(),
this.webVideoPickImpl,
this.iconSize, this.iconSize,
this.fillColor, this.fillColor,
super.iconData, super.iconData,
@ -33,9 +30,5 @@ class QuillToolbarCameraButtonOptions extends QuillToolbarBaseButtonOptions<
final Color? fillColor; final Color? fillColor;
final OnVideoPickCallback onVideoPickCallback;
final WebVideoPickImpl? webVideoPickImpl;
final QuillToolbarCameraConfigurations cameraConfigurations; final QuillToolbarCameraConfigurations cameraConfigurations;
} }

@ -18,7 +18,7 @@ class QuillToolbarMediaButtonOptions extends QuillToolbarBaseButtonOptions<
const QuillToolbarMediaButtonOptions({ const QuillToolbarMediaButtonOptions({
required this.type, required this.type,
required this.onMediaPickedCallback, required this.onMediaPickedCallback,
required this.onVideoPickCallback, // required this.onVideoPickCallback,
this.dialogBarrierColor, this.dialogBarrierColor,
this.mediaFilePicker, this.mediaFilePicker,
this.childrenSpacing = 16.0, this.childrenSpacing = 16.0,
@ -33,8 +33,6 @@ class QuillToolbarMediaButtonOptions extends QuillToolbarBaseButtonOptions<
this.galleryButtonText, this.galleryButtonText,
this.linkButtonText, this.linkButtonText,
this.validationMessage, this.validationMessage,
this.filePickImpl,
this.webVideoPickImpl,
super.iconData, super.iconData,
super.afterButtonPressed, super.afterButtonPressed,
super.tooltip, super.tooltip,
@ -74,7 +72,4 @@ class QuillToolbarMediaButtonOptions extends QuillToolbarBaseButtonOptions<
final AutovalidateMode autovalidateMode; final AutovalidateMode autovalidateMode;
final String? validationMessage; final String? validationMessage;
final FilePickImpl? filePickImpl;
final OnVideoPickCallback onVideoPickCallback;
final WebVideoPickImpl? webVideoPickImpl;
} }

@ -1,7 +1,6 @@
import 'package:flutter/widgets.dart' show Color; import 'package:flutter/widgets.dart' show Color;
import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill.dart';
import '../../../../embeds/embed_types.dart';
import '../../../../embeds/embed_types/video.dart'; import '../../../../embeds/embed_types/video.dart';
class QuillToolbarVideoButtonExtraOptions class QuillToolbarVideoButtonExtraOptions
@ -18,7 +17,6 @@ class QuillToolbarVideoButtonOptions extends QuillToolbarBaseButtonOptions<
const QuillToolbarVideoButtonOptions({ const QuillToolbarVideoButtonOptions({
this.linkRegExp, this.linkRegExp,
this.dialogTheme, this.dialogTheme,
this.webVideoPickImpl,
this.fillColor, this.fillColor,
this.iconSize, this.iconSize,
super.iconData, super.iconData,
@ -34,8 +32,6 @@ class QuillToolbarVideoButtonOptions extends QuillToolbarBaseButtonOptions<
final QuillDialogTheme? dialogTheme; final QuillDialogTheme? dialogTheme;
final QuillToolbarVideoConfigurations videoConfigurations; final QuillToolbarVideoConfigurations videoConfigurations;
final WebVideoPickImpl? webVideoPickImpl;
final Color? fillColor; final Color? fillColor;
final double? iconSize; final double? iconSize;

Loading…
Cancel
Save