From 6fc86505e39864dfb8f026fc97b2fb5e20366a0b Mon Sep 17 00:00:00 2001
From: nohli <43643339+nohli@users.noreply.github.com>
Date: Mon, 20 Sep 2021 13:06:53 +0200
Subject: [PATCH] Improve UI and architecture (#15)
* Fix deprecations
* Increase opacity to make letters above the sliders more readable
* Improve color of app bar and button (especially in dark mode)
* Make title of sliders look the same everywhere and move to own class
* Create folder structure pickers for picker pages and widgets/ for smaller widgets
* Simplify code
* Make text and button height aligned
* Make SliderTitle Text widgets vertically aligned
* Improve opacity of SliderTitle's left text
* Rename methods
* Improve ui (padding, remove underline in portrait mode)
* Auto-update files
* Auto-format example/pubspec.yaml
* Update version and changelog
* Update flutter_lints
* Improve UI
* Improve UI
* Improve UI
* User BorderRadius.circular constructor
* Make padding on SliderTitle symmetric to better support RTL layout
* Use SizedBox for whitespace
* Use Container instead of Padding plus SizedBox and DecoratedBox
* Use BorderRadius.circular constructor
* Refactor SliderTitle
* Improve UI
* Add alignment and margin to Row instead of each of its children
---
CHANGELOG.md | 6 ++
example/ios/Flutter/AppFrameworkInfo.plist | 2 +-
example/ios/Runner.xcodeproj/project.pbxproj | 6 +-
example/lib/main.dart | 4 +-
example/lib/main_page.dart | 15 ++--
example/pubspec.yaml | 6 +-
lib/flutter_hsvcolor_picker.dart | 22 +++---
lib/src/color_picker.dart | 74 +++++++++----------
lib/src/{ => pickers}/hsv_picker.dart | 35 ++-------
lib/src/{ => pickers}/palette_hue_picker.dart | 4 +-
.../palette_saturation_picker.dart | 4 +-
.../{ => pickers}/palette_value_picker.dart | 4 +-
lib/src/{ => pickers}/rgb_picker.dart | 40 ++--------
lib/src/{ => pickers}/swatches_picker.dart | 0
lib/src/{ => pickers}/wheel_picker.dart | 0
lib/src/{ => widgets}/alpha_picker.dart | 29 +-------
lib/src/{ => widgets}/hex_picker.dart | 0
lib/src/{ => widgets}/palette_picker.dart | 0
lib/src/{ => widgets}/slider_picker.dart | 0
lib/src/widgets/slider_title.dart | 40 ++++++++++
pubspec.yaml | 4 +-
21 files changed, 129 insertions(+), 166 deletions(-)
rename lib/src/{ => pickers}/hsv_picker.dart (70%)
rename lib/src/{ => pickers}/palette_hue_picker.dart (96%)
rename lib/src/{ => pickers}/palette_saturation_picker.dart (96%)
rename lib/src/{ => pickers}/palette_value_picker.dart (96%)
rename lib/src/{ => pickers}/rgb_picker.dart (72%)
rename lib/src/{ => pickers}/swatches_picker.dart (100%)
rename lib/src/{ => pickers}/wheel_picker.dart (100%)
rename lib/src/{ => widgets}/alpha_picker.dart (71%)
rename lib/src/{ => widgets}/hex_picker.dart (100%)
rename lib/src/{ => widgets}/palette_picker.dart (100%)
rename lib/src/{ => widgets}/slider_picker.dart (100%)
create mode 100644 lib/src/widgets/slider_title.dart
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32f8083..469b83e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [1.2.0]
+
+* Update deprecated theme color (accentColor -> colorScheme.secondary)
+* Improve UI
+* Refactor folder structure
+
## [1.1.0]
* Fix ColorPicker not shown in landscape mode
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 9367d48..8d4492f 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 8.0
+ 9.0
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index 0b79aee..bc99da3 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -284,7 +284,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -361,7 +361,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -408,7 +408,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
diff --git a/example/lib/main.dart b/example/lib/main.dart
index cbd89f4..683e88f 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -4,9 +4,7 @@ import 'package:flutter/widgets.dart';
import 'main_page.dart';
-void main() async {
- runApp(const MyApp());
-}
+void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
diff --git a/example/lib/main_page.dart b/example/lib/main_page.dart
index b7cea52..43359af 100644
--- a/example/lib/main_page.dart
+++ b/example/lib/main_page.dart
@@ -181,7 +181,7 @@ class _MainPageState extends State {
Widget buildDrawerHeader() {
return DrawerHeader(
- decoration: BoxDecoration(color: theme.accentColor),
+ decoration: const BoxDecoration(color: Colors.blue),
child: Stack(
children: [
// Avatar
@@ -196,10 +196,13 @@ class _MainPageState extends State {
backgroundColor: theme.cardColor,
backgroundImage: const AssetImage('packages/avatar.jpg'),
),
- Container(height: 10.0),
- const Text(
- '淹死的鱼ysdy44',
- style: TextStyle(color: Colors.white, fontSize: 18.0),
+ const SizedBox(height: 10.0),
+ const Padding(
+ padding: EdgeInsets.only(bottom: 8),
+ child: Text(
+ '淹死的鱼ysdy44',
+ style: TextStyle(color: Colors.white, fontSize: 18.0),
+ ),
)
],
),
@@ -211,7 +214,7 @@ class _MainPageState extends State {
child: ElevatedButton(
onPressed: setTheme,
style: ElevatedButton.styleFrom(
- primary: theme.accentColor,
+ primary: Colors.blue.shade400,
shape: const StadiumBorder(),
),
child: Text(
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 9fbe68d..eb11cd0 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -13,10 +13,10 @@ dependencies:
path: ../
dev_dependencies:
- flutter_lints: ^1.0.3
+ flutter_lints: ^1.0.4
flutter:
uses-material-design: true
-
+
assets:
- - packages/avatar.jpg
+ - packages/avatar.jpg
diff --git a/lib/flutter_hsvcolor_picker.dart b/lib/flutter_hsvcolor_picker.dart
index 5a56fc6..d8f7f8a 100644
--- a/lib/flutter_hsvcolor_picker.dart
+++ b/lib/flutter_hsvcolor_picker.dart
@@ -1,14 +1,14 @@
library flutter_hsvcolor_picker;
-export 'src/alpha_picker.dart';
+export 'src/widgets/alpha_picker.dart';
export 'src/color_picker.dart';
-export 'src/hex_picker.dart';
-export 'src/hsv_picker.dart';
-export 'src/palette_hue_picker.dart';
-export 'src/palette_picker.dart';
-export 'src/palette_saturation_picker.dart';
-export 'src/palette_value_picker.dart';
-export 'src/rgb_picker.dart';
-export 'src/slider_picker.dart';
-export 'src/swatches_picker.dart';
-export 'src/wheel_picker.dart';
+export 'src/widgets/hex_picker.dart';
+export 'src/pickers/hsv_picker.dart';
+export 'src/pickers/palette_hue_picker.dart';
+export 'src/widgets/palette_picker.dart';
+export 'src/pickers/palette_saturation_picker.dart';
+export 'src/pickers/palette_value_picker.dart';
+export 'src/pickers/rgb_picker.dart';
+export 'src/widgets/slider_picker.dart';
+export 'src/pickers/swatches_picker.dart';
+export 'src/pickers/wheel_picker.dart';
diff --git a/lib/src/color_picker.dart b/lib/src/color_picker.dart
index 37706ae..c27833b 100644
--- a/lib/src/color_picker.dart
+++ b/lib/src/color_picker.dart
@@ -1,14 +1,14 @@
import 'package:flutter/material.dart';
-import 'alpha_picker.dart';
-import 'hex_picker.dart';
-import 'hsv_picker.dart';
-import 'palette_hue_picker.dart';
-import 'palette_saturation_picker.dart';
-import 'palette_value_picker.dart';
-import 'rgb_picker.dart';
-import 'swatches_picker.dart';
-import 'wheel_picker.dart';
+import 'widgets/alpha_picker.dart';
+import 'widgets/hex_picker.dart';
+import 'pickers/hsv_picker.dart';
+import 'pickers/palette_hue_picker.dart';
+import 'pickers/palette_saturation_picker.dart';
+import 'pickers/palette_value_picker.dart';
+import 'pickers/rgb_picker.dart';
+import 'pickers/swatches_picker.dart';
+import 'pickers/wheel_picker.dart';
enum Picker {
swatches,
@@ -195,10 +195,10 @@ class _ColorPickerState extends State {
child: Text(
item.name,
style: _index == _pickers.indexOf(item)
- ? Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontSize: 18, color: Theme.of(context).accentColor)
+ ? Theme.of(context).textTheme.headline5?.copyWith(
+ fontSize: 18,
+ color: Theme.of(context).colorScheme.secondary,
+ )
: Theme.of(context).textTheme.headline5?.copyWith(fontSize: 18),
),
),
@@ -244,7 +244,7 @@ class _ColorPickerState extends State {
);
}
- Widget _buildDropdown() {
+ Widget _buildDropdownLandscapeMode() {
return SizedBox(
height: 38,
child: Material(
@@ -252,10 +252,8 @@ class _ColorPickerState extends State {
color: Theme.of(context).cardColor,
shadowColor: Colors.black26,
elevation: 4.0,
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.all(
- Radius.circular(2.0),
- ),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(2.0),
),
child: DropdownButton<_IPicker>(
iconSize: 32.0,
@@ -272,27 +270,25 @@ class _ColorPickerState extends State {
);
}
- Widget _buildDropdown2() {
- return SizedBox(
+ Widget _buildDropdownPortraitMode() {
+ return Container(
+ margin: const EdgeInsets.symmetric(vertical: 6.0),
height: 38,
- child: DecoratedBox(
- decoration: BoxDecoration(
- border: Border.all(color: Theme.of(context).dividerColor),
- borderRadius: const BorderRadius.all(
- Radius.circular(3.0),
- ),
- ),
- child: DropdownButton<_IPicker>(
- iconSize: 32.0,
- isExpanded: true,
- isDense: true,
- style: Theme.of(context).textTheme.headline5?.copyWith(fontSize: 20),
- value: _pickers[_index],
- onChanged: (_IPicker? value) => super.setState(
- () => _pickerOnChanged(value),
- ),
- items: _pickers.map(_buildDropdownMenuItems).toList(),
+ decoration: BoxDecoration(
+ border: Border.all(color: Theme.of(context).dividerColor),
+ borderRadius: BorderRadius.circular(3.0),
+ ),
+ child: DropdownButton<_IPicker>(
+ iconSize: 32.0,
+ isExpanded: true,
+ isDense: true,
+ style: Theme.of(context).textTheme.headline5?.copyWith(fontSize: 20),
+ value: _pickers[_index],
+ onChanged: (_IPicker? value) => super.setState(
+ () => _pickerOnChanged(value),
),
+ items: _pickers.map(_buildDropdownMenuItems).toList(),
+ underline: const SizedBox(),
),
);
}
@@ -321,7 +317,7 @@ class _ColorPickerState extends State {
mainAxisSize: MainAxisSize.min,
children: [
_buildHead(),
- _buildDropdown2(),
+ _buildDropdownPortraitMode(),
_buildBody(),
_buildAlphaPicker(),
],
@@ -336,7 +332,7 @@ class _ColorPickerState extends State {
mainAxisSize: MainAxisSize.min,
children: [
_buildHead(),
- _buildDropdown(),
+ _buildDropdownLandscapeMode(),
_buildAlphaPicker(),
],
),
diff --git a/lib/src/hsv_picker.dart b/lib/src/pickers/hsv_picker.dart
similarity index 70%
rename from lib/src/hsv_picker.dart
rename to lib/src/pickers/hsv_picker.dart
index d579fea..edc352c 100644
--- a/lib/src/hsv_picker.dart
+++ b/lib/src/pickers/hsv_picker.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
-import 'slider_picker.dart';
+import '../widgets/slider_picker.dart';
+import '../widgets/slider_title.dart';
/// Three sliders for selections a color via:
/// Hue
@@ -55,39 +56,13 @@ class _HSVPickerState extends State {
color.withValue(1.0).toColor(),
];
- Widget buildTitle(String title, String text) {
- return SizedBox(
- height: 34.0,
- child: Row(
- children: [
- Opacity(
- opacity: 0.5,
- child: Text(title, style: Theme.of(context).textTheme.headline6),
- ),
- Expanded(
- child: Align(
- alignment: Alignment.centerRight,
- child: Text(
- text,
- style: Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontSize: 18),
- ),
- ),
- )
- ],
- ),
- );
- }
-
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Hue
- buildTitle('H', '${color.hue.toInt()}º'),
+ SliderTitle('H', '${color.hue.toInt()}º'),
SliderPicker(
value: color.hue,
max: 360.0,
@@ -96,7 +71,7 @@ class _HSVPickerState extends State {
),
// Saturation
- buildTitle('S', '${(color.saturation * 100).toInt()}º'),
+ SliderTitle('S', '${(color.saturation * 100).toInt()}º'),
SliderPicker(
value: color.saturation,
onChanged: saturationOnChange,
@@ -104,7 +79,7 @@ class _HSVPickerState extends State {
),
// Value
- buildTitle('L', '${(color.value * 100).toInt()}º'),
+ SliderTitle('L', '${(color.value * 100).toInt()}º'),
SliderPicker(
value: color.value,
onChanged: valueOnChange,
diff --git a/lib/src/palette_hue_picker.dart b/lib/src/pickers/palette_hue_picker.dart
similarity index 96%
rename from lib/src/palette_hue_picker.dart
rename to lib/src/pickers/palette_hue_picker.dart
index e196b09..639ba3f 100644
--- a/lib/src/palette_hue_picker.dart
+++ b/lib/src/pickers/palette_hue_picker.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
-import 'palette_picker.dart';
-import 'slider_picker.dart';
+import '../widgets/palette_picker.dart';
+import '../widgets/slider_picker.dart';
/// Color palette and color slider
class PaletteHuePicker extends StatefulWidget {
diff --git a/lib/src/palette_saturation_picker.dart b/lib/src/pickers/palette_saturation_picker.dart
similarity index 96%
rename from lib/src/palette_saturation_picker.dart
rename to lib/src/pickers/palette_saturation_picker.dart
index 8e1741a..72a1657 100644
--- a/lib/src/palette_saturation_picker.dart
+++ b/lib/src/pickers/palette_saturation_picker.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
-import 'palette_picker.dart';
-import 'slider_picker.dart';
+import '../widgets/palette_picker.dart';
+import '../widgets/slider_picker.dart';
class PaletteSaturationPicker extends StatefulWidget {
const PaletteSaturationPicker({
diff --git a/lib/src/palette_value_picker.dart b/lib/src/pickers/palette_value_picker.dart
similarity index 96%
rename from lib/src/palette_value_picker.dart
rename to lib/src/pickers/palette_value_picker.dart
index ac9f938..431bc55 100644
--- a/lib/src/palette_value_picker.dart
+++ b/lib/src/pickers/palette_value_picker.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
-import 'palette_picker.dart';
-import 'slider_picker.dart';
+import '../widgets/palette_picker.dart';
+import '../widgets/slider_picker.dart';
class PaletteValuePicker extends StatefulWidget {
const PaletteValuePicker({
diff --git a/lib/src/rgb_picker.dart b/lib/src/pickers/rgb_picker.dart
similarity index 72%
rename from lib/src/rgb_picker.dart
rename to lib/src/pickers/rgb_picker.dart
index e482497..2b1e44d 100644
--- a/lib/src/rgb_picker.dart
+++ b/lib/src/pickers/rgb_picker.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
-import 'slider_picker.dart';
+import '../widgets/slider_picker.dart';
+import '../widgets/slider_title.dart';
/// Three sliders for selecting a color based on RGB
class RGBPicker extends StatefulWidget {
@@ -52,44 +53,13 @@ class _RGBPickerState extends State {
color.withBlue(255),
];
- Widget buildTitle(String title, String text) {
- return SizedBox(
- height: 34.0,
- child: Row(
- children: [
- Opacity(
- opacity: 0.5,
- child: Text(
- title,
- style: Theme.of(context).textTheme.headline6?.copyWith(
- fontSize: 18,
- ),
- ),
- ),
- Expanded(
- child: Align(
- alignment: Alignment.centerRight,
- child: Text(
- text,
- style: Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontSize: 18),
- ),
- ),
- )
- ],
- ),
- );
- }
-
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Red
- buildTitle(
+ SliderTitle(
'R',
color.red.toInt().toString(),
),
@@ -101,7 +71,7 @@ class _RGBPickerState extends State {
),
// Green
- buildTitle(
+ SliderTitle(
'G',
color.green.toInt().toString(),
),
@@ -113,7 +83,7 @@ class _RGBPickerState extends State {
),
// Blue
- buildTitle(
+ SliderTitle(
'B',
color.blue.toInt().toString(),
),
diff --git a/lib/src/swatches_picker.dart b/lib/src/pickers/swatches_picker.dart
similarity index 100%
rename from lib/src/swatches_picker.dart
rename to lib/src/pickers/swatches_picker.dart
diff --git a/lib/src/wheel_picker.dart b/lib/src/pickers/wheel_picker.dart
similarity index 100%
rename from lib/src/wheel_picker.dart
rename to lib/src/pickers/wheel_picker.dart
diff --git a/lib/src/alpha_picker.dart b/lib/src/widgets/alpha_picker.dart
similarity index 71%
rename from lib/src/alpha_picker.dart
rename to lib/src/widgets/alpha_picker.dart
index 4058775..4f471b6 100644
--- a/lib/src/alpha_picker.dart
+++ b/lib/src/widgets/alpha_picker.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'slider_picker.dart';
+import 'slider_title.dart';
/// Slider for selecting the alpha value (0-255)
class AlphaPicker extends StatefulWidget {
@@ -22,39 +23,13 @@ class _AlphaPickerState extends State {
widget.onChanged(ratio.toInt());
}
- Widget buildTitle(String title, String text) {
- return SizedBox(
- height: 34.0,
- child: Row(
- children: [
- Opacity(
- opacity: 0.5,
- child: Text(title, style: Theme.of(context).textTheme.headline6),
- ),
- Expanded(
- child: Align(
- alignment: Alignment.centerRight,
- child: Text(
- text,
- style: Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontSize: 18),
- ),
- ),
- )
- ],
- ),
- );
- }
-
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Alpha
- buildTitle('A', widget.alpha.toString()),
+ SliderTitle('A', widget.alpha.toString()),
SliderPicker(
value: widget.alpha.toDouble(),
max: 255.0,
diff --git a/lib/src/hex_picker.dart b/lib/src/widgets/hex_picker.dart
similarity index 100%
rename from lib/src/hex_picker.dart
rename to lib/src/widgets/hex_picker.dart
diff --git a/lib/src/palette_picker.dart b/lib/src/widgets/palette_picker.dart
similarity index 100%
rename from lib/src/palette_picker.dart
rename to lib/src/widgets/palette_picker.dart
diff --git a/lib/src/slider_picker.dart b/lib/src/widgets/slider_picker.dart
similarity index 100%
rename from lib/src/slider_picker.dart
rename to lib/src/widgets/slider_picker.dart
diff --git a/lib/src/widgets/slider_title.dart b/lib/src/widgets/slider_title.dart
new file mode 100644
index 0000000..3afb1fc
--- /dev/null
+++ b/lib/src/widgets/slider_title.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+
+class SliderTitle extends StatelessWidget {
+ const SliderTitle(
+ this.title,
+ this.text, {
+ Key? key,
+ }) : super(key: key);
+
+ final String title;
+ final String text;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ alignment: Alignment.bottomCenter,
+ margin: const EdgeInsets.fromLTRB(10, 8, 10, 0),
+ child: Row(
+ children: [
+ Opacity(
+ opacity: 0.7,
+ child: Text(
+ title,
+ style: Theme.of(context).textTheme.headline6?.copyWith(
+ fontSize: 18,
+ ),
+ ),
+ ),
+ const Spacer(),
+ Text(
+ text,
+ style: Theme.of(context).textTheme.headline5?.copyWith(
+ fontSize: 18,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 7f8b3a8..c509cd9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_hsvcolor_picker
description: A HSV color picker inspired by chrome devtools and a material color picker for your flutter app.
-version: 1.1.0
+version: 1.2.0
homepage: https://github.com/fluttercandies/flutter_hsvcolor_picker
dependencies:
@@ -12,6 +12,6 @@ environment:
flutter: '>=2.0.0'
dev_dependencies:
- flutter_lints: ^1.0.3
+ flutter_lints: ^1.0.4
flutter_test:
sdk: flutter