Merge branch 'master' into fix2

pull/142/head
Xun Gong 4 years ago
commit 154b58db92
  1. 16
      .github/ISSUE_TEMPLATE/issue-template.md
  2. 3
      CHANGELOG.md
  3. 8
      example/lib/widgets/demo_scaffold.dart
  4. 5
      lib/widgets/default_styles.dart
  5. 4
      lib/widgets/editor.dart
  6. 27
      lib/widgets/raw_editor.dart
  7. 10
      lib/widgets/text_block.dart
  8. 108
      lib/widgets/toolbar.dart
  9. 2
      pubspec.yaml

@ -0,0 +1,16 @@
---
name: Issue template
about: Common things to fill
title: "[Web] or [Mobile] or [Desktop]"
labels: ''
assignees: ''
---
My issue is about [Web]
My issue is about [Mobile]
My issue is about [Desktop]
I have tried running `example` directory successfully before creating an issue here AND it is NOT a stupid question.
Please note that we are using stable channel. If you are using beta or master channel, those are not supported.

@ -1,3 +1,6 @@
## [1.1.7]
* Fix text selection in read-only mode.
## [1.1.6] ## [1.1.6]
* Remove universal_html dependency. * Remove universal_html dependency.

@ -19,12 +19,12 @@ class DemoScaffold extends StatefulWidget {
final bool showToolbar; final bool showToolbar;
const DemoScaffold({ const DemoScaffold({
Key? key,
required this.documentFilename, required this.documentFilename,
required this.builder, required this.builder,
this.actions, this.actions,
this.showToolbar = true, this.showToolbar = true,
this.floatingActionButton, this.floatingActionButton,
Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
@ -59,14 +59,14 @@ class _DemoScaffoldState extends State<DemoScaffold> {
final doc = Document.fromJson(jsonDecode(result)); final doc = Document.fromJson(jsonDecode(result));
setState(() { setState(() {
_controller = QuillController( _controller = QuillController(
document: doc, selection: TextSelection.collapsed(offset: 0)); document: doc, selection: const TextSelection.collapsed(offset: 0));
_loading = false; _loading = false;
}); });
} catch (error) { } catch (error) {
final doc = Document()..insert(0, 'Empty asset'); final doc = Document()..insert(0, 'Empty asset');
setState(() { setState(() {
_controller = QuillController( _controller = QuillController(
document: doc, selection: TextSelection.collapsed(offset: 0)); document: doc, selection: const TextSelection.collapsed(offset: 0));
_loading = false; _loading = false;
}); });
} }
@ -97,7 +97,7 @@ class _DemoScaffoldState extends State<DemoScaffold> {
), ),
floatingActionButton: widget.floatingActionButton, floatingActionButton: widget.floatingActionButton,
body: _loading body: _loading
? Center(child: Text('Loading...')) ? const Center(child: Text('Loading...'))
: widget.builder(context, _controller), : widget.builder(context, _controller),
); );
} }

