Feature/default duration setting (#7)
* Implemented Basic Duration Settings into AppSettings Model * Implemented Basic Duration Settings into AppSettings Model * Created Duration Settings Widget and Started using ViewModel in HomeSettingsTab * Updated Version Number
This commit is contained in:
parent
b520d56d1a
commit
90f2998088
@ -13,19 +13,26 @@ class AppSettings {
|
|||||||
this.duration,
|
this.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory AppSettings.defaults() =>
|
factory AppSettings.defaults() => AppSettings(
|
||||||
AppSettings(doneColor: Colors.green, leftColor: Colors.red);
|
doneColor: Colors.green,
|
||||||
|
leftColor: Colors.red,
|
||||||
|
duration: Duration(days: 365),
|
||||||
|
);
|
||||||
|
|
||||||
AppSettings copyWith({
|
AppSettings copyWith({
|
||||||
Color doneColor,
|
Color doneColor,
|
||||||
Color leftColor,
|
Color leftColor,
|
||||||
|
Duration duration,
|
||||||
}) =>
|
}) =>
|
||||||
AppSettings(
|
AppSettings(
|
||||||
doneColor: doneColor ?? this.doneColor,
|
doneColor: doneColor ?? this.doneColor,
|
||||||
leftColor: leftColor ?? this.leftColor);
|
leftColor: leftColor ?? this.leftColor,
|
||||||
|
duration: duration ?? this.duration,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => doneColor.hashCode ^ leftColor.hashCode;
|
int get hashCode =>
|
||||||
|
doneColor.hashCode ^ leftColor.hashCode ^ duration.hashCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
@ -33,12 +40,15 @@ class AppSettings {
|
|||||||
other is AppSettings &&
|
other is AppSettings &&
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
doneColor == other.doneColor &&
|
doneColor == other.doneColor &&
|
||||||
leftColor == other.leftColor;
|
leftColor == other.leftColor &&
|
||||||
|
duration == other.duration;
|
||||||
|
|
||||||
AppSettingsEntity toEntity() =>
|
AppSettingsEntity toEntity() =>
|
||||||
AppSettingsEntity(doneColor.value, leftColor.value);
|
AppSettingsEntity(doneColor.value, leftColor.value, duration.inDays);
|
||||||
|
|
||||||
static AppSettings fromEntity(AppSettingsEntity entity) => AppSettings(
|
static AppSettings fromEntity(AppSettingsEntity entity) => AppSettings(
|
||||||
doneColor: Color(entity.doneColorValue),
|
doneColor: Color(entity.doneColorValue),
|
||||||
leftColor: Color(entity.leftColorValue));
|
leftColor: Color(entity.leftColorValue),
|
||||||
|
duration: Duration(days: entity.durationDays),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ class TimeProgress {
|
|||||||
"Initial Name", DateTime(thisYear - 1), DateTime(thisYear + 1));
|
"Initial Name", DateTime(thisYear - 1), DateTime(thisYear + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory TimeProgress.defaultFromDuration(Duration duration) =>
|
||||||
|
TimeProgress("", DateTime.now(), DateTime.now().add(duration));
|
||||||
|
|
||||||
TimeProgress copyWith(
|
TimeProgress copyWith(
|
||||||
{String id, String name, DateTime startTime, DateTime endTime}) =>
|
{String id, String name, DateTime startTime, DateTime endTime}) =>
|
||||||
TimeProgress(
|
TimeProgress(
|
||||||
|
@ -23,10 +23,13 @@ class AppSettingsRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AppSettingsEntity {
|
class AppSettingsEntity {
|
||||||
static const String _doneKey = "doneColorValue", _leftKey = "leftColorValue";
|
static const String _doneKey = "doneColorValue",
|
||||||
final int doneColorValue, leftColorValue;
|
_leftKey = "leftColorValue",
|
||||||
|
_durationDaysKey = "durationDays";
|
||||||
|
final int doneColorValue, leftColorValue, durationDays;
|
||||||
|
|
||||||
AppSettingsEntity(this.doneColorValue, this.leftColorValue);
|
AppSettingsEntity(
|
||||||
|
this.doneColorValue, this.leftColorValue, this.durationDays);
|
||||||
|
|
||||||
factory AppSettingsEntity.defaults() => AppSettings.defaults().toEntity();
|
factory AppSettingsEntity.defaults() => AppSettings.defaults().toEntity();
|
||||||
|
|
||||||
@ -41,9 +44,16 @@ class AppSettingsEntity {
|
|||||||
doneColorValue == other.doneColorValue &&
|
doneColorValue == other.doneColorValue &&
|
||||||
leftColorValue == other.leftColorValue;
|
leftColorValue == other.leftColorValue;
|
||||||
|
|
||||||
Map<String, Object> toJson() =>
|
Map<String, Object> toJson() => {
|
||||||
{_doneKey: doneColorValue, _leftKey: leftColorValue};
|
_doneKey: doneColorValue,
|
||||||
|
_leftKey: leftColorValue,
|
||||||
|
_durationDaysKey: durationDays,
|
||||||
|
};
|
||||||
|
|
||||||
static AppSettingsEntity fromJson(Map<String, Object> json) =>
|
static AppSettingsEntity fromJson(Map<String, Object> json) =>
|
||||||
AppSettingsEntity(json[_doneKey], json[_leftKey]);
|
AppSettingsEntity(
|
||||||
|
json[_doneKey],
|
||||||
|
json[_leftKey],
|
||||||
|
json[_durationDaysKey],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
import 'package:time_progress_tracker/actions/actions.dart';
|
import 'package:time_progress_tracker/actions/actions.dart';
|
||||||
|
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||||
import 'package:time_progress_tracker/models/app_state.dart';
|
import 'package:time_progress_tracker/models/app_state.dart';
|
||||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||||
|
import 'package:time_progress_tracker/selectors/time_progress_selectors.dart';
|
||||||
import 'package:time_progress_tracker/widgets/progress_editor_widget.dart';
|
import 'package:time_progress_tracker/widgets/progress_editor_widget.dart';
|
||||||
|
|
||||||
class ProgressCreationScreen extends StatefulWidget {
|
class ProgressCreationScreen extends StatefulWidget {
|
||||||
@ -17,10 +20,16 @@ class ProgressCreationScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProgressCreationScreenState extends State<ProgressCreationScreen> {
|
class _ProgressCreationScreenState extends State<ProgressCreationScreen> {
|
||||||
TimeProgress timeProgressToCreate =
|
TimeProgress timeProgressToCreate;
|
||||||
TimeProgress("", DateTime.now(), DateTime(DateTime.now().year + 1));
|
|
||||||
bool _isProgressValid = false;
|
bool _isProgressValid = false;
|
||||||
|
|
||||||
|
void initTimeProgress(TimeProgress timeProgress) {
|
||||||
|
if (timeProgressToCreate == null)
|
||||||
|
setState(() {
|
||||||
|
timeProgressToCreate = timeProgress;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void onTimeProgressChanged(
|
void onTimeProgressChanged(
|
||||||
TimeProgress newTimeProgress, bool isNewProgressValid) {
|
TimeProgress newTimeProgress, bool isNewProgressValid) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -37,27 +46,36 @@ class _ProgressCreationScreenState extends State<ProgressCreationScreen> {
|
|||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
child: ProgressEditorWidget(
|
child: StoreConnector<AppState, _ViewModel>(
|
||||||
|
onInit: loadSettingsIfUnloaded,
|
||||||
|
converter: (store) => _ViewModel.create(store),
|
||||||
|
builder: (context, _ViewModel viewModel) {
|
||||||
|
initTimeProgress(viewModel.defaultDurationProgress);
|
||||||
|
return ProgressEditorWidget(
|
||||||
timeProgress: timeProgressToCreate,
|
timeProgress: timeProgressToCreate,
|
||||||
onTimeProgressChanged: onTimeProgressChanged,
|
onTimeProgressChanged: onTimeProgressChanged,
|
||||||
),
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||||
floatingActionButton: Row(
|
floatingActionButton: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FloatingActionButton(
|
child: StoreConnector<AppState, _ViewModel>(
|
||||||
|
onInit: loadSettingsIfUnloaded,
|
||||||
|
converter: (store) => _ViewModel.create(store),
|
||||||
|
builder: (context, _ViewModel vm) => FloatingActionButton(
|
||||||
heroTag: "createTimeProgressBTN",
|
heroTag: "createTimeProgressBTN",
|
||||||
child: Icon(Icons.save),
|
child: Icon(Icons.save),
|
||||||
onPressed: _isProgressValid
|
onPressed: _isProgressValid
|
||||||
? () {
|
? () {
|
||||||
StoreProvider.of<AppState>(context).dispatch(
|
vm.onAddTimeProgress(timeProgressToCreate);
|
||||||
AddTimeProgressAction(timeProgressToCreate));
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
heroTag: "cancelTimeProgressCreationBTN",
|
heroTag: "cancelTimeProgressCreationBTN",
|
||||||
@ -72,3 +90,27 @@ class _ProgressCreationScreenState extends State<ProgressCreationScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ViewModel {
|
||||||
|
final TimeProgress defaultDurationProgress;
|
||||||
|
final void Function(TimeProgress) onAddTimeProgress;
|
||||||
|
|
||||||
|
_ViewModel({
|
||||||
|
@required this.defaultDurationProgress,
|
||||||
|
@required this.onAddTimeProgress,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory _ViewModel.create(Store<AppState> store) {
|
||||||
|
AppSettings settings = appSettingsSelector(store.state);
|
||||||
|
|
||||||
|
_onAddTimeProgress(TimeProgress tp) {
|
||||||
|
if (TimeProgress.isValid(tp)) store.dispatch(AddTimeProgressAction(tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ViewModel(
|
||||||
|
defaultDurationProgress:
|
||||||
|
TimeProgress.defaultFromDuration(settings.duration),
|
||||||
|
onAddTimeProgress: _onAddTimeProgress,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,24 +7,15 @@ import 'package:time_progress_tracker/models/app_settings.dart';
|
|||||||
import 'package:time_progress_tracker/models/app_state.dart';
|
import 'package:time_progress_tracker/models/app_state.dart';
|
||||||
import 'package:time_progress_tracker/selectors/time_progress_selectors.dart';
|
import 'package:time_progress_tracker/selectors/time_progress_selectors.dart';
|
||||||
import 'package:time_progress_tracker/widgets/home/tabs/settings/color_settings_widget.dart';
|
import 'package:time_progress_tracker/widgets/home/tabs/settings/color_settings_widget.dart';
|
||||||
|
import 'package:time_progress_tracker/widgets/home/tabs/settings/duration_settings_widget.dart';
|
||||||
|
|
||||||
class HomeSettingsTab extends StatelessWidget {
|
class HomeSettingsTab extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StoreConnector<AppState, AppSettings>(
|
return StoreConnector<AppState, _ViewModel>(
|
||||||
onInit: loadSettingsIfUnloaded,
|
onInit: loadSettingsIfUnloaded,
|
||||||
converter: (store) => appSettingsSelector(store.state),
|
converter: (store) => _ViewModel.create(store),
|
||||||
builder: (context, AppSettings settings) {
|
builder: (context, _ViewModel vm) {
|
||||||
Store<AppState> store = StoreProvider.of<AppState>(context);
|
|
||||||
void updateDoneColor(Color newDoneColor) => store.dispatch(
|
|
||||||
UpdateAppSettingsActions(
|
|
||||||
settings.copyWith(doneColor: newDoneColor)),
|
|
||||||
);
|
|
||||||
void updateLeftColor(Color newLeftColor) => store.dispatch(
|
|
||||||
UpdateAppSettingsActions(
|
|
||||||
settings.copyWith(leftColor: newLeftColor)),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
child: Center(
|
child: Center(
|
||||||
@ -32,10 +23,16 @@ class HomeSettingsTab extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ColorSettingsWidget(
|
child: ColorSettingsWidget(
|
||||||
doneColor: settings.doneColor,
|
doneColor: vm.doneColor,
|
||||||
leftColor: settings.leftColor,
|
leftColor: vm.leftColor,
|
||||||
updateDoneColor: updateDoneColor,
|
updateDoneColor: vm.onDoneColorChanged,
|
||||||
updateLeftColor: updateLeftColor,
|
updateLeftColor: vm.onLeftColorChanged,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: DurationSettingsWidget(
|
||||||
|
duration: vm.duration,
|
||||||
|
updateDuration: vm.onDurationChanged,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
@ -60,3 +57,39 @@ class HomeSettingsTab extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ViewModel {
|
||||||
|
final Color doneColor, leftColor;
|
||||||
|
final void Function(Color) onDoneColorChanged, onLeftColorChanged;
|
||||||
|
final Duration duration;
|
||||||
|
final void Function(Duration) onDurationChanged;
|
||||||
|
|
||||||
|
_ViewModel({
|
||||||
|
@required this.doneColor,
|
||||||
|
@required this.leftColor,
|
||||||
|
@required this.onDoneColorChanged,
|
||||||
|
@required this.onLeftColorChanged,
|
||||||
|
@required this.duration,
|
||||||
|
@required this.onDurationChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory _ViewModel.create(Store<AppState> store) {
|
||||||
|
AppSettings settings = appSettingsSelector(store.state);
|
||||||
|
|
||||||
|
void _onDoneColorChanged(Color c) => store
|
||||||
|
.dispatch(UpdateAppSettingsActions(settings.copyWith(doneColor: c)));
|
||||||
|
void _onLeftColorChanged(Color c) => store
|
||||||
|
.dispatch(UpdateAppSettingsActions(settings.copyWith(leftColor: c)));
|
||||||
|
|
||||||
|
void _onDurationChanged(Duration d) => store
|
||||||
|
.dispatch(UpdateAppSettingsActions(settings.copyWith(duration: d)));
|
||||||
|
|
||||||
|
return _ViewModel(
|
||||||
|
doneColor: settings.doneColor,
|
||||||
|
leftColor: settings.leftColor,
|
||||||
|
onDoneColorChanged: _onDoneColorChanged,
|
||||||
|
onLeftColorChanged: _onLeftColorChanged,
|
||||||
|
duration: settings.duration,
|
||||||
|
onDurationChanged: _onDurationChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class DirectSelectItem extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final bool isForList;
|
|
||||||
|
|
||||||
DirectSelectItem({this.title, this.isForList});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return SizedBox(
|
|
||||||
height: 60,
|
|
||||||
child: isForList
|
|
||||||
? Padding(
|
|
||||||
child: _buildItem(context),
|
|
||||||
padding: EdgeInsets.all(10),
|
|
||||||
)
|
|
||||||
: Card(
|
|
||||||
margin: EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
_buildItem(context),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: Icon(Icons.arrow_drop_down),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Container _buildItem(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(title),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
61
lib/widgets/home/tabs/settings/duration_settings_widget.dart
Normal file
61
lib/widgets/home/tabs/settings/duration_settings_widget.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_picker/flutter_picker.dart';
|
||||||
|
|
||||||
|
class DurationSettingsWidget extends StatelessWidget {
|
||||||
|
final Duration duration;
|
||||||
|
final void Function(Duration) updateDuration;
|
||||||
|
|
||||||
|
DurationSettingsWidget({
|
||||||
|
@required this.duration,
|
||||||
|
@required this.updateDuration,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
int years = duration.inDays ~/ 365;
|
||||||
|
int months = (duration.inDays - (365 * years)) ~/ 30;
|
||||||
|
int days = duration.inDays - (365 * years) - (30 * months);
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Picker(
|
||||||
|
adapter: NumberPickerAdapter(
|
||||||
|
data: [
|
||||||
|
const NumberPickerColumn(
|
||||||
|
begin: 0,
|
||||||
|
end: 999,
|
||||||
|
suffix: Text(" Y"),
|
||||||
|
),
|
||||||
|
const NumberPickerColumn(
|
||||||
|
begin: 0,
|
||||||
|
end: 11,
|
||||||
|
suffix: Text(" M"),
|
||||||
|
),
|
||||||
|
const NumberPickerColumn(
|
||||||
|
begin: 0,
|
||||||
|
end: 30,
|
||||||
|
suffix: Text(" D"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
hideHeader: true,
|
||||||
|
confirmText: "OK",
|
||||||
|
title: const Text("Select Duration"),
|
||||||
|
selectedTextStyle: TextStyle(color: Colors.blue),
|
||||||
|
onConfirm: (Picker picker, List<int> value) {
|
||||||
|
int years = value[0], months = value[1], days = value[2];
|
||||||
|
days = (years * 365) + (months * 30) + days;
|
||||||
|
Duration newDuration = Duration(days: days);
|
||||||
|
updateDuration(newDuration);
|
||||||
|
},
|
||||||
|
).showDialog(context);
|
||||||
|
},
|
||||||
|
child: Text("Default Duration: $years Y - $months M - $days D"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
16
pubspec.lock
16
pubspec.lock
@ -78,13 +78,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.3"
|
||||||
direct_select:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: direct_select
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -125,6 +118,15 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.1"
|
version: "0.8.1"
|
||||||
|
flutter_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: HEAD
|
||||||
|
resolved-ref: e95d121f54faba889fbf8a850c86dd5cf4aa5c5a
|
||||||
|
url: "git://github.com/yangyxd/flutter_picker.git"
|
||||||
|
source: git
|
||||||
|
version: "1.1.5"
|
||||||
flutter_redux:
|
flutter_redux:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 0.0.17+17
|
version: 0.0.18+18
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
@ -25,7 +25,8 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_colorpicker:
|
flutter_colorpicker:
|
||||||
flutter_redux:
|
flutter_redux:
|
||||||
direct_select:
|
flutter_picker:
|
||||||
|
git: git://github.com/yangyxd/flutter_picker.git
|
||||||
meta:
|
meta:
|
||||||
package_info:
|
package_info:
|
||||||
percent_indicator:
|
percent_indicator:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user