Bug fix and other changes

pull/1486/head
Ellet 2 years ago
parent 2610dab118
commit c2d1942af6
No known key found for this signature in database
GPG Key ID: C488CC70BBCEF0D1
  1. 10
      .github/ISSUE_TEMPLATE/issue-template.md
  2. 65
      lib/src/models/config/toolbar/buttons/link_style2.dart
  3. 2
      lib/src/models/config/toolbar/buttons/select_alignment.dart
  4. 17
      lib/src/models/config/toolbar/buttons/select_header_style.dart
  5. 14
      lib/src/models/rules/insert.dart
  6. 4
      lib/src/widgets/toolbar/buttons/arrow_indicated_list.dart
  7. 18
      lib/src/widgets/toolbar/buttons/link_style.dart
  8. 186
      lib/src/widgets/toolbar/buttons/link_style2.dart
  9. 64
      lib/src/widgets/toolbar/buttons/select_alignment.dart
  10. 44
      lib/src/widgets/toolbar/buttons/select_header_style.dart

@ -1,20 +1,16 @@
---
name: Issue template
about: Common things to fill
title: "[Web] or [Mobile] or [Desktop]"
title: "Issue in [Mobile, Desktop, Web]"
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.
Please note that we are using <b>latest</b> flutter version in stable channel on branch master. If you are using beta or master channel, or you are not using <b>latest</b> flutter version in stable channel, you may experience error.
<!-- Did you try the running `example` directory?? How does it goes -->
<!-- Please explain how to encounter the issue in details if possible -->
<!-- Don't forgot to mention the platform you are testing in -->

@ -0,0 +1,65 @@
import 'package:flutter/widgets.dart';
import '../../../../widgets/controller.dart';
import '../../../themes/quill_dialog_theme.dart';
import '../../../themes/quill_icon_theme.dart';
import 'base.dart';
class QuillToolbarLinkStyleButton2ExtraOptions
extends QuillToolbarBaseButtonExtraOptions {
const QuillToolbarLinkStyleButton2ExtraOptions({
required super.controller,
required super.context,
required super.onPressed,
});
}
class QuillToolbarLinkStyleButton2Options extends QuillToolbarBaseButtonOptions<
QuillToolbarLinkStyleButton2Options,
QuillToolbarLinkStyleButton2ExtraOptions> {
const QuillToolbarLinkStyleButton2Options({
this.iconSize,
this.dialogTheme,
this.constraints,
this.addLinkLabel,
this.editLinkLabel,
this.linkColor,
this.validationMessage,
this.buttonSize,
this.dialogBarrierColor,
this.childrenSpacing = 16.0,
this.autovalidateMode = AutovalidateMode.disabled,
super.iconData,
super.afterButtonPressed,
super.tooltip,
super.iconTheme,
super.childBuilder,
super.controller,
});
final double? iconSize;
final QuillDialogTheme? dialogTheme;
/// The constrains for dialog.
final BoxConstraints? constraints;
/// The text of label in link add mode.
final String? addLinkLabel;
/// The text of label in link edit mode.
final String? editLinkLabel;
/// The color of URL.
final Color? linkColor;
/// The margin between child widgets in the dialog.
final double childrenSpacing;
final AutovalidateMode autovalidateMode;
final String? validationMessage;
/// The size of dialog buttons.
final Size? buttonSize;
final Color? dialogBarrierColor;
}

@ -19,6 +19,8 @@ class QuillToolbarSelectAlignmentButtonOptions
this.tooltips,
this.iconSize,
super.afterButtonPressed,
/// This will called on every select alignment button
super.childBuilder,
super.controller,
super.iconTheme,

@ -20,20 +20,21 @@ class QuillToolbarSelectHeaderStyleButtonsOptions
super.afterButtonPressed,
super.childBuilder,
super.controller,
super.iconData,
super.iconTheme,
super.tooltip,
this.axis,
this.attributes = const [
Attribute.header,
Attribute.h1,
Attribute.h2,
Attribute.h3,
],
this.attributes,
this.iconSize,
});
final List<Attribute> attributes;
/// Default value:
/// const [
/// Attribute.header,
/// Attribute.h1,
/// Attribute.h2,
/// Attribute.h3,
/// ]
final List<Attribute>? attributes;
/// By default we will the toolbar axis from [QuillToolbarConfigurations]
final Axis? axis;

