diff --git a/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart b/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart index c79972bc2..4e56e8c41 100644 --- a/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart +++ b/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart @@ -1,9 +1,7 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/views/button/icon_button_web.dart'; -import 'package:core/presentation/views/pick_color/color_code_field.dart'; -import 'package:core/presentation/views/pick_color/color_picker_action_buttons.dart'; -import 'package:core/presentation/views/pick_color/color_picker_copy_past_behaivor.dart'; +import 'package:flex_color_picker/flex_color_picker.dart'; import 'package:flutter/material.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; @@ -76,9 +74,11 @@ class ColorPickerDialogBuilder { borderRadius: BorderRadius.all(Radius.circular(4)), color: Colors.white ), - child: Wrap(children: AppColor.listColorsPicker - .map((color) => _itemColorWidget(context, color)) - .toList(), + child: Center( + child: Wrap(children: AppColor.listColorsPicker + .map((color) => _itemColorWidget(context, color)) + .toList(), + ), ), ), Padding( diff --git a/core/lib/presentation/views/pick_color/color_code_field.dart b/core/lib/presentation/views/pick_color/color_code_field.dart deleted file mode 100644 index 4f8502ab3..000000000 --- a/core/lib/presentation/views/pick_color/color_code_field.dart +++ /dev/null @@ -1,356 +0,0 @@ -import 'package:core/presentation/views/pick_color/color_picker_action_buttons.dart'; -import 'package:core/presentation/views/pick_color/color_picker_copy_past_behaivor.dart'; -import 'package:core/presentation/views/pick_color/color_picker_extensions.dart'; -import 'package:core/presentation/views/pick_color/dry_intrinsic.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -/// Color code entry and display field used by the color picker. -class ColorCodeField extends StatefulWidget { - /// Default const constructor. - const ColorCodeField({ - Key? key, - required this.color, - this.readOnly = false, - required this.onColorChanged, - required this.onEditFocused, - this.textStyle, - this.prefixStyle, - this.colorCodeHasColor = false, - this.toolIcons = const ColorPickerActionButtons(), - this.copyPasteBehavior = const ColorPickerCopyPasteBehavior(), - this.enableTooltips = true, - this.shouldUpdate = false, - }) : super(key: key); - - /// Current color value for the field. - final Color color; - - /// Is in read only mode, we should not be able to select either. - final bool readOnly; - - /// Color code of the entered color string is returned back in this callback. - final ValueChanged onColorChanged; - - /// The Color code editing field has focus. - final ValueChanged onEditFocused; - - /// TextStyle of the color code display and edit field. - /// - /// Defaults to Theme.of(context).textTheme.bodyMedium; - final TextStyle? textStyle; - - /// The TextStyle of the prefix of the color code. - /// - /// Defaults to [textStyle], if not defined. - final TextStyle? prefixStyle; - - /// If true then the background of the color code entry field uses the current - /// selected color. - /// - /// This makes the color code entry field a larger current color indicator - /// area that changes color as the color value is changed. - /// The text color of the filed will adjust to for best contrast as will - /// the opacity indicator text. Enabling this feature will override any - /// color specified in [textStyle] and [prefixStyle] but - /// their styles will otherwise be kept as specified. - /// - /// Defaults to false. - final bool colorCodeHasColor; - - /// Defines icons for the color picker title bar and its actions. - /// - /// Defaults to ColorPickerToolIcons(). - final ColorPickerActionButtons toolIcons; - - /// Defines the color picker's copy and paste behavior. - /// - /// Defaults to ColorPickerPasteBehavior(). - final ColorPickerCopyPasteBehavior copyPasteBehavior; - - /// Controls if tooltips are shown or not - /// - /// Defaults to true. - final bool enableTooltips; - - /// Should a change on the color value update the field? - /// - /// If we are just editing text in the control it should not, we just send - /// the data out to update any widget using the [color]. - /// However, when we get a new color due to external action is should update. - /// This is similar to the same property on the wheel. - /// - /// Defaults to false. - final bool shouldUpdate; - - @override - // ignore: library_private_types_in_public_api - _ColorCodeFieldState createState() => _ColorCodeFieldState(); -} - -// Color code display and entry field. -class _ColorCodeFieldState extends State { - late TextEditingController textController; - late FocusNode textFocusNode; - late String colorHexCode; - late Color color; - - @override - void initState() { - super.initState(); - textController = TextEditingController(); - textFocusNode = FocusNode(); - color = widget.color; - textController.text = color.hex; - } - - @override - void dispose() { - textController.dispose(); - textFocusNode.dispose(); - super.dispose(); - } - - @override - void didUpdateWidget(covariant ColorCodeField oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.color != widget.color && widget.shouldUpdate) { - color = widget.color; - textController.text = color.hex; - } - } - - @override - Widget build(BuildContext context) { - // The tooltip for copying the color code via the icon button - String? copyTooltip; - - if (widget.enableTooltips) { - // Get current platform. - final TargetPlatform platform = Theme.of(context).platform; - // Get the Material localizations. - final MaterialLocalizations translate = MaterialLocalizations.of(context); - // If shortcut key enabled, make a shortcut platform aware info tooltip. - String copyKeyTooltip = ''; - if (widget.copyPasteBehavior.ctrlC) { - copyKeyTooltip = platformControlKey(platform, 'C'); - } - // Make the Copy tooltip. - copyTooltip = - (widget.copyPasteBehavior.copyTooltip ?? translate.copyButtonLabel) + - copyKeyTooltip; - } - - // Define opinionated styles for the color code display and entry field. - final bool isLight = Theme.of(context).brightness == Brightness.light; - final Color fieldBackground = widget.colorCodeHasColor - ? color - : isLight - ? Colors.black.withAlpha(11) - : Colors.white.withAlpha(33); - - final bool isLightBackground = - ThemeData.estimateBrightnessForColor(fieldBackground) == - Brightness.light; - final Color textColor = isLight - ? (isLightBackground || fieldBackground.opacity < 0.5) - ? Colors.black - : Colors.white - : (!isLightBackground || fieldBackground.opacity < 0.5) - ? Colors.white - : Colors.black; - - final Color fieldBorder = - isLight ? Colors.black.withAlpha(33) : Colors.white.withAlpha(55); - - // Set the default text style to bodyMedium if not given. - TextStyle effectiveStyle = widget.textStyle ?? - Theme.of(context).textTheme.bodyMedium ?? - const TextStyle(fontSize: 14); - - TextStyle effectivePrefixStyle = widget.prefixStyle ?? effectiveStyle; - - if (widget.colorCodeHasColor) { - effectiveStyle = effectiveStyle.copyWith(color: textColor); - effectivePrefixStyle = effectivePrefixStyle.copyWith(color: textColor); - } - - // Compute color code field size based on the used font size. Might not - // always be ideal, but with normal fonts and sizes they have been tested to - // work well enough visually and to always have room for "DDDDDD", which is - // usually the widest possible entry string. - final double fontSize = effectiveStyle.fontSize ?? 14.0; - final double iconSize = fontSize * 1.1; - final double borderRadius = fontSize * 1.2; - final double fieldWidth = fontSize * 10; - - return SizedBox( - width: fieldWidth, - // The custom DryIntrinsicWidth layout widget is used due to issue: - // https://github.com/flutter/flutter/issues/71687 - child: DryIntrinsicWidth( - child: Focus( - // Tell the parent when the text edit field has focus. - onFocusChange: widget.onEditFocused, - child: TextField( - enabled: true, - readOnly: widget.readOnly, - enableInteractiveSelection: !widget.readOnly, - controller: textController, - focusNode: textFocusNode, - maxLength: 6, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - // Remove line that shows entered chars when maxLength is used. - buildCounter: (BuildContext context, - {required int currentLength, - int? maxLength, - required bool isFocused}) => - null, - style: effectiveStyle, - // Only affects the type of keyboard shown on devices, does not - // make the input uppercase. - textCapitalization: TextCapitalization.characters, - // These input formatters limits the input to only valid chars for - // a hex color code, and we also convert them to uppercase. - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp('[a-fA-F0-9]')), - _UpperCaseTextFormatter(), - ], - decoration: InputDecoration( - suffixIcon: widget.copyPasteBehavior.editFieldCopyButton - ? IconButton( - icon: Icon(widget.copyPasteBehavior.copyIcon), - padding: EdgeInsets.zero, - tooltip: copyTooltip, - iconSize: iconSize, - splashRadius: borderRadius, - color: effectiveStyle.color, - constraints: const BoxConstraints(), - onPressed: _setClipboard, - ) - : SizedBox(height: borderRadius * 2), - suffixIconConstraints: BoxConstraints( - minHeight: borderRadius * 2, - minWidth: borderRadius * 2, - ), - isDense: true, - contentPadding: EdgeInsetsDirectional.only(start: fontSize), - prefixText: _editColorPrefix, - prefixStyle: effectivePrefixStyle, - filled: true, - fillColor: fieldBackground, - border: OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(borderRadius), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: fieldBorder, - ), - borderRadius: BorderRadius.circular(borderRadius), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: fieldBorder, - ), - borderRadius: BorderRadius.circular(borderRadius), - ), - disabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: fieldBorder, - ), - borderRadius: BorderRadius.circular(borderRadius), - ), - errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: fieldBorder, - ), - borderRadius: BorderRadius.circular(borderRadius), - ), - focusedErrorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: fieldBorder, - ), - borderRadius: BorderRadius.circular(borderRadius), - ), - ), - // - onChanged: (String textColor) { - setState(() { - color = textColor - .toColorShort(widget.copyPasteBehavior.parseShortHexCode) - .withOpacity(color.opacity); - }); - widget.onColorChanged(color); - }, - onEditingComplete: () { - setState(() { - color = textController.text - .toColorShort(widget.copyPasteBehavior.parseShortHexCode) - .withOpacity(color.opacity); - }); - textController.text = color.hex; - widget.onColorChanged(color); - textFocusNode.unfocus(); - }, - ), - ), - ), - ); - } - - // Set current selected color values as a String on the Clipboard in the - // currently configured format. - Future _setClipboard() async { - String colorString = '00000000'; - switch (widget.copyPasteBehavior.copyFormat) { - case ColorPickerCopyFormat.dartCode: - colorString = '0x${color.hexAlpha}'; - break; - case ColorPickerCopyFormat.hexRRGGBB: - colorString = color.hex; - break; - case ColorPickerCopyFormat.hexAARRGGBB: - colorString = color.hexAlpha; - break; - case ColorPickerCopyFormat.numHexRRGGBB: - colorString = '#${color.hex}'; - break; - case ColorPickerCopyFormat.numHexAARRGGBB: - colorString = '#${color.hexAlpha}'; - break; - } - final ClipboardData data = ClipboardData(text: colorString); - await Clipboard.setData(data); - } - - // Get the current selected color prefix format for the input field. - // The prefix in the input field matches the set copy format. - String get _editColorPrefix { - final String alphaValue = color.hexAlpha.substring(0, 2); - switch (widget.copyPasteBehavior.copyFormat) { - case ColorPickerCopyFormat.dartCode: - return '0x$alphaValue'; - case ColorPickerCopyFormat.hexRRGGBB: - return ' '; - case ColorPickerCopyFormat.hexAARRGGBB: - return ' $alphaValue'; - case ColorPickerCopyFormat.numHexRRGGBB: - return ' #'; - case ColorPickerCopyFormat.numHexAARRGGBB: - return ' #$alphaValue'; - } - } -} - -// This TextField formatter converts all input to uppercase. -class _UpperCaseTextFormatter extends TextInputFormatter { - @override - TextEditingValue formatEditUpdate( - TextEditingValue oldValue, TextEditingValue newValue) { - return TextEditingValue( - text: newValue.text.toUpperCase(), - selection: newValue.selection, - ); - } -} diff --git a/core/lib/presentation/views/pick_color/color_picker_action_buttons.dart b/core/lib/presentation/views/pick_color/color_picker_action_buttons.dart deleted file mode 100644 index 484845b75..000000000 --- a/core/lib/presentation/views/pick_color/color_picker_action_buttons.dart +++ /dev/null @@ -1,427 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -/// Type of button used for OK or Cancel action button on a FlexColorPicker -/// dialog. -enum ColorPickerActionButtonType { - /// Use a [TextButton] button. - text, - - /// Use [OutlinedButton] button. - outlined, - - /// Use [ElevatedButton] button. - elevated, -} - -/// Used to define the order of OK and Cancel buttons on the FlexColorPicker -/// dialog. -enum ColorPickerActionButtonOrder { - /// OK is the right button. - okIsRight, - - /// OK is the left button. - okIsLeft, - - /// OK is on the place where it belongs depending on used platform - /// - /// Right: - /// - /// Cancel - OK : macOS, iOS, Android, Linux, Fuchsia - /// - /// Left: - /// - /// OK - Cancel : Windows - adaptive, -} - -/// Defines the FlexColorPicker OK and Cancel actions buttons and their style. -/// -/// You can define if action buttons are on a top toolbar or only -/// in the dialog bottom. The toolbar buttons are plain icon only -/// buttons. For the Dialog buttons you can choose between -/// [TextButton], [OutlinedButton] and [ElevatedButton]. -/// -/// The used icons can be changed form default ones, as can used tooltips. -/// -/// Used by FlexColorPicker to define action buttons and their style. -@immutable -class ColorPickerActionButtons with Diagnosticable { - /// Default const constructor. - const ColorPickerActionButtons({ - this.okButton = false, - this.closeButton = false, - this.okIcon = Icons.check, - this.closeIcon = Icons.close, - this.closeIsLast = true, - this.okTooltip, - this.closeTooltip, - this.closeTooltipIsClose = true, - this.toolIconsThemeData, - this.visualDensity, - this.padding = EdgeInsets.zero, - this.alignment = Alignment.center, - this.splashRadius = 24, - this.constraints = const BoxConstraints(minHeight: 42, minWidth: 42), - this.dialogActionButtons = true, - this.dialogActionOrder = ColorPickerActionButtonOrder.okIsRight, - this.dialogActionIcons = false, - this.dialogCancelButtonLabel, - this.dialogCancelButtonType = ColorPickerActionButtonType.text, - this.dialogOkButtonLabel, - this.dialogOkButtonType = ColorPickerActionButtonType.text, - this.useRootNavigator = true, - }); - - /// Dialog has an OK icon button on top toolbar to select active color - /// and close the color picker dialog. - /// - /// This will pop the current top route on navigation stack and return true. - /// Only enable this toolbar button when you are using the picker in a dialog. - /// - /// Defaults to false. - final bool okButton; - - /// Dialog has a Close icon button on top toolbar to cancel and close the - /// color picker dialog. - /// - /// This will pop the current top route on navigation stack and return false. - /// Only enable this toolbar button when you are using the picker in a dialog. - /// - /// Defaults to false. - final bool closeButton; - - /// Icon used for the OK action icon in the color picker dialog. - /// - /// Used both on the toolbar icon button and as a prefix icon on the bottom - /// action button, when icons have been enabled for the bottom action buttons. - /// - /// Defaults to [Icons.check]. - final IconData okIcon; - - /// Icon used for the close action icon in the color picker dialog. - /// - /// Used both on the toolbar icon button and as a prefix icon on the bottom - /// action button, when prefix icons have been enabled for the bottom - /// action buttons. - /// - /// Defaults to [Icons.close]. - final IconData closeIcon; - - /// Close icon is last in the color picker title toolbar. - /// - /// Set to false to swap the order of the OK and Close toolbar icons. - /// - /// Defaults to true, which results in the close 'x' icon being in upper - /// end corner of the picker dialog. - /// - /// Based on Material guide, the bottom action buttons in a dialog are always - /// in the Cancel-OK order. If the top toolbar buttons are used at the - /// same time, this value can be set to false to show the top toolbar buttons - /// in the same order as the Material bottom dialog action buttons. - /// - /// The recommendation is to not use the top and bottom action buttons at the - /// same time, but rather select one of the two options. The API does - /// however allow using both or even a mix and match. It is possible to show - /// **Cancel** and **OK** actions at the bottom of the dialog, and also add - /// just an 'x' icon in the upper end corner of the dialog that also - /// cancel-closes the dialog as expected. - final bool closeIsLast; - - /// Label used as tooltip for OK toolbar button. - /// - /// Provide your own or use the default material localization label. - /// - /// Defaults to MaterialLocalizations.of(context).okButtonLabel. - final String? okTooltip; - - /// Label used as tooltip for close toolbar button. - /// - /// Provide your own or use the default material localization label. - /// - /// Defaults to MaterialLocalizations.of(context).cancelButtonLabel if - /// closeTooltipIsClose is true. If false it defaults to - /// MaterialLocalizations.of(context).cancelButtonLabel. - final String? closeTooltip; - - /// Close toolbar icon button uses "close" material localization as - /// default label. - /// - /// If set to false, it uses "cancel" localization. You can still also - /// provide your own custom tooltip. This toggle is just convenient - /// if you want to call the top toolbar buttons that closes/cancels the - /// dialog "Close" (default) or "Cancel" like on a typical dialog bottom. - /// The "Close" tooltip, is more in line with the 'x' icon, - /// that here also closes the dialog with the dismiss result. - /// - /// Defaults to true. - final bool closeTooltipIsClose; - - /// The theme for the toolbar icons. - /// - /// The toolbar is compact, so icons are small by design. - /// - /// Effective style will uses any none null property in the passed in - /// [IconThemeData]. If the passed in theme data is null, or any property in - /// it, is null, then the following fallback defaults are used: - /// - /// color: remains null, so default [IconThemeData] color behavior is kept. - /// size: 22 - /// opacity: 0.90 - /// - /// NOTE: This theme on purpose does not merge any ambient theme. To keep the - /// compact fallback values as its default style. To change them you have - /// to pass in the desired [IconThemeData]. - final IconThemeData? toolIconsThemeData; - - /// Defines how compact the toolbar icon button layout will be. - /// - /// See also: - /// - /// * [ThemeData.visualDensity], which specifies the [visualDensity] for all - /// widgets within a [Theme]. - final VisualDensity? visualDensity; - - /// The padding around the toolbar icon buttons. The entire padded icon will - /// react to input gestures. - /// - /// Defaults to const EdgeInsets.all(0), - final EdgeInsetsGeometry padding; - - /// Defines how the icon is positioned within the IconButton. - /// - /// Defaults to [Alignment.center]. - final AlignmentGeometry alignment; - - /// The splash radius on the toolbar icon buttons. - /// - /// Defaults to 24. - final double splashRadius; - - /// Optional size constraints for the icon button. - /// - /// Defaults to: const BoxConstraints(minHeight: 34, minWidth: 34), - final BoxConstraints constraints; - - /// If set to false, the bottom dialog action buttons att the bottom - /// are removed. - /// - /// If you remove the bottom dialog action buttons, make sure to enabled the - /// ones in the dialog toolbar. - /// - /// Defaults to true. - final bool dialogActionButtons; - - /// Defines the order of the OK and Cancel actions buttons at the bottom - /// of the dialog. - /// - /// Options are: - /// - /// * okIsRight: OK is the right button. - /// * okIsLeft: OK is the left button. - /// * adaptive: OK is on the place where it belongs on used platform - /// Right: Cancel - OK : macOS, iOS, Android, Linux, Fuchsia - /// Left : OK - Cancel : Windows - /// - /// Defaults to "okIsRight". Prefer using "adaptive", but defaults to - /// "okIsRight" in order to not break past behavior. - final ColorPickerActionButtonOrder dialogActionOrder; - - /// If set to true, the dialog bottom action buttons will be prefixed with - /// an icon. - /// - /// The cancel buttons will get the [closeIcon] and the ok button will get - /// prefixed with the [okIcon]. - /// - /// Defaults to false. - final bool dialogActionIcons; - - /// Color picker dialog cancel button label. - /// - /// Label shown on the button for cancelling the color picking and closing - /// the dialog and returning false. - /// - /// If null, defaults to MaterialLocalizations.of(context).cancelButtonLabel. - final String? dialogCancelButtonLabel; - - /// Type of button used in the dialog for the Cancel button. - /// - /// The button will be themed based on closest ambient theme. - /// - /// Defaults to [ColorPickerActionButtonType.text] resulting in [TextButton]. - final ColorPickerActionButtonType dialogCancelButtonType; - - /// Color picker dialog OK button label. - /// - /// Label shown on bottom action button for selecting the current color in - /// the color picker dialog and closing the dialog and returning true. - /// - /// If null, defaults to MaterialLocalizations.of(context).okButtonLabel. - final String? dialogOkButtonLabel; - - /// Type of button used in the dialog for the OK button. - /// - /// The button will be themed based on closest ambient theme. - /// - /// Defaults to [ColorPickerActionButtonType.text] resulting in [TextButton]. - final ColorPickerActionButtonType dialogOkButtonType; - - /// The `useRootNavigator` argument is used to determine whether to push the - /// ColorPicker dialog to the [Navigator] furthest from or nearest to the - /// given `context`. - /// - /// By default, `useRootNavigator` is `true` and the dialog route created - /// by build of ColorPicker dialogs are on the root. - /// - /// This setting was moved here in version 2.1.0 in order to make the - /// property accessible by Navigator pop functions both in the ColorPicker - /// widget itself, as well as built-in dialogs that uses the ColorPicker. - final bool useRootNavigator; - - /// Copy the object with one or more provided properties changed. - ColorPickerActionButtons copyWith({ - bool? okButton, - bool? closeButton, - IconData? okIcon, - IconData? closeIcon, - bool? closeIsLast, - String? okTooltip, - String? closeTooltip, - bool? closeTooltipIsClose, - IconThemeData? toolIconsThemeData, - VisualDensity? visualDensity, - EdgeInsetsGeometry? padding, - AlignmentGeometry? alignment, - double? splashRadius, - BoxConstraints? constraints, - bool? dialogActionButtons, - ColorPickerActionButtonOrder? dialogActionOrder, - bool? dialogActionIcons, - String? dialogCancelButtonLabel, - ColorPickerActionButtonType? dialogCancelButtonType, - String? dialogOkButtonLabel, - ColorPickerActionButtonType? dialogOkButtonType, - bool? useRootNavigator, - }) { - return ColorPickerActionButtons( - okButton: okButton ?? this.okButton, - closeButton: closeButton ?? this.closeButton, - okIcon: okIcon ?? this.okIcon, - closeIcon: closeIcon ?? this.closeIcon, - closeIsLast: closeIsLast ?? this.closeIsLast, - okTooltip: okTooltip ?? this.okTooltip, - closeTooltip: closeTooltip ?? this.closeTooltip, - closeTooltipIsClose: closeTooltipIsClose ?? this.closeTooltipIsClose, - toolIconsThemeData: toolIconsThemeData ?? this.toolIconsThemeData, - visualDensity: visualDensity ?? this.visualDensity, - padding: padding ?? this.padding, - alignment: alignment ?? this.alignment, - splashRadius: splashRadius ?? this.splashRadius, - constraints: constraints ?? this.constraints, - dialogActionButtons: dialogActionButtons ?? this.dialogActionButtons, - dialogActionOrder: dialogActionOrder ?? this.dialogActionOrder, - dialogActionIcons: dialogActionIcons ?? this.dialogActionIcons, - dialogCancelButtonLabel: - dialogCancelButtonLabel ?? this.dialogCancelButtonLabel, - dialogCancelButtonType: - dialogCancelButtonType ?? this.dialogCancelButtonType, - dialogOkButtonLabel: dialogOkButtonLabel ?? this.dialogOkButtonLabel, - dialogOkButtonType: dialogOkButtonType ?? this.dialogOkButtonType, - useRootNavigator: useRootNavigator ?? this.useRootNavigator, - ); - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other.runtimeType != runtimeType) return false; - return other is ColorPickerActionButtons && - runtimeType == other.runtimeType && - okButton == other.okButton && - closeButton == other.closeButton && - okIcon == other.okIcon && - closeIcon == other.closeIcon && - closeIsLast == other.closeIsLast && - okTooltip == other.okTooltip && - closeTooltip == other.closeTooltip && - closeTooltipIsClose == other.closeTooltipIsClose && - toolIconsThemeData == other.toolIconsThemeData && - visualDensity == other.visualDensity && - padding == other.padding && - alignment == other.alignment && - splashRadius == other.splashRadius && - constraints == other.constraints && - dialogActionButtons == other.dialogActionButtons && - dialogActionOrder == other.dialogActionOrder && - dialogActionIcons == other.dialogActionIcons && - dialogCancelButtonLabel == other.dialogCancelButtonLabel && - dialogCancelButtonType == other.dialogCancelButtonType && - dialogOkButtonLabel == other.dialogOkButtonLabel && - dialogOkButtonType == other.dialogOkButtonType && - useRootNavigator == other.useRootNavigator; - } - - @override - int get hashCode => Object.hashAll([ - okButton, - closeButton, - okIcon, - closeIcon, - closeIsLast, - okTooltip, - closeTooltip, - closeTooltipIsClose, - toolIconsThemeData, - visualDensity, - padding, - alignment, - splashRadius, - constraints, - dialogActionButtons, - dialogActionOrder, - dialogActionIcons, - dialogCancelButtonLabel, - dialogCancelButtonType, - dialogOkButtonLabel, - dialogOkButtonType, - useRootNavigator, - ]); - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('okButton', okButton)); - properties.add(DiagnosticsProperty('closeButton', closeButton)); - properties.add(DiagnosticsProperty('okIcon', okIcon)); - properties.add(DiagnosticsProperty('closeIcon', closeIcon)); - properties.add(DiagnosticsProperty('closeIsLast', closeIsLast)); - properties.add(StringProperty('okTooltip', okTooltip)); - properties.add(StringProperty('closeTooltip', closeTooltip)); - properties.add( - DiagnosticsProperty('closeTooltipIsClose', closeTooltipIsClose)); - properties.add(DiagnosticsProperty( - 'toolIconsThemeData', toolIconsThemeData)); - properties.add( - DiagnosticsProperty('visualDensity', visualDensity)); - properties - .add(DiagnosticsProperty('alignment', alignment)); - properties.add(DoubleProperty('splashRadius', splashRadius)); - properties - .add(DiagnosticsProperty('constraints', constraints)); - properties.add( - DiagnosticsProperty('dialogActionButtons', dialogActionButtons)); - properties.add(EnumProperty( - 'dialogActionOrder', dialogActionOrder)); - properties - .add(DiagnosticsProperty('dialogActionIcons', dialogActionIcons)); - properties.add( - StringProperty('dialogCancelButtonLabel', dialogCancelButtonLabel)); - properties.add(EnumProperty( - 'dialogCancelButtonType', dialogCancelButtonType)); - properties.add(StringProperty('dialogOkButtonLabel', dialogOkButtonLabel)); - properties.add(EnumProperty( - 'dialogOkButtonType', dialogOkButtonType)); - properties - .add(DiagnosticsProperty('useRootNavigator', useRootNavigator)); - } -} diff --git a/core/lib/presentation/views/pick_color/color_picker_copy_past_behaivor.dart b/core/lib/presentation/views/pick_color/color_picker_copy_past_behaivor.dart deleted file mode 100644 index 39a3806d3..000000000 --- a/core/lib/presentation/views/pick_color/color_picker_copy_past_behaivor.dart +++ /dev/null @@ -1,511 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -/// Enum that controls the RGB string format of the copied color value. -/// -/// When you copy a [Color] value from the color picker, this enum is -/// used to configure the desired default format of the received RGB string. -/// -/// If you have opacity enabled for the picker, the alpha value will not -/// be included in the copied RGB string if you use a format that does -/// not include the alpha value. -/// -/// When you paste a color string value into the color picker, it can -/// automatically parse a string from any of the available RGB strings formats -/// to a Dart and Flutter [Color] object, regardless of what the copy format is. -/// Additionally the pasted color value can be in the 3-char short RGB hex -/// format, it will also be correctly parsed to its [Color] value, provided -/// that [ColorPickerCopyPasteBehavior.parseShortHexCode] is true. -enum ColorPickerCopyFormat { - /// In Flutter/Dart Hex RGB format '0xAARRGGBB'. - dartCode, - - /// Hex RGB format with no alpha 'RRGGBB'. - hexRRGGBB, - - /// Hex RGB format with alpha 'AARRGGBB'. - hexAARRGGBB, - - /// Web Hex RGB format with leading num # sign and no alpha '#RRGGBB'. - numHexRRGGBB, - - /// Web Hex RGB format with leading num # sign and alpha '#AARRGGBB'. - numHexAARRGGBB, -} - -/// Used by FlexColorPicker to define how copy-paste operations behave. -/// -/// * Copy and paste action buttons in the top toolbar. -/// * Long press and/or right click copy and paste context menu. -/// * Ctrl-C and Ctrl-V keyboard shortcuts, also when not in edit field. -/// Keyboard shortcuts automatically uses Command instead of Ctrl on macOS. -/// * A copy color action button in the code entry and display field. -/// -/// You can also: -/// -/// * Define default result RGB string format of a copy command. -/// * Define icons for copy and paste action buttons. -/// * Define icon theme's for the copy and paste icons. -/// * Define paste color string parsing error feedback type and message if used. -/// * Modify the tooltips for copy and paste buttons. -/// -/// Paste operation supports all RGB string formats defined by -/// [ColorPickerCopyFormat], but copy format is only in selected -/// [copyFormat]. -@immutable -class ColorPickerCopyPasteBehavior with Diagnosticable { - /// Default constructor - const ColorPickerCopyPasteBehavior( - {this.ctrlC = true, - this.ctrlV = true, - this.autoFocus = true, - this.copyButton = false, - this.pasteButton = false, - this.copyIcon = Icons.copy, - this.pasteIcon = Icons.paste, - this.copyTooltip, - this.pasteTooltip, - this.copyFormat = ColorPickerCopyFormat.dartCode, - this.longPressMenu = false, - this.secondaryMenu = false, - this.secondaryOnDesktopLongOnDevice = false, - this.secondaryOnDesktopLongOnDeviceAndWeb = false, - this.editFieldCopyButton = true, - this.menuIconThemeData, - this.menuThemeData, - this.menuWidth = 80, - this.menuItemHeight = 30, - this.snackBarParseError = false, - this.snackBarMessage, - this.snackBarDuration = const Duration(milliseconds: 1800), - this.feedbackParseError = false, - this.parseShortHexCode = false, - this.editUsesParsedPaste = false}); - - /// A keyboard CMD/CTRL-C press will copy the clipboard into the picker. - /// - /// When enabled, this keyboard copy color shortcut works when the - /// ColorPicker and one of its focusable widgets have focus. Those include - /// color indicator, color field, buttons, opacity slider and the picker - /// selector as well as the color wheel. - /// - /// Defaults to true. - final bool ctrlC; - - /// A keyboard CMD/CTRL-V press will paste the clipboard into the picker. - /// - /// When enabled, this keyboard copy color shortcut works when the - /// ColorPicker and one of its focusable widgets have focus. Those include - /// color indicator, color field, buttons, opacity slider and the picker - /// selector as well as the color wheel. - /// - /// Defaults to true. - final bool ctrlV; - - /// When true, the picker tries to grab the focus when the picker is created. - /// - /// By default the picker tries to set focus to its own widgets when it is - /// created. It does this when either [ctrlC] or [ctrlV] are enabled in - /// order for the keyboard listener to be able to react to copy-paste events - /// even if no control on the widget has been focused yet. - /// - /// If you need another widget to retain focus. e.g. if the picker is used on - /// surface/scope shared with other widgets and not in its own dialog, then - /// setting [autoFocus] to false might help. - /// - /// If both [ctrlC] and [ctrlV] are false, the picker yields the focus the - /// same way as setting [autoFocus] false, but then you have no keyboard - /// shortcut copy-paste functions at all. With [autoFocus] false, you - /// can still use keyboard copy-paste shortcuts and yield the focus from - /// the picker. When you do this, the copy-paste keyboard shortcuts will not - /// work until one of the picker's components have been focused by - /// interacting with them. - /// - /// The picker still grabs focus when you click on its background, as one way - /// to set focus to keyboard listener to enable copy-paste keyboard shortcuts - /// or when you operate any of its controls, the control in question - /// always gains focus. - /// - /// Default to true. - final bool autoFocus; - - /// Show a copy action icon in the picker top tool bar. - /// - /// Defaults to false. - final bool copyButton; - - /// Show a paste action icon in the picker top tool bar. - /// - /// Defaults to false. - final bool pasteButton; - - /// Icon used for the copy action. - /// - /// The same COPY icon is used in the top tool bar, on the context menu and - /// after the code field, when those features are enabled. - /// - /// Defaults to [Icons.copy]. - final IconData copyIcon; - - /// Icon used for the paste action icon in the title bar. - /// - /// The same PASTE icon is used in the top tool bar and on the context menu, - /// when those features are enabled. - /// - /// Defaults to [Icons.paste]. - final IconData pasteIcon; - - /// Label used as tooltip for copy action. - /// - /// Provide your own or use the default material localization label. - /// - /// Defaults to MaterialLocalizations.of(context).copyButtonLabel. - /// If CTRL-C copying is also enabled, the string ' (CTRL-C)' is added - /// on Linux and Windows platforms and on macOS ' (CMD-C)' is added. - final String? copyTooltip; - - /// Label used as tooltip for paste action. - /// - /// Provide your own or use the default material localization label. - /// - /// Defaults to: MaterialLocalizations.of(context).pasteButtonLabel. - /// If CTRL-V pasting is also enabled, the string ' (CTRL-V)' is added - /// on Linux and Windows platforms and on macOS ' (CMD-V)' is added. - final String? pasteTooltip; - - /// Defines the format of the copied color code string. - /// - /// Defaults to [ColorPickerCopyFormat.dartCode]. - /// - /// * [ColorPickerCopyFormat.dartCode] is Flutter Hex RGB format '0xAARRGGBB'. - /// * [ColorPickerCopyFormat.hexRRGGBB] is Hex RGB format with no - /// alpha 'RRGGBB'. - /// * [ColorPickerCopyFormat.hexAARRGGBB] is Hex RGB format with - /// alpha 'AARRGGBB'. - /// * [ColorPickerCopyFormat.numHexRRGGBB] is Web Hex RGB format with a - /// leading num # sign and no alpha '#RRGGBB'. - /// * [ColorPickerCopyFormat.numHexAARRGGBB] is Web Hex RGB format with a - /// * leading num # sign and alpha '#AARRGGBB'. - final ColorPickerCopyFormat copyFormat; - - /// Use long press in the picker to open a color copy and paste menu. - /// - /// Defaults to false. - final bool longPressMenu; - - /// Use secondary button click in the picker to open a color copy and paste - /// menu. - /// - /// Defaults to false. - final bool secondaryMenu; - - /// Use secondary button click on desktop and their web version and long - /// press on iOs/Android devices in the picker, to open a color copy and - /// paste context menu. - /// - /// Defaults to false. - final bool secondaryOnDesktopLongOnDevice; - - /// Use secondary button click on desktop and long press on iOs/Android - /// devices and all web builds in the picker, to open a color copy and - /// paste context menu. - /// - /// Defaults to false. - final bool secondaryOnDesktopLongOnDeviceAndWeb; - - /// Show a copy button suffix in the color code edit and display field. - /// - /// Defaults to true. - final bool editFieldCopyButton; - - /// The theme for the menu icons. - /// - /// The menu is compact, so icons are small by design. - /// - /// Uses any none null property in passed in [IconThemeData]. If it is - /// is null, or any property in it is null, then it uses the - /// property values from surrounding `Theme.of(context).iconTheme` if they - /// are defined. For any values that remain null value, the following - /// fallback defaults are used: - /// ``` - /// color: remains null, so default [IconThemeData] color behavior is kept. - /// size: 16 - /// opacity: 0.90 - /// ``` - final IconThemeData? menuIconThemeData; - - /// The theme of the popup menu. - /// - /// Uses any none null property in provided [PopupMenuThemeData], if it is - /// null or any property in it is null, then it uses property values from - /// `Theme.of(context).popupMenuTheme` if they are not null, for any null - /// value the following fallback defaults are used: - /// ``` - /// color: theme.cardColor.withOpacity(0.9) - /// shape: RoundedRectangleBorder( - /// borderRadius: BorderRadius.circular(8), - /// side: BorderSide( - /// color: theme.dividerColor)) - /// elevation: 3 - /// textStyle: theme.textTheme.bodyMedium! - /// enableFeedback: true - /// ``` - final PopupMenuThemeData? menuThemeData; - - /// The width of the menu. - /// - /// Defaults to 80 dp. - final double menuWidth; - - /// The height of each menu item. - /// - /// Defaults to 30 dp. - final double menuItemHeight; - - /// Show a snack bar paste parse error message when pasting something that - /// could not be parsed to a color value. - /// - /// A paste parse error occurs when something is pasted into the color picker - /// that cannot parsed to a color value. - /// - /// Defaults to false. - final bool snackBarParseError; - - /// The message shown in the paste parse error snack bar. - /// - /// The String is shown in the snack bar when there - /// is a paste parse error and [snackBarParseError] is true. - /// - /// If null, it defaults to the combination of the two Material localization - /// labels `pasteButtonLabel`: `invalidDateFormatLabel` in a [Text] widget. - /// In English it says "Paste: Invalid format.". - /// - /// The snackBar uses the closest theme with SnackBarThemeData for its - /// theming. - final String? snackBarMessage; - - /// The duration the paste parse error snack bar message is shown. - /// - /// Defaults to const Duration(milliseconds: 1800). - final Duration snackBarDuration; - - /// If true then vibrate, play audible click or an alert sound, when a - /// paste parse error occurs. - /// - /// A paste parse error occurs when something is pasted into the color picker - /// that cannot parsed to a color value. - /// - /// This feature is experimental, its support is limited on most platforms - /// in Flutter. If Flutter one day supports the Material Sound Guide, this - /// feature can be improved with better sound effects. Currently it cannot be - /// improved without importing none SDK plugins/packages to make sounds. - /// This package strives to work without any plugins or packages, so it will - /// not add any additional none Flutter SDK imports. - /// - /// Defaults to false. - final bool feedbackParseError; - - /// When true the hex color code paste action and field entry parser, - /// interpret short three character web hex color codes like in CSS. - /// - /// Web allows for short HEX RGB color codes like 123, ABC, F0C and 5D1 - /// being used as RGB hex color values. These will be interpreted as - /// 112233, AABBCC, FF00CC and 55DD11 when [parseShortHexCode] is true. - /// This parsing applies to both pasted color values and entries in the color - /// code field when [parseShortHexCode] is true. - /// - /// Defaults to false. - final bool parseShortHexCode; - - /// If true, the color code entry field uses parsed paste action for - /// keyboard shortcuts CTRL-V and CMD-V, - /// - /// A standard text field, will just paste whatever text is in the copy/paste - /// buffer into the field. This is the `false` default behavior here too, - /// with the exception that the field only accepts valid hex value input - /// chars (0-9, A-F), so it always filters and pastes only the acceptable - /// input chars from the paste buffer. - /// - /// If this property is `true`, the edit field will use the same color - /// paste value parsing used by the other paste actions used when the input - /// field is not in focus. - /// This results in a paste action in the field that always fully replaces - /// the content with the parsed color value of the pasted data, not just - /// pasting in the string in the paste buffer over selected text. - /// - /// Currently this setting only impacts CTRL-V and CMD-V keyboard shortcut - /// pasting on desktops. The paste on Android and iOS are not intercepted - /// when this setting is true. - /// - /// Defaults to false. - /// - /// The false setting is equivalent to past versions (1.x) default behavior - /// when pasting strings into the code entry field. Setting the value to true - /// may be preferred for a more consistent paste experience. - final bool editUsesParsedPaste; - - /// Copy the object with one or more provided properties changed. - ColorPickerCopyPasteBehavior copyWith({ - bool? ctrlC, - bool? ctrlV, - bool? autoFocus, - bool? copyButton, - bool? pasteButton, - IconData? copyIcon, - IconData? pasteIcon, - String? copyTooltip, - String? pasteTooltip, - ColorPickerCopyFormat? copyFormat, - bool? longPressMenu, - bool? secondaryMenu, - bool? secondaryOnDesktopLongOnDevice, - bool? secondaryOnDesktopLongOnDeviceAndWeb, - bool? editFieldCopyButton, - IconThemeData? menuIconThemeData, - PopupMenuThemeData? menuThemeData, - double? menuWidth, - double? menuItemHeight, - bool? snackBarParseError, - String? snackBarMessage, - Duration? snackBarDuration, - bool? feedbackParseError, - bool? parseShortHexCode, - bool? editUsesParsedPaste, - }) { - return ColorPickerCopyPasteBehavior( - ctrlC: ctrlC ?? this.ctrlC, - ctrlV: ctrlV ?? this.ctrlV, - autoFocus: autoFocus ?? this.autoFocus, - copyButton: copyButton ?? this.copyButton, - pasteButton: pasteButton ?? this.pasteButton, - copyIcon: copyIcon ?? this.copyIcon, - pasteIcon: pasteIcon ?? this.pasteIcon, - copyTooltip: copyTooltip ?? this.copyTooltip, - pasteTooltip: pasteTooltip ?? this.pasteTooltip, - copyFormat: copyFormat ?? this.copyFormat, - longPressMenu: longPressMenu ?? this.longPressMenu, - secondaryMenu: secondaryMenu ?? this.secondaryMenu, - secondaryOnDesktopLongOnDevice: - secondaryOnDesktopLongOnDevice ?? this.secondaryOnDesktopLongOnDevice, - secondaryOnDesktopLongOnDeviceAndWeb: - secondaryOnDesktopLongOnDeviceAndWeb ?? - this.secondaryOnDesktopLongOnDeviceAndWeb, - editFieldCopyButton: editFieldCopyButton ?? this.editFieldCopyButton, - menuIconThemeData: menuIconThemeData ?? this.menuIconThemeData, - menuThemeData: menuThemeData ?? this.menuThemeData, - menuWidth: menuWidth ?? this.menuWidth, - menuItemHeight: menuItemHeight ?? this.menuItemHeight, - snackBarParseError: snackBarParseError ?? this.snackBarParseError, - snackBarMessage: snackBarMessage ?? this.snackBarMessage, - snackBarDuration: snackBarDuration ?? this.snackBarDuration, - feedbackParseError: feedbackParseError ?? this.feedbackParseError, - parseShortHexCode: parseShortHexCode ?? this.parseShortHexCode, - editUsesParsedPaste: editUsesParsedPaste ?? this.editUsesParsedPaste, - ); - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other.runtimeType != runtimeType) return false; - return other is ColorPickerCopyPasteBehavior && - ctrlC == other.ctrlC && - ctrlV == other.ctrlV && - autoFocus == other.autoFocus && - copyButton == other.copyButton && - pasteButton == other.pasteButton && - copyIcon == other.copyIcon && - pasteIcon == other.pasteIcon && - copyTooltip == other.copyTooltip && - pasteTooltip == other.pasteTooltip && - copyFormat == other.copyFormat && - longPressMenu == other.longPressMenu && - secondaryMenu == other.secondaryMenu && - secondaryOnDesktopLongOnDevice == - other.secondaryOnDesktopLongOnDevice && - secondaryOnDesktopLongOnDeviceAndWeb == - other.secondaryOnDesktopLongOnDeviceAndWeb && - editFieldCopyButton == other.editFieldCopyButton && - menuIconThemeData == other.menuIconThemeData && - menuThemeData == other.menuThemeData && - menuWidth == other.menuWidth && - menuItemHeight == other.menuItemHeight && - snackBarParseError == other.snackBarParseError && - snackBarMessage == other.snackBarMessage && - snackBarDuration == other.snackBarDuration && - feedbackParseError == other.feedbackParseError && - parseShortHexCode == other.parseShortHexCode && - editUsesParsedPaste == other.editUsesParsedPaste; - } - - @override - int get hashCode => Object.hashAll([ - ctrlC, - ctrlV, - autoFocus, - copyButton, - pasteButton, - copyIcon, - pasteIcon, - copyTooltip, - pasteTooltip, - copyFormat, - longPressMenu, - secondaryMenu, - secondaryOnDesktopLongOnDevice, - secondaryOnDesktopLongOnDeviceAndWeb, - editFieldCopyButton, - menuIconThemeData, - menuThemeData, - menuWidth, - menuItemHeight, - snackBarParseError, - snackBarMessage, - snackBarDuration, - feedbackParseError, - parseShortHexCode, - editUsesParsedPaste, - ]); - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('ctrlC', ctrlC)); - properties.add(DiagnosticsProperty('ctrlV', ctrlV)); - properties.add(DiagnosticsProperty('autoFocus', autoFocus)); - properties.add(DiagnosticsProperty('copyButton', copyButton)); - properties.add(DiagnosticsProperty('pasteButton', pasteButton)); - properties.add(DiagnosticsProperty('copyIcon', copyIcon)); - properties.add(DiagnosticsProperty('pasteIcon', pasteIcon)); - properties.add(StringProperty('copyTooltip', copyTooltip)); - properties.add(StringProperty('pasteTooltip', pasteTooltip)); - properties - .add(EnumProperty('copyFormat', copyFormat)); - properties.add(DiagnosticsProperty('longPressMenu', longPressMenu)); - properties.add(DiagnosticsProperty('secondaryMenu', secondaryMenu)); - properties.add(DiagnosticsProperty( - 'secondaryOnDesktopLongOnDevice', secondaryOnDesktopLongOnDevice)); - properties.add(DiagnosticsProperty( - 'secondaryOnDesktopLongOnDeviceAndWeb', - secondaryOnDesktopLongOnDeviceAndWeb)); - properties.add( - DiagnosticsProperty('editFieldCopyButton', editFieldCopyButton)); - properties.add(DiagnosticsProperty( - 'menuIconThemeData', menuIconThemeData)); - properties.add(DiagnosticsProperty( - 'menuThemeData', menuThemeData)); - properties.add(DoubleProperty('menuWidth', menuWidth)); - properties.add(DoubleProperty('menuItemHeight', menuItemHeight)); - properties.add( - DiagnosticsProperty('snackBarParseError', snackBarParseError)); - properties.add(StringProperty('snackBarMessage', snackBarMessage)); - properties.add( - DiagnosticsProperty('snackBarDuration', snackBarDuration)); - properties.add( - DiagnosticsProperty('feedbackParseError', feedbackParseError)); - properties - .add(DiagnosticsProperty('parseShortHexCode', parseShortHexCode)); - properties.add( - DiagnosticsProperty('editUsesParsedPaste', editUsesParsedPaste)); - } -} diff --git a/core/lib/presentation/views/pick_color/color_picker_extensions.dart b/core/lib/presentation/views/pick_color/color_picker_extensions.dart deleted file mode 100644 index 43f19880d..000000000 --- a/core/lib/presentation/views/pick_color/color_picker_extensions.dart +++ /dev/null @@ -1,214 +0,0 @@ -import 'package:flutter/material.dart'; - -/// Extensions on non nullable [Color] to return it's color value as strings. -/// -/// The color extension also include getting a color's RGB hex code as a string -/// in two different formats. Extension [hexAlpha] returns a HEX code string of -/// a Color value including alpha channel. -/// The [hex] extension returns the hex color value as RGB string without the -/// alpha channel value. -extension FlexPickerNoNullColorExtensions on Color { - /// Return color's uppercase RGB hex string, including alpha channel. - String get hexAlpha { - return value.toRadixString(16).toUpperCase().padLeft(8, '0'); - } - - /// Return color's uppercase RGB hex string, excluding alpha channel. - String get hex { - return value.toRadixString(16).toUpperCase().padLeft(8, '0').substring(2); - } -} - -/// Extensions on [String]. -/// -/// Included extensions are, [toColor] to convert a String to a Color. -/// To [capitalize] the first letter in a String and [dotTail] to get -/// remaining string after first dot "." in a String. -extension FlexPickerNoNullStringExtensions on String { - // - /// Convert a HEX value encoded (A)RGB string to a Dart Color. - /// - /// * The string may include the '#' char, but does not have to. - /// * String may also include '0x' Dart Hex indicator, but does not have to. - /// * Any '#' '0x' patterns are trimmed out and String is assumed to be Hex. - /// * The String may start with alpha channel hex value, but does not have to, - /// if alpha value is missing "FF" is used for alpha. - /// * String may be longer than 8 chars, after trimming out # and 0x, it will - /// be RIGHT truncated to max 8 chars before parsing. - /// * If [enableShortRGB] is true a CSS style 3 char RGB value is interpreted - /// as RRGGBB, if false it used it as a partial color value. - /// - /// IF the resulting string cannot be parsed to a Color, is empty or null - /// THEN fully opaque black color is returned ELSE the Color is returned. - /// - /// To give caller a chance to handle parsing errors, use the same - /// extension on nullable Color [toColorMaybeNull]. It returns null when - /// there is a string that cannot be parsed to color value. - /// You can then decide what to do with the error instead of just receiving - /// fully opaque black color. - Color toColorShort(bool enableShortRGB) { - // If String was zero length, then we return transparent, cannot parse. - if (this == '') return const Color(0xFF000000); - // If String length is > 200 we as a safety precaution will not try to - // parse it to a color, for shorter lengths the last 8 chars will be used. - if (this.length > 200) return const Color(0xFF000000); - // Remove all num signs, we allow them, but disregard them all. - String hexColor = replaceAll('#', ''); - if (hexColor == '') return const Color(0xFF000000); - // Remove all spaces, we allow them, but disregard them all. - hexColor = hexColor.replaceAll(' ', ''); - if (hexColor == '') return const Color(0xFF000000); - // Remove all '0x' Hex code marks, we allow them, but disregard them all. - hexColor = hexColor.replaceAll('0x', ''); - if (hexColor == '') return const Color(0xFF000000); - // If the input is exactly 3 chars long, we may have a short Web hex code, - // let's make the potential 'RGB' code to a 'RRGGBB' code. - if (hexColor.length == 3 && enableShortRGB) { - hexColor = hexColor[0] + - hexColor[0] + - hexColor[1] + - hexColor[1] + - hexColor[2] + - hexColor[2]; - } - // Pad anything shorter than 7 with left 0 -> fill non spec channels with 0. - hexColor = hexColor.padLeft(6, '0'); - // Pad anything shorter than 9 with left F -> fill with opaque alpha. - hexColor = hexColor.padLeft(8, 'F'); - - // We only try to parse the last 8 chars in the remaining string, rest can - // still be whatever. - final int length = hexColor.length; - return Color(int.tryParse('0x${hexColor.substring(length - 8, length)}') ?? - 0xFF000000); - } - - /// Returns [toColorShort] with `enableShortRGB` set to true. - /// - /// Available for backwards compatibility with previous API. - Color get toColor => toColorShort(true); - - /// Capitalize the first letter in a string. - String get capitalize { - return (length > 1) ? this[0].toUpperCase() + substring(1) : toUpperCase(); - } - - /// Return the string remaining in a string after the last "." in a String, - /// if there is no "." the string itself is returned. - /// - /// This function can be used to e.g. return the enum tail value from an - /// enum's standard toString method. - String get dotTail { - return split('.').last; - } -} - -/// Extensions on [String]. -/// -/// Included extensions are, [toColorMaybeNull] to convert a String to a Color. -/// To [capitalizeMaybeNull] the first letter in a String and -/// [dotTailMaybeNull] to get remaining string after first dot "." in a String. -extension FlexPickerNullableStringExtensions on String? { - // - /// Convert a HEX value encoded (A)RGB string to a Dart Color. - /// - /// * The string may include the '#' char, but does not have to. - /// * String may also include '0x' Dart Hex indicator, but does not have to. - /// * Any '#' '0x' patterns are trimmed out and String is assumed to be Hex. - /// * The String may start with alpha channel hex value, but does not have to, - /// if alpha value is missing "FF" is used for alpha. - /// * String may be longer than 8 chars, after trimming out # and 0x, it will - /// be RIGHT truncated to max 8 chars before parsing. - /// * If [enableShortRGB] is true a CSS style 3 char RGB value is interpreted - /// as RRGGBB, if false it used it as a partial color value. - /// - /// IF the resulting string cannot be parsed to a Color, is empty or null - /// THEN NULL is returned ELSE the Color is returned. - Color? toColorShortMaybeNull(bool enableShortRGB) { - // If String was null or zero length, then we return null, cannot parse. - if (this == null || this == '') return null; - // If String length is > 200 we as a safety precaution will not try to - // parse it to a color, for shorter lengths the last 8 chars will be used. - if ((this?.length ?? 200) > 200) return null; - // Remove all num signs, we allow them, but disregard them all. - String hexColor = this?.replaceAll('#', '') ?? ''; - if (hexColor == '') return null; - // Remove all spaces, we allow them, but disregard them all. - hexColor = hexColor.replaceAll(' ', ''); - if (hexColor == '') return null; - // Remove all '0x' Hex code marks, we allow them, but disregard them all. - hexColor = hexColor.replaceAll('0x', ''); - if (hexColor == '') return null; - // If the input is exactly 3 chars long, we may have a short Web hex code, - // let's make the potential 'RGB' code to a 'RRGGBB' code. - if (hexColor.length == 3 && enableShortRGB) { - hexColor = hexColor[0] + - hexColor[0] + - hexColor[1] + - hexColor[1] + - hexColor[2] + - hexColor[2]; - } - // Pad anything shorter than 7 with left 0 -> fill non spec channels with 0. - hexColor = hexColor.padLeft(6, '0'); - // Pad anything shorter than 9 with left F -> fill with opaque alpha. - hexColor = hexColor.padLeft(8, 'F'); - - // We only try to parse the last 8 chars in the remaining string, rest can - // still be whatever. - final int length = hexColor.length; - final int? intColor = - int.tryParse('0x${hexColor.substring(length - 8, length)}'); - return intColor != null ? Color(intColor) : null; - } - - /// Returns [toColorShortMaybeNull] with `enableShortRGB` set to true. - /// - /// Available for backwards compatibility with previous API. - Color? get toColorMaybeNull => toColorShortMaybeNull(true); - - /// Capitalize the first letter in a string. If string is null, we get null - /// back. - String? get capitalizeMaybeNull { - if (this == null) { - return this; - } else { - return ((this?.length ?? 0) > 1) - ? (this?[0].toUpperCase() ?? '') + (this?.substring(1) ?? '') - : this?.toUpperCase() ?? ''; - } - } - - /// Return the string remaining in a string after the last "." in a String, - /// if there is no "." the string itself is returned. If string is null - /// we get null back. - /// - /// This function can be used to e.g. return the enum tail value from an - /// enum's standard toString method. - String? get dotTailMaybeNull { - if (this == null) { - return this; - } else { - return this?.split('.').last; - } - } -} - -/// Returns the control key label for the current platform. -/// -/// Windows, Linux: CTRL -/// Mac: CMD (Tried using the ⌘ symbol, did not show up on Web though.) -/// Others: Empty string -String platformControlKey(TargetPlatform platform, String key) { - switch (platform) { - case TargetPlatform.android: - case TargetPlatform.iOS: - case TargetPlatform.fuchsia: - return ''; - case TargetPlatform.linux: - case TargetPlatform.windows: - return ' (CTRL-$key)'; - case TargetPlatform.macOS: - return ' (CMD-$key)'; - } -} \ No newline at end of file diff --git a/core/lib/presentation/views/pick_color/dry_intrinsic.dart b/core/lib/presentation/views/pick_color/dry_intrinsic.dart deleted file mode 100644 index 597728910..000000000 --- a/core/lib/presentation/views/pick_color/dry_intrinsic.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; - -// These two classes are a workaround to issue: -// https://github.com/flutter/flutter/issues/71687 -// This workaround for the issue was made by: -// @slightfoot and @matthew-carroll (GitHub accounts) - -/// Same as `IntrinsicWidth` except that when this widget is instructed -/// to `computeDryLayout()`, it doesn't invoke that on its child, instead -/// it computes the child's intrinsic width. -/// -/// This widget is useful in situations where the `child` does not -/// support dry layout, e.g., `TextField` as of 01/02/2021. -/// -/// Not library exposed, private to the package. -@immutable -class DryIntrinsicWidth extends SingleChildRenderObjectWidget { - /// Default const constructor. - const DryIntrinsicWidth({ - super.key, - required Widget super.child, - }); - - @override - _RenderDryIntrinsicWidth createRenderObject(BuildContext context) => - _RenderDryIntrinsicWidth(); -} - -class _RenderDryIntrinsicWidth extends RenderIntrinsicWidth { - @override - Size computeDryLayout(BoxConstraints constraints) { - if (child != null) { - final double? width = - child?.computeMinIntrinsicWidth(constraints.maxHeight); - final double? height = child?.computeMinIntrinsicHeight(width ?? 0); - return Size(width ?? 0, height ?? 0); - } else { - return Size.zero; - } - } -} - -/// Same as `IntrinsicHeight` except that when this widget is instructed -/// to `computeDryLayout()`, it doesn't invoke that on its child, instead -/// it computes the child's intrinsic height. -/// -/// This widget is useful in situations where the `child` does not -/// support dry layout, e.g., `TextField` as of 01/02/2021. -/// -/// Not library exposed, private to the library. -@immutable -class DryIntrinsicHeight extends SingleChildRenderObjectWidget { - /// Default const constructor. - const DryIntrinsicHeight({ - super.key, - required Widget super.child, - }); - - @override - _RenderDryIntrinsicHeight createRenderObject(BuildContext context) => - _RenderDryIntrinsicHeight(); -} - -class _RenderDryIntrinsicHeight extends RenderIntrinsicHeight { - @override - Size computeDryLayout(BoxConstraints constraints) { - if (child != null) { - final double? height = - child?.computeMinIntrinsicHeight(constraints.maxWidth); - final double? width = child?.computeMinIntrinsicWidth(height ?? 0); - return Size(width ?? 0, height ?? 0); - } else { - return Size.zero; - } - } -} diff --git a/core/pubspec.lock b/core/pubspec.lock index a6408da6d..5b95455b5 100644 --- a/core/pubspec.lock +++ b/core/pubspec.lock @@ -145,6 +145,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + flex_color_picker: + dependency: "direct main" + description: + name: flex_color_picker + sha256: f0e0db8e3e47435cfbe9aa15c71b898fa218be0fc4ae409e1e42d5d5266b2c90 + url: "https://pub.dev" + source: hosted + version: "3.2.0" + flex_seed_scheme: + dependency: transitive + description: + name: flex_seed_scheme + sha256: "7058288ef97d348657ac95cea25d65a9aac181ca08387ede891fd7230ad7600f" + url: "https://pub.dev" + source: hosted + version: "1.2.3" flutter: dependency: "direct main" description: flutter @@ -559,4 +575,4 @@ packages: version: "6.2.2" sdks: dart: ">=2.19.2 <3.0.0" - flutter: ">=3.7.0-0" + flutter: ">=3.7.0" diff --git a/core/pubspec.yaml b/core/pubspec.yaml index a9a09cb7d..d95175a91 100644 --- a/core/pubspec.yaml +++ b/core/pubspec.yaml @@ -59,6 +59,8 @@ dependencies: flutter_keyboard_visibility: 5.4.0 + flex_color_picker: 3.2.0 + flutter_image_compress: 1.1.3 http_parser: 4.0.2 diff --git a/pubspec.lock b/pubspec.lock index 1f602102b..77277dcc9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -516,10 +516,10 @@ packages: dependency: transitive description: name: flex_color_picker - sha256: "607c9fdb26be84d4a5a0931ab42a7eda725372e4f5ebaa2526ab6b22ead752f9" + sha256: f0e0db8e3e47435cfbe9aa15c71b898fa218be0fc4ae409e1e42d5d5266b2c90 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.2.0" flex_seed_scheme: dependency: transitive description: