Fix style settings (#1962)

* Value setting Stateful toolbar buttons derive from base class

* Rename base class as QuillToolbarBaseValueButton

* Removed deprecated functions

* Move clipboard actions to QuillController

* Fix: collectAllIndividualStylesAndEmbed for result span

* Add: Clipboard toolbar buttons

* Add: test for QuillController clipboard
Dart Formatted

* Translation Justify

* Translation alignJustify

* Fix: Translation en-US

* Fix style settings

---------

Co-authored-by: Douglas Ward <dward@scied.com>
pull/1964/head^2 v9.5.2
AtlasAutocode 9 months ago committed by GitHub
parent 02ad0517f5
commit 858d61a7a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 19
      example/lib/screens/quill/my_quill_editor.dart
  2. 34
      lib/src/models/documents/document.dart
  3. 8
      lib/src/widgets/raw_editor/raw_editor_state.dart
  4. 85
      test/utils/document_test.dart

@ -30,6 +30,7 @@ class MyQuillEditor extends StatelessWidget {
@override
Widget build(BuildContext context) {
final defaultTextStyle = DefaultTextStyle.of(context);
return QuillEditor(
scrollController: scrollController,
focusNode: focusNode,
@ -43,27 +44,21 @@ class MyQuillEditor extends StatelessWidget {
useTextColorForDot: true,
),
),
customStyles: const DefaultStyles(
customStyles: DefaultStyles(
h1: DefaultTextBlockStyle(
TextStyle(
defaultTextStyle.style.copyWith(
fontSize: 32,
height: 1.15,
fontWeight: FontWeight.w300,
),
VerticalSpacing(16, 0),
VerticalSpacing(0, 0),
const VerticalSpacing(16, 0),
const VerticalSpacing(0, 0),
null,
),
sizeSmall: TextStyle(fontSize: 9),
subscript: TextStyle(
fontFeatures: [FontFeature.subscripts()],
),
superscript: TextStyle(
fontFeatures: [FontFeature.superscripts()],
),
sizeSmall: defaultTextStyle.style.copyWith(fontSize: 9),
),
scrollable: true,
placeholder: 'Start writting your notes...',
placeholder: 'Start writing your notes...',
padding: const EdgeInsets.all(16),
onImagePaste: (imageBytes) async {
if (isWeb()) {

@ -177,26 +177,46 @@ class Document {
/// Only attributes applied to all characters within this range are
/// included in the result.
/// Special case of no-selection at start of empty line: gets inline style(s) from preceding non-empty line.
Style collectStyle(int index, int len) {
final res = queryChild(index);
Style rangeStyle;
var res = queryChild(index);
if (len > 0) {
return (res.node as Line).collectStyle(res.offset, len);
}
//
if (res.offset == 0) {
return rangeStyle = (res.node as Line).collectStyle(res.offset, len);
final current = (res.node as Line).collectStyle(0, 0);
//
while ((res.node as Line).length == 1 && index > 0) {
res = queryChild(--index);
}
//
final style = (res.node as Line).collectStyle(res.offset, 0);
final remove = <Attribute>{};
for (final attr in style.attributes.values) {
if (!Attribute.inlineKeys.contains(attr.key)) {
if (!current.containsKey(attr.key)) {
remove.add(attr);
}
}
}
if (remove.isNotEmpty) {
return style.removeAll(remove);
}
return style;
}
rangeStyle = (res.node as Line).collectStyle(res.offset - 1, len);
final linkAttribute = rangeStyle.attributes[Attribute.link.key];
//
final style = (res.node as Line).collectStyle(res.offset - 1, 0);
final linkAttribute = style.attributes[Attribute.link.key];
if ((linkAttribute != null) &&
(linkAttribute.value !=
(res.node as Line)
.collectStyle(res.offset, len)
.attributes[Attribute.link.key]
?.value)) {
return rangeStyle.removeAll({linkAttribute});
return style.removeAll({linkAttribute});
}
return rangeStyle;
return style;
}
/// Returns all styles and Embed for each node within selection

@ -875,6 +875,14 @@ class QuillRawEditorState extends EditorState
..formatSelection(attribute)
// Remove the added newline.
..replaceText(controller.selection.baseOffset + 1, 1, '', null);
//
final style =
controller.document.collectStyle(controller.selection.baseOffset, 0);
if (style.isNotEmpty) {
for (final attr in style.values) {
controller.formatSelection(attr);
}
}
}
void _handleSelectionChanged(

@ -0,0 +1,85 @@
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/quill_delta.dart';
import 'package:test/test.dart';
void main() {
group('collectStyle', () {
/// Enter key inserts newline as plain text without inline styles.
/// collectStyle needs to retrieve style of preceding line
test('Simulate double enter key at end', () {
final delta = Delta()
..insert('data\n')
..insert('second\n', <String, dynamic>{'bold': true})
..insert('\n\nplain\n');
final document = Document.fromDelta(delta);
//
expect(document.getPlainText(0, document.length),
'data\nsecond\n\n\nplain\n');
expect(document.length, 20);
//
expect('data\n', document.getPlainText(0, 5));
for (var index = 0; index < 5; index++) {
expect(const Style(), document.collectStyle(index, 0));
}
//
expect('second\n', document.getPlainText(5, 7));
for (var index = 5; index < 12; index++) {
expect(const Style.attr({'bold': Attribute.bold}),
document.collectStyle(index, 0));
}
//
expect('\n\n', document.getPlainText(12, 2));
for (var index = 12; index < 14; index++) {
expect(const Style.attr({'bold': Attribute.bold}),
document.collectStyle(index, 0));
}
//
for (var index = 14; index < document.length; index++) {
expect(const Style(), document.collectStyle(index, 0));
}
});
test('No selection', () {
final delta = Delta()
..insert('plain\n')
..insert('bold\n', <String, dynamic>{'bold': true})
..insert('italic\n', <String, dynamic>{'italic': true});
final document = Document.fromDelta(delta);
//
expect(
document.getPlainText(0, document.length), 'plain\nbold\nitalic\n');
expect(document.length, 18);
//
for (var index = 0; index < 6; index++) {
expect(const Style(), document.collectStyle(index, 0));
}
//
for (var index = 6; index < 11; index++) {
expect(const Style.attr({'bold': Attribute.bold}),
document.collectStyle(index, 0));
}
//
for (var index = 11; index < document.length; index++) {
expect(const Style.attr({'italic': Attribute.italic}),
document.collectStyle(index, 0));
}
});
test('Selection', () {
final delta = Delta()
..insert('data\n')
..insert('second\n', <String, dynamic>{'bold': true});
final document = Document.fromDelta(delta);
//
expect(const Style(), document.collectStyle(0, 4));
expect(const Style(), document.collectStyle(1, 3));
//
expect(const Style.attr({'bold': Attribute.bold}),
document.collectStyle(5, 3));
expect(const Style.attr({'bold': Attribute.bold}),
document.collectStyle(8, 3));
//
expect(const Style(), document.collectStyle(3, 3));
});
});
}
Loading…
Cancel
Save