@ -59,6 +59,7 @@ class DefaultStyles {
final DefaultTextBlockStyle? code; final DefaultTextBlockStyle? code;
final DefaultTextBlockStyle? indent; final DefaultTextBlockStyle? indent;
final DefaultTextBlockStyle? align; final DefaultTextBlockStyle? align;
final DefaultTextBlockStyle? leading;
DefaultStyles( DefaultStyles(
{this.h1, {this.h1,
@ -77,6 +78,7 @@ class DefaultStyles {
this.code, this.code,
this.indent, this.indent,
this.align, this.align,
this.leading,
this.sizeSmall, this.sizeSmall,
this.sizeLarge, this.sizeLarge,
this.sizeHuge}); this.sizeHuge});
@ -183,6 +185,8 @@ class DefaultStyles {
baseStyle, baseSpacing, const Tuple2(0.0, 6.0), null), baseStyle, baseSpacing, const Tuple2(0.0, 6.0), null),
align: DefaultTextBlockStyle( align: DefaultTextBlockStyle(
baseStyle, const Tuple2(0.0, 0.0), const Tuple2(0.0, 0.0), null), baseStyle, const Tuple2(0.0, 0.0), const Tuple2(0.0, 0.0), null),
leading: DefaultTextBlockStyle(
baseStyle, const Tuple2(0.0, 0.0), const Tuple2(0.0, 0.0), null),
sizeSmall: const TextStyle(fontSize: 10.0), sizeSmall: const TextStyle(fontSize: 10.0),
sizeLarge: const TextStyle(fontSize: 18.0), sizeLarge: const TextStyle(fontSize: 18.0),
sizeHuge: const TextStyle(fontSize: 22.0)); sizeHuge: const TextStyle(fontSize: 22.0));
@ -206,6 +210,7 @@ class DefaultStyles {
code: other.code ?? code, code: other.code ?? code,
indent: other.indent ?? indent, indent: other.indent ?? indent,
align: other.align ?? align, align: other.align ?? align,
leading: other.leading ?? leading,
sizeSmall: other.sizeSmall ?? sizeSmall, sizeSmall: other.sizeSmall ?? sizeSmall,
sizeLarge: other.sizeLarge ?? sizeLarge, sizeLarge: other.sizeLarge ?? sizeLarge,
sizeHuge: other.sizeHuge ?? sizeHuge); sizeHuge: other.sizeHuge ?? sizeHuge);

@ -258,10 +258,10 @@ class _QuillEditorState extends State<QuillEditor>
widget.placeholder, widget.placeholder,
widget.onLaunchUrl, widget.onLaunchUrl,
ToolbarOptions( ToolbarOptions(
copy: true, copy: widget.enableInteractiveSelection,
cut: widget.enableInteractiveSelection, cut: widget.enableInteractiveSelection,
paste: widget.enableInteractiveSelection, paste: widget.enableInteractiveSelection,
selectAll: true, selectAll: widget.enableInteractiveSelection,
), ),
theme.platform == TargetPlatform.iOS || theme.platform == TargetPlatform.iOS ||
theme.platform == TargetPlatform.android, theme.platform == TargetPlatform.android,

@ -371,6 +371,10 @@ class RawEditorState extends EditorState
_textInputConnection != null && _textInputConnection!.attached; _textInputConnection != null && _textInputConnection!.attached;
void openConnectionIfNeeded() { void openConnectionIfNeeded() {
if (!shouldCreateInputConnection) {
return;
}
if (!hasConnection) { if (!hasConnection) {
_lastKnownRemoteTextEditingValue = textEditingValue; _lastKnownRemoteTextEditingValue = textEditingValue;
_textInputConnection = TextInput.attach( _textInputConnection = TextInput.attach(
@ -388,11 +392,8 @@ class RawEditorState extends EditorState
_textInputConnection!.setEditingState(_lastKnownRemoteTextEditingValue!); _textInputConnection!.setEditingState(_lastKnownRemoteTextEditingValue!);
// _sentRemoteValues.add(_lastKnownRemoteTextEditingValue); // _sentRemoteValues.add(_lastKnownRemoteTextEditingValue);
} }
_textInputConnection!.show(); _textInputConnection!.show();
if (widget.readOnly) {
// temporary hack to dismiss keyboard
SystemChannels.textInput.invokeMethod('TextInput.hide');
}
} }
void closeConnectionIfNeeded() { void closeConnectionIfNeeded() {
@ -897,6 +898,12 @@ class RawEditorState extends EditorState
_onChangeTextEditingValue(); _onChangeTextEditingValue();
} else { } else {
requestKeyboard(); requestKeyboard();
if (mounted) {
setState(() {
// Use widget.controller.value in build()
// Trigger build and updateChildren
});
}
} }
} }
@ -912,11 +919,12 @@ class RawEditorState extends EditorState
SchedulerBinding.instance!.addPostFrameCallback( SchedulerBinding.instance!.addPostFrameCallback(
(Duration _) => _updateOrDisposeSelectionOverlayIfNeeded()); (Duration _) => _updateOrDisposeSelectionOverlayIfNeeded());
if (!mounted) return; if (mounted) {
setState(() { setState(() {
// Use widget.controller.value in build() // Use widget.controller.value in build()
// Trigger build and updateChildren // Trigger build and updateChildren
}); });
}
} }
void _updateOrDisposeSelectionOverlayIfNeeded() { void _updateOrDisposeSelectionOverlayIfNeeded() {
@ -1108,6 +1116,7 @@ class RawEditorState extends EditorState
return false; return false;
} }
_selectionOverlay!.update(textEditingValue);
_selectionOverlay!.showToolbar(); _selectionOverlay!.showToolbar();
return true; return true;
} }

