Merge branch 'master' into fix_optional

pull/239/head
Xun Gong 4 years ago
commit e35e1b018f
  1. 2
      analysis_options.yaml
  2. 3
      example/lib/pages/home_page.dart
  3. 9
      example/lib/universal_ui/universal_ui.dart
  4. 0
      example/lib/widgets/responsive_widget.dart
  5. 1
      lib/flutter_quill.dart
  6. 2
      lib/models/documents/attribute.dart
  7. 2
      lib/models/documents/document.dart
  8. 2
      lib/models/documents/history.dart
  9. 2
      lib/models/documents/style.dart
  10. 2
      lib/models/quill_delta.dart
  11. 2
      lib/models/rules/delete.dart
  12. 2
      lib/models/rules/format.dart
  13. 2
      lib/models/rules/insert.dart
  14. 2
      lib/models/rules/rule.dart
  15. 2
      lib/src/models/documents/document.dart
  16. 2
      lib/src/models/documents/nodes/container.dart
  17. 10
      lib/src/models/documents/nodes/embed.dart
  18. 5
      lib/src/models/quill_delta.dart
  19. 5
      lib/src/models/rules/insert.dart
  20. 3
      lib/src/utils/diff_delta.dart
  21. 2
      lib/src/widgets/controller.dart
  22. 47
      lib/src/widgets/cursor.dart
  23. 7
      lib/src/widgets/editor.dart
  24. 2
      lib/src/widgets/keyboard_listener.dart
  25. 24
      lib/src/widgets/raw_editor.dart
  26. 6
      lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart
  27. 8
      lib/src/widgets/simple_viewer.dart
  28. 3
      lib/src/widgets/text_block.dart
  29. 2
      lib/utils/color.dart
  30. 2
      lib/utils/diff_delta.dart
  31. 2
      lib/widgets/box.dart
  32. 2
      lib/widgets/controller.dart
  33. 2
      lib/widgets/cursor.dart
  34. 2
      lib/widgets/default_styles.dart
  35. 2
      lib/widgets/delegate.dart
  36. 2
      lib/widgets/editor.dart
  37. 2
      lib/widgets/image.dart
  38. 2
      lib/widgets/keyboard_listener.dart
  39. 2
      lib/widgets/proxy.dart
  40. 2
      lib/widgets/raw_editor.dart
  41. 3
      lib/widgets/responsive_widget.dart
  42. 2
      lib/widgets/simple_viewer.dart
  43. 2
      lib/widgets/text_block.dart
  44. 2
      lib/widgets/text_line.dart
  45. 2
      lib/widgets/text_selection.dart
  46. 2
      lib/widgets/toolbar.dart

@ -17,6 +17,7 @@ linter:
- avoid_void_async
- cascade_invocations
- directives_ordering
- lines_longer_than_80_chars
- omit_local_variable_types
- prefer_const_constructors
- prefer_const_constructors_in_immutables
@ -31,5 +32,6 @@ linter:
- prefer_single_quotes
- sort_constructors_first
- sort_unnamed_constructors_first
- unnecessary_lambdas
- unnecessary_parenthesis
- unnecessary_string_interpolations

@ -170,7 +170,8 @@ class _HomePageState extends State<HomePage> {
}
// Renders the image picked by imagePicker from local file storage
// You can also upload the picked image to any server (eg : AWS s3 or Firebase) and then return the uploaded image URL
// You can also upload the picked image to any server (eg : AWS s3
// or Firebase) and then return the uploaded image URL.
Future<String> _onImagePickCallback(File file) async {
// Copies the picked file from temporary cache to applications directory
final appDocDir = await getApplicationDocumentsDirectory();

@ -3,9 +3,9 @@ library universal_ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:universal_html/html.dart' as html;
import '../widgets/responsive_widget.dart';
import 'fake_ui.dart' if (dart.library.html) 'real_ui.dart' as ui_instance;
class PlatformViewRegistryFix {
@ -50,8 +50,9 @@ Widget defaultEmbedBuilderWeb(BuildContext context, Embed node) {
default:
throw UnimplementedError(
'Embeddable type "${node.value.type}" is not supported by default embed '
'builder of QuillEditor. You must pass your own builder function to '
'embedBuilder property of QuillEditor or QuillField widgets.');
'Embeddable type "${node.value.type}" is not supported by default '
'embed builder of QuillEditor. You must pass your own builder function '
'to embedBuilder property of QuillEditor or QuillField widgets.',
);
}
}

@ -8,5 +8,4 @@ export 'src/models/quill_delta.dart';
export 'src/widgets/controller.dart';
export 'src/widgets/default_styles.dart';
export 'src/widgets/editor.dart';
export 'src/widgets/responsive_widget.dart';
export 'src/widgets/toolbar.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/documents/attribute.dart';
export '../../src/models/documents/attribute.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/documents/document.dart';
export '../../src/models/documents/document.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/documents/history.dart';
export '../../src/models/documents/history.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/documents/style.dart';
export '../../src/models/documents/style.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/quill_delta.dart';
export '../src/models/quill_delta.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/rules/delete.dart';
export '../../src/models/rules/delete.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/rules/format.dart';
export '../../src/models/rules/format.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/rules/insert.dart';
export '../../src/models/rules/insert.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/models/rules/rule.dart';
export '../../src/models/rules/rule.dart';

@ -250,7 +250,7 @@ class Document {
for (final op in doc.toList()) {
if (!op.isInsert) {
throw ArgumentError.value(doc,
'Document Delta can only contain insert operations but ${op.key} found.');
'Document can only contain insert operations but ${op.key} found.');
}
final style =
op.attributes != null ? Style.fromJson(op.attributes) : null;

@ -79,7 +79,7 @@ abstract class Container<T extends Node?> extends Node {
if (last != null) last.adjust();
}
/// Queries the child [Node] at specified character [offset] in this container.
/// Queries the child [Node] at [offset] in this container.
///
/// The result may contain the found node or `null` if no node is found
/// at specified offset.

@ -4,7 +4,7 @@
///
/// * [BlockEmbed] which represents a block embed.
class Embeddable {
Embeddable(this.type, this.data);
const Embeddable(this.type, this.data);
/// The type of this object.
final String type;
@ -32,9 +32,11 @@ class Embeddable {
/// the document model itself does not make any assumptions about the types
/// of embedded objects and allows users to define their own types.
class BlockEmbed extends Embeddable {
BlockEmbed(String type, String data) : super(type, data);
const BlockEmbed(String type, String data) : super(type, data);
static BlockEmbed horizontalRule = BlockEmbed('divider', 'hr');
static const String horizontalRuleType = 'divider';
static BlockEmbed horizontalRule = const BlockEmbed(horizontalRuleType, 'hr');
static BlockEmbed image(String imageUrl) => BlockEmbed('image', imageUrl);
static const String imageType = 'image';
static BlockEmbed image(String imageUrl) => BlockEmbed(imageType, imageUrl);
}

@ -1,5 +1,6 @@
// Copyright (c) 2018, Anatoly Pulyaevskiy. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.
// Copyright (c) 2018, Anatoly Pulyaevskiy. All rights reserved. Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
/// Implementation of Quill Delta format in Dart.
library quill_delta;

@ -167,7 +167,8 @@ class AutoExitBlockRule extends InsertRule {
// First check if `cur` length is greater than 1, this would indicate
// that it contains multiple newline characters which share the same style.
// This would mean we are not on the last line yet.
// `cur.value as String` is safe since we already called isEmptyLine and know it contains a newline
// `cur.value as String` is safe since we already called isEmptyLine and
// know it contains a newline
if ((cur.value as String).length > 1) {
// We are not on the last line of this block, ignore.
return null;
@ -188,7 +189,7 @@ class AutoExitBlockRule extends InsertRule {
// therefore we can exit this block.
final attributes = cur.attributes ?? <String, dynamic>{};
final k = attributes.keys
.firstWhere((k) => Attribute.blockKeysExceptHeader.contains(k));
.firstWhere(Attribute.blockKeysExceptHeader.contains);
attributes[k] = null;
// retain(1) should be '\n', set it with no attribute
return Delta()..retain(index + (len ?? 0))..retain(1, attributes);

@ -79,7 +79,8 @@ int getPositionDelta(Delta user, Delta actual) {
final userOperation = userItr.next(length as int);
final actualOperation = actualItr.next(length);
if (userOperation.length != actualOperation.length) {
throw 'userOp ${userOperation.length} does not match actualOp ${actualOperation.length}';
throw 'userOp ${userOperation.length} does not match actualOp '
'${actualOperation.length}';
}
if (userOperation.key == actualOperation.key) {
continue;

@ -69,7 +69,7 @@ class QuillController extends ChangeNotifier {
// if (this.selection.extentOffset >= document.length) {
// // cursor exceeds the length of document, position it in the end
// updateSelection(
// TextSelection.collapsed(offset: document.length), ChangeSource.LOCAL);
// TextSelection.collapsed(offset: document.length), ChangeSource.LOCAL);
updateSelection(
TextSelection.collapsed(offset: selection.baseOffset + len!),
ChangeSource.LOCAL);

@ -267,8 +267,9 @@ class CursorPainter {
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
// Override the height to take the full height of the glyph at the TextPosition
// when not on iOS. iOS has special handling that creates a taller caret.
// Override the height to take the full height of the glyph at the
// TextPosition when not on iOS. iOS has special handling that
// creates a taller caret.
caretRect = Rect.fromLTWH(
caretRect.left,
caretRect.top - 2.0,
@ -291,25 +292,39 @@ class CursorPainter {
}
}
final caretPosition = editable!.localToGlobal(caretRect.topLeft);
final pixelMultiple = 1.0 / devicePixelRatio;
caretRect = caretRect.shift(Offset(
caretPosition.dx.isFinite
? (caretPosition.dx / pixelMultiple).round() * pixelMultiple -
caretPosition.dx
: caretPosition.dx,
caretPosition.dy.isFinite
? (caretPosition.dy / pixelMultiple).round() * pixelMultiple -
caretPosition.dy
: caretPosition.dy));
final pixelPerfectOffset =
_getPixelPerfectCursorOffset(editable!, caretRect, devicePixelRatio);
if (!pixelPerfectOffset.isFinite) {
return;
}
caretRect = caretRect.shift(pixelPerfectOffset);
final paint = Paint()..color = color;
if (style.radius == null) {
canvas.drawRect(caretRect, paint);
return;
} else {
final caretRRect = RRect.fromRectAndRadius(caretRect, style.radius!);
canvas.drawRRect(caretRRect, paint);
}
}
Offset _getPixelPerfectCursorOffset(
RenderContentProxyBox editable,
Rect caretRect,
double devicePixelRatio,
) {
final caretPosition = editable.localToGlobal(caretRect.topLeft);
final pixelMultiple = 1.0 / devicePixelRatio;
final pixelPerfectOffsetX = caretPosition.dx.isFinite
? (caretPosition.dx / pixelMultiple).round() * pixelMultiple -
caretPosition.dx
: caretPosition.dx;
final pixelPerfectOffsetY = caretPosition.dy.isFinite
? (caretPosition.dy / pixelMultiple).round() * pixelMultiple -
caretPosition.dy
: caretPosition.dy;
final caretRRect = RRect.fromRectAndRadius(caretRect, style.radius!);
canvas.drawRRect(caretRRect, paint);
return Offset(pixelPerfectOffsetX, pixelPerfectOffsetY);
}
}

@ -107,9 +107,10 @@ Widget _defaultEmbedBuilder(BuildContext context, leaf.Embed node) {
: Image.file(io.File(imageUrl));
default:
throw UnimplementedError(
'Embeddable type "${node.value.type}" is not supported by default embed '
'builder of QuillEditor. You must pass your own builder function to '
'embedBuilder property of QuillEditor or QuillField widgets.');
'Embeddable type "${node.value.type}" is not supported by default '
'embed builder of QuillEditor. You must pass your own builder function '
'to embedBuilder property of QuillEditor or QuillField widgets.',
);
}
}

@ -64,7 +64,7 @@ class KeyboardListener {
bool handleRawKeyEvent(RawKeyEvent event) {
if (kIsWeb) {
// On web platform, we should ignore the key because it's processed already.
// On web platform, we ignore the key because it's already processed.
return false;
}

@ -483,8 +483,12 @@ class RawEditorState extends EditorState
..startCursorTimer();
}
SchedulerBinding.instance!.addPostFrameCallback(
(_) => _updateOrDisposeSelectionOverlayIfNeeded());
SchedulerBinding.instance!.addPostFrameCallback((_) {
if (!mounted) {
return;
}
_updateOrDisposeSelectionOverlayIfNeeded();
});
if (mounted) {
setState(() {
// Use widget.controller.value in build()
@ -559,13 +563,17 @@ class RawEditorState extends EditorState
if (widget.scrollable) {
_showCaretOnScreenScheduled = false;
final viewport = RenderAbstractViewport.of(getRenderEditor());
final renderEditor = getRenderEditor();
if (renderEditor == null) {
return;
}
final editorOffset = getRenderEditor()!
.localToGlobal(const Offset(0, 0), ancestor: viewport);
final viewport = RenderAbstractViewport.of(renderEditor);
final editorOffset =
renderEditor.localToGlobal(const Offset(0, 0), ancestor: viewport);
final offsetInViewport = _scrollController!.offset + editorOffset.dy;
final offset = getRenderEditor()!.getOffsetToRevealCursor(
final offset = renderEditor.getOffsetToRevealCursor(
_scrollController!.position.viewportDimension,
_scrollController!.offset,
offsetInViewport,
@ -584,7 +592,7 @@ class RawEditorState extends EditorState
@override
RenderEditor? getRenderEditor() {
return _editorKey.currentContext!.findRenderObject() as RenderEditor?;
return _editorKey.currentContext?.findRenderObject() as RenderEditor?;
}
@override
@ -672,7 +680,7 @@ class RawEditorState extends EditorState
@override
void userUpdateTextEditingValue(
TextEditingValue value, SelectionChangedCause cause) {
// TODO: implement userUpdateTextEditingValue
updateEditingValue(value);
}
}

@ -103,7 +103,11 @@ mixin RawEditorStateTextInputClientMixin on EditorState
final shouldRemember =
getTextEditingValue().text != _lastKnownRemoteTextEditingValue!.text;
_lastKnownRemoteTextEditingValue = actualValue;
_textInputConnection!.setEditingState(actualValue);
_textInputConnection!.setEditingState(
// Set composing to (-1, -1), otherwise an exception will be thrown if
// the values are different.
actualValue.copyWith(composing: const TextRange(start: -1, end: -1)),
);
if (shouldRemember) {
// Only keep track if text changed (selection changes are not relevant)
_sentRemoteValues.add(actualValue);

@ -109,9 +109,11 @@ class _QuillSimpleViewerState extends State<QuillSimpleViewer>
: Image.file(io.File(imageUrl));
default:
throw UnimplementedError(
'Embeddable type "${node.value.type}" is not supported by default embed '
'builder of QuillEditor. You must pass your own builder function to '
'embedBuilder property of QuillEditor or QuillField widgets.');
'Embeddable type "${node.value.type}" is not supported by default '
'embed builder of QuillEditor. You must pass your own builder '
'function to embedBuilder property of QuillEditor or QuillField '
'widgets.',
);
}
}

@ -512,7 +512,8 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
offset.translate(decorationPadding.left, decorationPadding.top);
_painter!.paint(context.canvas, decorationOffset, filledConfiguration);
if (debugSaveCount != context.canvas.getSaveCount()) {
throw '${_decoration.runtimeType} painter had mismatching save and restore calls.';
throw '${_decoration.runtimeType} painter had mismatching save and '
'restore calls.';
}
if (decoration.isComplex) {
context.setIsComplexHint();

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/utils/color.dart';
export '../src/utils/color.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../../src/utils/diff_delta.dart';
export '../src/utils/diff_delta.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/box.dart';
export '../src/widgets/box.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/controller.dart';
export '../src/widgets/controller.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/cursor.dart';
export '../src/widgets/cursor.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/default_styles.dart';
export '../src/widgets/default_styles.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/delegate.dart';
export '../src/widgets/delegate.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/editor.dart';
export '../src/widgets/editor.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/image.dart';
export '../src/widgets/image.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/keyboard_listener.dart';
export '../src/widgets/keyboard_listener.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/proxy.dart';
export '../src/widgets/proxy.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/raw_editor.dart';
export '../src/widgets/raw_editor.dart';

@ -1,3 +0,0 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/responsive_widget.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/simple_viewer.dart';
export '../src/widgets/simple_viewer.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/text_block.dart';
export '../src/widgets/text_block.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/text_line.dart';
export '../src/widgets/text_line.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/text_selection.dart';
export '../src/widgets/text_selection.dart';

@ -1,3 +1,3 @@
/// TODO: Remove this file in the next breaking release, because implementation
/// files should be located in the src folder, https://bit.ly/3fA23Yz.
export '../../src/widgets/toolbar.dart';
export '../src/widgets/toolbar.dart';

Loading…
Cancel
Save