Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 2.0.1 #16

Merged
merged 3 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
name: Deploy Web
on:
push:
branches: [master]
branches: [none]
#release:
# types: [published]
# Edit and add other trigger options if an extra new Web deployment is needed.
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
- name: Verify that Dart formatting is used, fail if not
run: dart format --output=none --set-exit-if-changed .

- name: Test package FlexColorScheme using test coverage
- name: Test package FlexColorPicker using test coverage
run: flutter test --coverage

- name: Upload test coverage to Codecov
Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All notable changes to the **FlexColorPicker** package will be documented in this file.

## [2.0.1] - April 10, 2021
* **New feature:** Enabled updating the color picker externally. Just set the `color` property of the widget to a
new value to update it. You can even "remote control" the color picker by updating the `color`, if so needed.

This is mostly a potential use-case for desktop/web when the picker is not used in a dialog.
You can of course use this on a phone or tablet too, but often there is not room enough to keep the picker
visible on the main surface this way on mobile devices. However, on desktops it is certainly a valid use
case that should be supported. It was previously not supported by design, but as we are going for covering
web/desktop use-cases, it should certainly be supported. This update adds support for it. The picker only
updates if the externally provided `color` constructor property differs from its internally kept color
state. Finding the right picker, computing its swatches, is a bit demanding, but it seems to work fluidly,
even when remote controlling the wheel and sliders interactively.

* **Web example**: Updated the Web example to also show the "remote control" of the on-screen color picker. A
remote control widget with a few color boxes, that you can click on to update its colors externally was added.
The demo even goes meta! You can use a modal dialog version of the ColorPicker, to control the ColorPicker
on the screen in the card, from the dialog ColorPicker! Maybe not as such so useful, but an interesting demo.

## [2.0.0] - April 9, 2021
* This release only contains documentation updates from pre-release **2.0.0-nullsafety.5**
* Thi is the first stable release of the null-safe version
Expand All @@ -14,7 +32,7 @@ All notable changes to the **FlexColorPicker** package will be documented in thi
### Breaking Changes
In addition to breaking changes as a result of the null-safety implementation, this release contain a few other
**minor breaking changes** from version 1.x, they mostly concern visual nuances and label defaults.