@ -141,7 +141,7 @@ class EditableTextBlock extends StatelessWidget {
index: index, index: index,
indentLevelCounts: indentLevelCounts, indentLevelCounts: indentLevelCounts,
count: count, count: count,
style: defaultStyles!.paragraph!.style, style: defaultStyles!.leading!.style,
attrs: attrs, attrs: attrs,
width: 32.0, width: 32.0,
padding: 8.0, padding: 8.0,
@ -150,20 +150,20 @@ class EditableTextBlock extends StatelessWidget {
if (attrs[Attribute.list.key] == Attribute.ul) { if (attrs[Attribute.list.key] == Attribute.ul) {
return _BulletPoint( return _BulletPoint(
style: defaultStyles!.paragraph!.style style:
.copyWith(fontWeight: FontWeight.bold), defaultStyles!.leading!.style.copyWith(fontWeight: FontWeight.bold),
width: 32, width: 32,
); );
} }
if (attrs[Attribute.list.key] == Attribute.checked) { if (attrs[Attribute.list.key] == Attribute.checked) {
return _Checkbox( return _Checkbox(
style: defaultStyles!.paragraph!.style, width: 32, isChecked: true); style: defaultStyles!.leading!.style, width: 32, isChecked: true);
} }
if (attrs[Attribute.list.key] == Attribute.unchecked) { if (attrs[Attribute.list.key] == Attribute.unchecked) {
return _Checkbox( return _Checkbox(
style: defaultStyles!.paragraph!.style, width: 32, isChecked: false); style: defaultStyles!.leading!.style, width: 32, isChecked: false);
} }
if (attrs.containsKey(Attribute.codeBlock.key)) { if (attrs.containsKey(Attribute.codeBlock.key)) {

@ -430,56 +430,62 @@ class _SelectHeaderStyleButtonState extends State<SelectHeaderStyleButton> {
Widget _selectHeadingStyleButtonBuilder(BuildContext context, Attribute? value, Widget _selectHeadingStyleButtonBuilder(BuildContext context, Attribute? value,
ValueChanged<Attribute?> onSelected) { ValueChanged<Attribute?> onSelected) {
final style = const TextStyle(fontSize: 13);
final Map<Attribute, String> _valueToText = { final Map<Attribute, String> _valueToText = {
Attribute.header: 'Normal text', Attribute.header: 'N',
Attribute.h1: 'Heading 1', Attribute.h1: 'H1',
Attribute.h2: 'Heading 2', Attribute.h2: 'H2',
Attribute.h3: 'Heading 3', Attribute.h3: 'H3',
}; };
return QuillDropdownButton<Attribute?>( List<Attribute> _valueAttribute = [
highlightElevation: 0, Attribute.header,
hoverElevation: 0, Attribute.h1,
height: iconSize * 1.77, Attribute.h2,
fillColor: Theme.of(context).canvasColor, Attribute.h3
initialValue: value, ];
items: [ List<String> _valueString = ['N', 'H1', 'H2', 'H3'];
PopupMenuItem(
value: Attribute.header, final theme = Theme.of(context);
height: iconSize * 1.77, final style = TextStyle(
child: Text(_valueToText[Attribute.header]!, style: style), fontWeight: FontWeight.w600,
), fontSize: iconSize * 0.7,
PopupMenuItem( );
value: Attribute.h1,
height: iconSize * 1.77, return Row(
child: Text(_valueToText[Attribute.h1]!, style: style), mainAxisSize: MainAxisSize.min,
), children: List.generate(4, (index) {
PopupMenuItem( return Padding(
value: Attribute.h2, padding: const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
height: iconSize * 1.77, child: ConstrainedBox(
child: Text(_valueToText[Attribute.h2]!, style: style), constraints: BoxConstraints.tightFor(
), width: iconSize * 1.77,
PopupMenuItem( height: iconSize * 1.77,
value: Attribute.h3, ),
height: iconSize * 1.77, child: RawMaterialButton(
child: Text(_valueToText[Attribute.h3]!, style: style), hoverElevation: 0,
), highlightElevation: 0,
], elevation: 0.0,
onSelected: onSelected, visualDensity: VisualDensity.compact,
child: Text( shape:
!kIsWeb RoundedRectangleBorder(borderRadius: BorderRadius.circular(2)),
? _valueToText[value!]! fillColor: _valueToText[value] == _valueString[index]
: _valueToText[value!.key == 'header' ? theme.toggleableActiveColor
? Attribute.header : theme.canvasColor,
: (value.key == 'h1') onPressed: () {
? Attribute.h1 onSelected(_valueAttribute[index]);
: (value.key == 'h2') },
? Attribute.h2 child: Text(
: Attribute.h3]!, _valueString[index],
style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600), style: style.copyWith(
), color: _valueToText[value] == _valueString[index]
? theme.primaryIconTheme.color
: theme.iconTheme.color,
),
),
),
),
);
}),
); );
} }
@ -1027,11 +1033,11 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget {
Visibility( Visibility(
visible: showHeaderStyle, visible: showHeaderStyle,
child: VerticalDivider( child: VerticalDivider(
indent: 16, endIndent: 16, color: Colors.grey.shade400)), indent: 12, endIndent: 12, color: Colors.grey.shade400)),
Visibility( Visibility(
visible: showHeaderStyle, visible: showHeaderStyle,
child: SelectHeaderStyleButton(controller: controller)), child: SelectHeaderStyleButton(controller: controller)),
VerticalDivider(indent: 16, endIndent: 16, color: Colors.grey.shade400), VerticalDivider(indent: 12, endIndent: 12, color: Colors.grey.shade400),
Visibility( Visibility(
visible: showListNumbers, visible: showListNumbers,
child: ToggleStyleButton( child: ToggleStyleButton(
@ -1070,7 +1076,7 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget {
!showListCheck && !showListCheck &&
!showCodeBlock, !showCodeBlock,
child: VerticalDivider( child: VerticalDivider(
indent: 16, endIndent: 16, color: Colors.grey.shade400)), indent: 12, endIndent: 12, color: Colors.grey.shade400)),
Visibility( Visibility(
visible: showQuote, visible: showQuote,
child: ToggleStyleButton( child: ToggleStyleButton(
@ -1098,7 +1104,7 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget {
Visibility( Visibility(
visible: showQuote, visible: showQuote,
child: VerticalDivider( child: VerticalDivider(
indent: 16, endIndent: 16, color: Colors.grey.shade400)), indent: 12, endIndent: 12, color: Colors.grey.shade400)),
Visibility( Visibility(
visible: showLink, child: LinkStyleButton(controller: controller)), visible: showLink, child: LinkStyleButton(controller: controller)),
Visibility( Visibility(

@ -1,6 +1,6 @@
name: flutter_quill name: flutter_quill
description: A rich text editor supporting mobile and web (Demo App @ bulletjournal.us) description: A rich text editor supporting mobile and web (Demo App @ bulletjournal.us)
version: 1.1.6 version: 1.1.7
#author: bulletjournal #author: bulletjournal
homepage: https://bulletjournal.us/home/index.html homepage: https://bulletjournal.us/home/index.html
repository: https://github.com/singerdmx/flutter-quill repository: https://github.com/singerdmx/flutter-quill

Loading…
Cancel
Save