@ -358,14 +358,14 @@ class AutoFormatMultipleLinksRule extends InsertRule {
// TODO: You might want to rename those but everywhere even in
// flutter_quill_extensions
static const _oneLinePattern =
static const _oneLineLinkPattern =
r'^https?:\/\/[\w\-]+(\.[\w\-]+)*(:\d+)?(\/.*)?$';
static const _detectLinkPattern =
r'https?:\/\/[\w\-]+(\.[\w\-]+)*(:\d+)?(\/[^\s]*)?';
/// It requires a valid link in one link
static final oneLineRegExp = RegExp(
_oneLinePattern,
static final oneLineLinkRegExp = RegExp(
_oneLineLinkPattern,
caseSensitive: false,
);
@ -375,10 +375,10 @@ class AutoFormatMultipleLinksRule extends InsertRule {
_detectLinkPattern,
caseSensitive: false,
);
@Deprecated(
'Please use [linkRegExp1] or [linkRegExp2]',
)
static final linkRegExp = oneLineRegExp;
// @Deprecated(
// 'Please use [linkRegExp1] or [linkRegExp2]',
// )
static final linkRegExp = oneLineLinkRegExp;
@override
Delta? applyRule(

@ -10,8 +10,8 @@ class QuillToolbarArrowIndicatedButtonList extends StatefulWidget {
const QuillToolbarArrowIndicatedButtonList({
required this.axis,
required this.buttons,
Key? key,
}) : super(key: key);
super.key,
});
final Axis axis;
final List<Widget> buttons;

@ -95,14 +95,13 @@ class _QuillToolbarLinkStyleButtonState
context.requireQuillSharedConfigurations.dialogBarrierColor;
}
RegExp get linkRegExp {
return options.linkRegExp ?? RegExp(r'https?://\S+');
RegExp? get linkRegExp {
return options.linkRegExp;
}
@override
Widget build(BuildContext context) {
final isToggled = _getLinkAttributeValue() != null;
final pressedHandler = () => _openLinkDialog(context);
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
@ -124,7 +123,7 @@ class _QuillToolbarLinkStyleButtonState
context: context,
controller: controller,
onPressed: () {
pressedHandler();
_openLinkDialog(context);
afterButtonPressed?.call();
},
),
@ -144,10 +143,10 @@ class _QuillToolbarLinkStyleButtonState
: (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
),
fillColor: isToggled
? (iconTheme?.iconSelectedFillColor ?? Theme.of(context).primaryColor)
? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: pressedHandler,
onPressed: () => _openLinkDialog(context),
afterPressed: afterButtonPressed,
);
}
@ -236,7 +235,11 @@ class _LinkDialog extends StatefulWidget {
class _LinkDialogState extends State<_LinkDialog> {
late String _link;
late String _text;
late RegExp linkRegExp;
RegExp get linkRegExp {
return widget.linkRegExp ?? AutoFormatMultipleLinksRule.oneLineLinkRegExp;
}
late TextEditingController _linkController;
late TextEditingController _textController;
@ -245,7 +248,6 @@ class _LinkDialogState extends State<_LinkDialog> {
super.initState();
_link = widget.link ?? '';
_text = widget.text ?? '';
linkRegExp = widget.linkRegExp ?? AutoFormatMultipleLinksRule.oneLineRegExp;
_linkController = TextEditingController(text: _link);
_textController = TextEditingController(text: _text);
}

@ -5,9 +5,11 @@ import 'package:url_launcher/link.dart';
import '../../../../extensions.dart'
show UtilityWidgets, AutoFormatMultipleLinksRule;
import '../../../../translations.dart';
import '../../../models/config/toolbar/buttons/link_style2.dart';
import '../../../models/documents/attribute.dart';
import '../../../models/themes/quill_dialog_theme.dart';
import '../../../models/themes/quill_icon_theme.dart';
import '../../../utils/extensions/build_context.dart';
import '../../controller.dart';
import '../../link.dart';
import '../base_toolbar.dart';
@ -16,60 +18,20 @@ import '../base_toolbar.dart';
/// customization
/// and uses dialog similar to one which is used on [http://quilljs.com].
class QuillToolbarLinkStyleButton2 extends StatefulWidget {
const QuillToolbarLinkStyleButton2({
QuillToolbarLinkStyleButton2({
required this.controller,
this.icon,
this.iconSize = kDefaultIconSize,
this.iconTheme,
this.dialogTheme,
this.afterButtonPressed,
this.tooltip,
this.constraints,
this.addLinkLabel,
this.editLinkLabel,
this.linkColor,
this.childrenSpacing = 16.0,
this.autovalidateMode = AutovalidateMode.disabled,
this.validationMessage,
this.buttonSize,
this.dialogBarrierColor = Colors.black54,
Key? key,
}) : assert(addLinkLabel == null || addLinkLabel.length > 0),
assert(editLinkLabel == null || editLinkLabel.length > 0),
assert(childrenSpacing > 0),
assert(validationMessage == null || validationMessage.length > 0),
super(key: key);
required this.options,
super.key,
}) : assert(options.addLinkLabel == null ||
(options.addLinkLabel?.isNotEmpty ?? true)),
assert(options.editLinkLabel == null ||
(options.editLinkLabel?.isNotEmpty ?? true)),
assert(options.childrenSpacing > 0),
assert(options.validationMessage == null ||
(options.validationMessage?.isNotEmpty ?? true));
final QuillController controller;
final IconData? icon;
final double iconSize;
final QuillIconTheme? iconTheme;
final QuillDialogTheme? dialogTheme;
final VoidCallback? afterButtonPressed;
final String? tooltip;
/// The constrains for dialog.
final BoxConstraints? constraints;
/// The text of label in link add mode.
final String? addLinkLabel;
/// The text of label in link edit mode.
final String? editLinkLabel;
/// The color of URL.
final Color? linkColor;
/// The margin between child widgets in the dialog.
final double childrenSpacing;
final AutovalidateMode autovalidateMode;
final String? validationMessage;
/// The size of dialog buttons.
final Size? buttonSize;
final Color dialogBarrierColor;
final QuillToolbarLinkStyleButton2Options options;
@override
State<QuillToolbarLinkStyleButton2> createState() =>
@ -99,30 +61,101 @@ class _QuillToolbarLinkStyleButton2State
}
}
QuillController get controller {
return widget.controller;
}
QuillToolbarLinkStyleButton2Options get options {
return widget.options;
}
double get iconSize {
final baseFontSize = baseButtonExtraOptions.globalIconSize;
final iconSize = options.iconSize;
return iconSize ?? baseFontSize;
}
VoidCallback? get afterButtonPressed {
return options.afterButtonPressed ??
baseButtonExtraOptions.afterButtonPressed;
}
QuillIconTheme? get iconTheme {
return options.iconTheme ?? baseButtonExtraOptions.iconTheme;
}
QuillToolbarBaseButtonOptions get baseButtonExtraOptions {
return context.requireQuillToolbarBaseButtonOptions;
}
String get tooltip {
return options.tooltip ??
baseButtonExtraOptions.tooltip ??
'Insert URL'.i18n;
}
IconData get iconData {
return options.iconData ?? baseButtonExtraOptions.iconData ?? Icons.link;
}
Color get dialogBarrierColor {
return options.dialogBarrierColor ??
context.requireQuillSharedConfigurations.dialogBarrierColor;
}
@override
Widget build(BuildContext context) {
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
if (childBuilder != null) {
return childBuilder(
QuillToolbarLinkStyleButton2Options(
iconData: iconData,
addLinkLabel: options.addLinkLabel,
afterButtonPressed: options.afterButtonPressed,
autovalidateMode: options.autovalidateMode,
buttonSize: options.buttonSize,
childrenSpacing: options.childrenSpacing,
dialogBarrierColor: dialogBarrierColor,
dialogTheme: options.dialogTheme,
iconSize: iconSize,
constraints: options.constraints,
tooltip: tooltip,
iconTheme: iconTheme,
editLinkLabel: options.editLinkLabel,
validationMessage: options.validationMessage,
linkColor: options.linkColor,
),
QuillToolbarLinkStyleButton2ExtraOptions(
controller: controller,
context: context,
onPressed: () {
_openLinkDialog();
afterButtonPressed?.call();
},
),
);
}
final theme = Theme.of(context);
final isToggled = _getLinkAttributeValue() != null;
return QuillToolbarIconButton(
tooltip: widget.tooltip,
tooltip: tooltip,
highlightElevation: 0,
hoverElevation: 0,
size: widget.iconSize * kIconButtonFactor,
size: iconSize * kIconButtonFactor,
icon: Icon(
widget.icon ?? Icons.link,
size: widget.iconSize,
iconData,
size: iconSize,
color: isToggled
? (widget.iconTheme?.iconSelectedColor ??
theme.primaryIconTheme.color)
: (widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
? (iconTheme?.iconSelectedColor ?? theme.primaryIconTheme.color)
: (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
),
fillColor: isToggled
? (widget.iconTheme?.iconSelectedFillColor ??
Theme.of(context).primaryColor)
: (widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
borderRadius: widget.iconTheme?.borderRadius ?? 2,
? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: _openLinkDialog,
afterPressed: widget.afterButtonPressed,
afterPressed: afterButtonPressed,
);
}
@ -131,19 +164,19 @@ class _QuillToolbarLinkStyleButton2State
final textLink = await showDialog<QuillTextLink>(
context: context,
barrierColor: widget.dialogBarrierColor,
barrierColor: dialogBarrierColor,
builder: (_) => LinkStyleDialog(
dialogTheme: widget.dialogTheme,
dialogTheme: options.dialogTheme,
text: initialTextLink.text,
link: initialTextLink.link,
constraints: widget.constraints,
addLinkLabel: widget.addLinkLabel,
editLinkLabel: widget.editLinkLabel,
linkColor: widget.linkColor,
childrenSpacing: widget.childrenSpacing,
autovalidateMode: widget.autovalidateMode,
validationMessage: widget.validationMessage,
buttonSize: widget.buttonSize,
constraints: options.constraints,
addLinkLabel: options.addLinkLabel,
editLinkLabel: options.editLinkLabel,
linkColor: options.linkColor,
childrenSpacing: options.childrenSpacing,
autovalidateMode: options.autovalidateMode,
validationMessage: options.validationMessage,
buttonSize: options.buttonSize,
),
);
@ -166,7 +199,7 @@ class _QuillToolbarLinkStyleButton2State
class LinkStyleDialog extends StatefulWidget {
const LinkStyleDialog({
Key? key,
super.key,
this.text,
this.link,
this.dialogTheme,
@ -183,8 +216,7 @@ class LinkStyleDialog extends StatefulWidget {
}) : assert(addLinkLabel == null || addLinkLabel.length > 0),
assert(editLinkLabel == null || editLinkLabel.length > 0),
assert(childrenSpacing > 0),
assert(validationMessage == null || validationMessage.length > 0),
super(key: key);
assert(validationMessage == null || validationMessage.length > 0);
final String? text;
final String? link;
@ -387,7 +419,7 @@ class _LinkStyleDialogState extends State<LinkStyleDialog> {
String? _validateLink(String? value) {
if ((value?.isEmpty ?? false) ||
!AutoFormatMultipleLinksRule.oneLineRegExp.hasMatch(value!)) {
!AutoFormatMultipleLinksRule.oneLineLinkRegExp.hasMatch(value!)) {
return widget.validationMessage ?? 'That is not a valid URL';
}

@ -60,18 +60,18 @@ class _QuillToolbarSelectAlignmentButtonState
return widget.controller;
}
double get iconSize {
double get _iconSize {
final baseFontSize = baseButtonExtraOptions.globalIconSize;
final iconSize = options.iconSize;
return iconSize ?? baseFontSize;
}
VoidCallback? get afterButtonPressed {
VoidCallback? get _afterButtonPressed {
return options.afterButtonPressed ??
baseButtonExtraOptions.afterButtonPressed;
}
QuillIconTheme? get iconTheme {
QuillIconTheme? get _iconTheme {
return options.iconTheme ?? baseButtonExtraOptions.iconTheme;
}
@ -191,25 +191,42 @@ class _QuillToolbarSelectAlignmentButtonState
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
if (childBuilder != null) {
throw UnsupportedError(
'Sorry but the `childBuilder` for the Select alignment buttons'
' is not supported. Yet but we will work on that soon.',
);
void _sharedOnPressed(int index) {
_valueAttribute[index] == Attribute.leftAlignment
? controller.formatSelection(
Attribute.clone(Attribute.align, null),
)
: controller.formatSelection(_valueAttribute[index]);
_afterButtonPressed?.call();
}
final theme = Theme.of(context);
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(buttonCount, (index) {
if (childBuilder != null) {
return childBuilder(
QuillToolbarSelectAlignmentButtonOptions(
afterButtonPressed: _afterButtonPressed,
iconSize: _iconSize,
iconTheme: _iconTheme,
tooltips: _tooltips,
iconsData: _iconsData,
),
QuillToolbarSelectAlignmentButtonExtraOptions(
context: context,
controller: controller,
onPressed: () => _sharedOnPressed(index),
),
);
}
final theme = Theme.of(context);
return Padding(
padding: widget.padding ??
const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: iconSize * kIconButtonFactor,
height: iconSize * kIconButtonFactor,
width: _iconSize * kIconButtonFactor,
height: _iconSize * kIconButtonFactor,
),
child: UtilityWidgets.maybeTooltip(
message: _valueString[index] == Attribute.leftAlignment.value
@ -226,19 +243,12 @@ class _QuillToolbarSelectAlignmentButtonState
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(iconTheme?.borderRadius ?? 2)),
BorderRadius.circular(_iconTheme?.borderRadius ?? 2)),
fillColor: _valueToText[_value] == _valueString[index]
? (iconTheme?.iconSelectedFillColor ??
Theme.of(context).primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
onPressed: () {
_valueAttribute[index] == Attribute.leftAlignment
? controller.formatSelection(
Attribute.clone(Attribute.align, null),
)
: controller.formatSelection(_valueAttribute[index]);
afterButtonPressed?.call();
},
? (_iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (_iconTheme?.iconUnselectedFillColor ??
theme.canvasColor),
onPressed: () => _sharedOnPressed(index),
child: Icon(
_valueString[index] == Attribute.leftAlignment.value
? _iconsData.leftAlignment
@ -248,11 +258,11 @@ class _QuillToolbarSelectAlignmentButtonState
Attribute.rightAlignment.value
? _iconsData.rightAlignment
: _iconsData.justifyAlignment,
size: iconSize,
size: _iconSize,
color: _valueToText[_value] == _valueString[index]
? (iconTheme?.iconSelectedColor ??
? (_iconTheme?.iconSelectedColor ??
theme.primaryIconTheme.color)
: (iconTheme?.iconUnselectedColor ??
: (_iconTheme?.iconUnselectedColor ??
theme.iconTheme.color),
),
),

@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import '../../../../extensions.dart';
@ -90,10 +91,20 @@ class _QuillToolbarSelectHeaderStyleButtonsState
afterButtonPressed?.call();
}
List<Attribute> get _attrbuites {
return options.attributes ??
const [
Attribute.header,
Attribute.h1,
Attribute.h2,
Attribute.h3,
];
}
@override
Widget build(BuildContext context) {
assert(
options.attributes.every(
_attrbuites.every(
(element) => _valueToText.keys.contains(element),
),
'All attributes must be one of them: header, h1, h2 or h3',
@ -107,19 +118,28 @@ class _QuillToolbarSelectHeaderStyleButtonsState
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
final children = _attrbuites.map((attribute) {
if (childBuilder != null) {
throw UnsupportedError(
'Sorry but the `childBuilder` for the Select header button'
' is not supported. Yet but we will work on that soon.',
return childBuilder(
QuillToolbarSelectHeaderStyleButtonsOptions(
afterButtonPressed: afterButtonPressed,
attributes: _attrbuites,
axis: axis,
iconSize: iconSize,
iconTheme: iconTheme,
tooltip: tooltip,
),
QuillToolbarSelectHeaderStyleButtonExtraOptions(
controller: controller,
context: context,
onPressed: () => _sharedOnPressed(attribute),
),
);
}
final theme = Theme.of(context);
final children = options.attributes.map((attribute) {
final isSelected = _selectedAttribute == attribute;
return Padding(
// Do we really need to ignore (prefer_const_constructors)??
padding: EdgeInsets.symmetric(horizontal: !isWeb() ? 1.0 : 5.0),
padding: const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: iconSize * kIconButtonFactor,
@ -136,12 +156,14 @@ class _QuillToolbarSelectHeaderStyleButtonsState
borderRadius:
BorderRadius.circular(iconTheme?.borderRadius ?? 2)),
fillColor: isSelected
? (iconTheme?.iconSelectedFillColor ??
Theme.of(context).primaryColor)
? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
onPressed: () => _sharedOnPressed(attribute),
child: Text(
_valueToText[attribute] ?? '',
_valueToText[attribute] ??
(throw ArgumentError.notNull(
'attrbuite',
)),
style: style.copyWith(
color: isSelected
? (iconTheme?.iconSelectedColor ??

Loading…
Cancel
Save