* The `colorCodeIcon` has been deprecated and no longer has any function. To modify the copy icon on the color
code entry field, define the `ColorPickerCopyPasteBehavior(copyIcon: myIcon)` and provide it to the
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,12 @@ ColorPicker(
),
```

If you need to update the `ColorPicker` externally, just pass in a new value to the `color` property.
In the above example you could give the state variable `myColor` a new value from some other place than
the above `onColorChanged` callback, and call `setState`. The [live Web demo](https://rydmike.com/flexcolorpicker/)
includes an example of how you can update the `ColorPicker` via other widget interactions,
or even remote control, or mirror it completely from another **FlexColorPicker** opened as a dialog.

### Enabled Color Pickers

API reference: [pickersEnabled](https://pub.dev/documentation/flex_color_picker/latest/flex_color_picker/ColorPicker/pickersEnabled.html)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Picker indicators
export 'picker_indicators/card_picker_color_indicator.dart';
export 'picker_indicators/dialog_picker_color_indicator.dart';
export 'picker_indicators/meta_picker_color_indicator.dart';
export 'picker_indicators/on_changed_color_indicator.dart';
export 'picker_indicators/on_end_color_indicator.dart';
export 'picker_indicators/on_start_color_indicator.dart';
Expand Down
24 changes: 18 additions & 6 deletions example/lib/demo/screens/color_picker/color_picker_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,32 @@ import '../../pods/pods.dart';
import '../../utils/app.dart';

/// The ColorPicker shown in a dialog that is opened from the ColorPickerScreen.
Future<bool> colorPickerDialog(BuildContext context, ScopedReader watch) async {
Future<bool> colorPickerDialog(
BuildContext context,
ScopedReader watch, {
bool cardRemote = false,
}) async {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return ColorPicker(
color: watch(dialogPickerColorPod).state,
color: cardRemote
? watch(cardPickerColorPod).state
: watch(dialogPickerColorPod).state,
onColorChangeStart: (Color color) {
context.read(onColorChangeStartPod).state = color;
},
onColorChanged: (Color color) {
context.read(dialogPickerColorPod).state = color;
cardRemote
? context.read(cardPickerColorPod).state = color
: context.read(dialogPickerColorPod).state = color;
context.read(onColorChangedPod).state = color;
},
onColorChangeEnd: (Color color) {
context.read(onColorChangeEndPod).state = color;
},
onRecentColorsChanged: (List<Color> colors) {
context.read(dialogRecentColorsPod).state = colors;
cardRemote
? context.read(cardRecentColorsPod).state = colors
: context.read(dialogRecentColorsPod).state = colors;
},
crossAxisAlignment: watch(alignmentPod).state,
padding: EdgeInsets.all(watch(paddingPod).state),
Expand Down Expand Up @@ -114,8 +124,10 @@ Future<bool> colorPickerDialog(BuildContext context, ScopedReader watch) async {
colorCodeReadOnly: watch(colorCodeReadOnlyPod).state,
showColorValue: watch(showColorValuePod).state,
showRecentColors: watch(showRecentColorsPod).state,
recentColors: watch(dialogRecentColorsPod).state,
maxRecentColors: 5,
recentColors: cardRemote
? watch(cardRecentColorsPod).state
: watch(dialogRecentColorsPod).state,
maxRecentColors: cardRemote ? 8 : 5,
customColorSwatchesAndNames: App.colorsNameMap,
).showPickerDialog(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ class _Column1 extends StatelessWidget {
const DialogPickerColorIndicator(),
// Show the color selected in the picker in a Card below.
const CardPickerColorIndicator(),
// Show the picker meta remote control widget.
const MetaPickerColorIndicator(),
// The color picker in a Card.
const Padding(
padding: EdgeInsets.all(6),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class CardPickerColorIndicator extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
return ListTile(
title: const Text('Select color below to change this color'),
title: const Text('Change this color with the ColorPicker below'),
subtitle: Text(
'${ColorTools.materialNameAndARGBCode(watch(cardPickerColorPod).state, colorSwatchNameMap: App.colorsNameMap)} '
'aka ${ColorTools.nameThatColor(watch(cardPickerColorPod).state)}'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DialogPickerColorIndicator extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
return ListTile(
title: const Text('Click this color to change it in a dialog'),
title: const Text('Click this color to update it from a dialog'),
subtitle: Text(
'${ColorTools.materialNameAndARGBCode(watch(dialogPickerColorPod).state, colorSwatchNameMap: App.colorsNameMap)} '
'aka ${ColorTools.nameThatColor(watch(dialogPickerColorPod).state)}'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'package:flex_color_picker/flex_color_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../pods/pods.dart';
import '../color_picker_dialog.dart';

@immutable
class MetaPickerColorIndicator extends ConsumerWidget {
const MetaPickerColorIndicator({Key? key}) : super(key: key);

@override
Widget build(BuildContext context, ScopedReader watch) {
return ListTile(
title: const Text('Control the ColorPicker below'),
subtitle: Wrap(
runSpacing: 4,
spacing: 4,
children: const <Widget>[
ColorControlBox(color: Color(0xFF43A047)),
ColorControlBox(color: Color(0xCAFF5252)),
ColorControlBox(color: Color(0xFFF7F7F7)),
ColorControlBox(color: Color(0xF04F75B8)),
ColorControlBox(color: Color(0xA8E86600)),
ColorControlBox(color: Color(0xFFFF5319)),
ColorControlBox(color: Color(0xFF7D2079)),
],
),
trailing: ColorIndicator(
height: watch(sizePod).state,
width: watch(sizePod).state,
borderRadius: watch(borderRadiusPod).state,
elevation: watch(elevationPod).state,
color: watch(cardPickerColorPod).state,
hasBorder: watch(hasBorderPod).state,
onSelectFocus: false,
onSelect: () async {
final Color colorBeforeDialog =
context.read(cardPickerColorPod).state;
if (!(await colorPickerDialog(
context,
watch,
cardRemote: true,
))) {
context.read(cardPickerColorPod).state = colorBeforeDialog;
}
},
),
);
}
}

class ColorControlBox extends ConsumerWidget {
const ColorControlBox({
Key? key,
required this.color,
}) : super(key: key);

final Color color;

@override
Widget build(BuildContext context, ScopedReader watch) {
return ColorIndicator(
height: watch(sizePod).state * 0.8,
width: watch(sizePod).state * 0.8,
borderRadius: watch(borderRadiusPod).state * 0.8,
elevation: watch(elevationPod).state,
color: watch(enableOpacityPod).state ? color : color.withAlpha(0xFF),
hasBorder: watch(hasBorderPod).state,
onSelectFocus: false,
isSelected: watch(cardPickerColorPod).state == color,
onSelect: () {
context.read(cardPickerColorPod).state = color;
},
);
}
}
2 changes: 1 addition & 1 deletion example/lib/demo/utils/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class App {
// Web demo with inside the app. Shown on the start screen in the demo,
// so people testing it don't have to ask. Also info for the About screen.
static const String appName = 'FlexColorPicker';
static const String version = '2.0.0';
static const String version = '2.0.1';
static const String packageVersion = 'FlexColorScheme package $version';
static const String packageUrl = 'https://pub.dev/packages/flex_color_picker';
static const String flutterVersion = 'Channel beta 2.1.0-12.2.pre, CanvasKit';
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ packages:
path: ".."
relative: true
source: path
version: "2.0.0"
version: "2.0.1"
flutter:
dependency: "direct main"
description: flutter
Expand Down
5 changes: 3 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
name: color_picker_example
description: Two examples of how to use the FlexColorPicker package.
version: 2.0.0
version: 2.0.1
publish_to: 'none'
environment:
sdk: '>=2.12.0 <3.0.0'

dependencies:
# https://pub.dev/packages/flex_color_picker
flex_color_picker: ^2.0.0
flex_color_picker:
path: ../

flutter:
sdk: flutter
Expand Down
40 changes: 34 additions & 6 deletions lib/src/color_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,9 @@ class _ColorPickerState extends State<ColorPicker> {
void didUpdateWidget(ColorPicker oldWidget) {
// debugPrint('didUpdateWidget called **********************************');

// Set to true if a change was done where we need to find the picker again.
bool _shouldFindPickerAndSwatch = false;

// Opacity enable/disable changed, update selected color and opacity.
if (widget.enableOpacity != oldWidget.enableOpacity) {
// debugPrint('didUpdateWidget enableOpacity = '
Expand All @@ -1089,8 +1092,8 @@ class _ColorPickerState extends State<ColorPicker> {
widget.enableOpacity ? widget.color : widget.color.withAlpha(0xFF);
_opacity = widget.enableOpacity ? widget.color.opacity : 1;
}
// Picker labels map changed, update used one, with its default fallbacks.

// Picker labels map changed, update used one, with its default fallbacks.
if (!mapEquals(widget.pickerTypeLabels, oldWidget.pickerTypeLabels)) {
// debugPrint('didUpdateWidget pickerTypeLabels mapEquals: '
// '${mapEquals(widget.pickerTypeLabels, oldWidget.pickerTypeLabels)}');
Expand Down Expand Up @@ -1134,6 +1137,8 @@ class _ColorPickerState extends State<ColorPicker> {
// Therefore using `toString` comparisons for now to get around the issue,
// not ideal, but it seems to work.

// debugPrint('didUpdateWidget pickersEnabled or custom swatch updated!');

// Update _typeToSwatchMap, because custom color swatches were updated.
_typeToSwatchMap = <ColorPickerType, List<ColorSwatch<Object>>>{
ColorPickerType.both: ColorTools.primaryAndAccentColors,
Expand Down Expand Up @@ -1167,12 +1172,9 @@ class _ColorPickerState extends State<ColorPicker> {
};
// debugPrint('${widget.customColorSwatchesAndNames}');
// debugPrint('${oldWidget.customColorSwatchesAndNames}');
// debugPrint('didUpdateWidget calls findPicker and updateActiveSwatch');

// When in this IF branch, we need to find the right picker again.
_findPicker();
// And also update the active swatch again.
_updateActiveSwatch();
// We should find picker and swatch after above updates.
_shouldFindPickerAndSwatch = true;
}
// If the recent colors that is stored in local state version is
// not equal to the one passed in, then the picker got a new externally
Expand All @@ -1182,6 +1184,32 @@ class _ColorPickerState extends State<ColorPicker> {
if (!listEquals(widget.recentColors, _recentColors)) {
_recentColors = <Color>[...widget.recentColors];
}
// The widget color was updated externally since it differs from internally
// kept state, we should update the widget to new color and find picker.
if (widget.color != _selectedColor) {
// debugPrint('didUpdateWidget external color update!');
_selectedColor =
widget.enableOpacity ? widget.color : widget.color.withAlpha(0xFF);
_opacity = widget.enableOpacity ? widget.color.opacity : 1;
// Need to make a swatch too be able to find it on wheel, if it is there.
_typeToSwatchMap[ColorPickerType.wheel] = <ColorSwatch<Object>>[
ColorTools.createPrimarySwatch(_selectedColor.withAlpha(0xFF)),
];
// Wheel and edit needs to update.
_wheelShouldUpdate = true;
_editShouldUpdate = true;
// We need to find the right picker again.
_shouldFindPickerAndSwatch = true;
}
//
if (_shouldFindPickerAndSwatch) {
// debugPrint('didUpdateWidget calls findPicker and updateActiveSwatch');

// When in this IF branch, we need to find the right picker again.
_findPicker();
// And also update the active swatch again.
_updateActiveSwatch();
}
//
super.didUpdateWidget(oldWidget);
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flex_color_picker
description: A customizable Flutter primary, accent and custom color picker. Includes an optional HSV wheel color picker.
version: 2.0.0
version: 2.0.1
homepage: https://github.com/rydmike/flex_color_picker

environment:
Expand Down