Cleaned up the repo
Singed-off-by: Andreas Fahrecker <AndreasFahrecker@gmail.com>
This commit is contained in:
14
lib/redux/actions/app_settings_actions.dart
Normal file
14
lib/redux/actions/app_settings_actions.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/redux_actions.dart';
|
||||
|
||||
class LoadAppSettingsAction {}
|
||||
|
||||
class AppSettingsLoadedActions extends AppSettingsAction with BoolAction {
|
||||
AppSettingsLoadedActions(AppSettings appSettings) : super(appSettings);
|
||||
}
|
||||
|
||||
class UpdateAppSettingsActions extends AppSettingsAction {
|
||||
UpdateAppSettingsActions(AppSettings appSettings) : super(appSettings);
|
||||
}
|
||||
|
||||
class AppSettingsNotLoadedAction extends BoolAction {}
|
16
lib/redux/actions/redux_actions.dart
Normal file
16
lib/redux/actions/redux_actions.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
|
||||
abstract class BoolAction {}
|
||||
|
||||
abstract class AppSettingsAction {
|
||||
final AppSettings appSettings;
|
||||
|
||||
AppSettingsAction(this.appSettings);
|
||||
}
|
||||
|
||||
abstract class TimeProgressAction {
|
||||
final TimeProgress timeProgress;
|
||||
|
||||
TimeProgressAction(this.timeProgress);
|
||||
}
|
29
lib/redux/actions/time_progress_actions.dart
Normal file
29
lib/redux/actions/time_progress_actions.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/redux_actions.dart';
|
||||
|
||||
class LoadTimeProgressListAction {}
|
||||
|
||||
class TimeProgressListLoadedAction extends BoolAction {
|
||||
final List<TimeProgress> timeProgressList;
|
||||
|
||||
TimeProgressListLoadedAction(this.timeProgressList);
|
||||
}
|
||||
|
||||
class TimeProgressListNotLoadedAction extends BoolAction {}
|
||||
|
||||
class AddTimeProgressAction extends TimeProgressAction {
|
||||
AddTimeProgressAction(TimeProgress timeProgress) : super(timeProgress);
|
||||
}
|
||||
|
||||
class UpdateTimeProgressAction extends TimeProgressAction {
|
||||
final String id;
|
||||
|
||||
UpdateTimeProgressAction(this.id, TimeProgress timeProgress)
|
||||
: super(timeProgress);
|
||||
}
|
||||
|
||||
class DeleteTimeProgressAction {
|
||||
final String id;
|
||||
|
||||
DeleteTimeProgressAction(this.id);
|
||||
}
|
14
lib/redux/reducers/app_state_reducer.dart
Normal file
14
lib/redux/reducers/app_state_reducer.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/redux/reducers/bool_reducers.dart';
|
||||
import 'package:time_progress_tracker/redux/reducers/model_reducers.dart';
|
||||
|
||||
AppState appStateReducer(AppState state, dynamic action) {
|
||||
return AppState(
|
||||
hasSettingsLoaded:
|
||||
hasSettingsLoadedReducer(state.hasSettingsLoaded, action),
|
||||
hasProgressesLoaded:
|
||||
hasProgressesLoadedReducer(state.hasProgressesLoaded, action),
|
||||
timeProgressList: timeProgressListReducer(state.timeProgressList, action),
|
||||
appSettings: appSettingsReducers(state.appSettings, action),
|
||||
);
|
||||
}
|
22
lib/redux/reducers/bool_reducers.dart
Normal file
22
lib/redux/reducers/bool_reducers.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/app_settings_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/redux_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/time_progress_actions.dart';
|
||||
|
||||
final hasProgressesLoadedReducer = combineReducers<bool>([
|
||||
TypedReducer<bool, TimeProgressListLoadedAction>(_setTrue),
|
||||
TypedReducer<bool, TimeProgressListNotLoadedAction>(_setFalse)
|
||||
]);
|
||||
|
||||
final hasSettingsLoadedReducer = combineReducers<bool>([
|
||||
TypedReducer<bool, AppSettingsLoadedActions>(_setTrue),
|
||||
TypedReducer<bool, AppSettingsNotLoadedAction>(_setFalse)
|
||||
]);
|
||||
|
||||
bool _setTrue(bool value, BoolAction action) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _setFalse(bool value, BoolAction action) {
|
||||
return false;
|
||||
}
|
62
lib/redux/reducers/model_reducers.dart
Normal file
62
lib/redux/reducers/model_reducers.dart
Normal file
@ -0,0 +1,62 @@
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/app_settings_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/redux_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/time_progress_actions.dart';
|
||||
|
||||
final timeProgressListReducer = combineReducers<List<TimeProgress>>([
|
||||
TypedReducer<List<TimeProgress>, TimeProgressListLoadedAction>(
|
||||
_setLoadedTimeProgressList),
|
||||
TypedReducer<List<TimeProgress>, TimeProgressListNotLoadedAction>(
|
||||
_setEmptyTimeProgressList),
|
||||
TypedReducer<List<TimeProgress>, AddTimeProgressAction>(_addTimeProgress),
|
||||
TypedReducer<List<TimeProgress>, UpdateTimeProgressAction>(
|
||||
_updateTimeProgress),
|
||||
TypedReducer<List<TimeProgress>, DeleteTimeProgressAction>(
|
||||
_deleteTimeProgress),
|
||||
]);
|
||||
|
||||
List<TimeProgress> _setEmptyTimeProgressList(
|
||||
List<TimeProgress> timeProgressList,
|
||||
TimeProgressListNotLoadedAction action) {
|
||||
return [];
|
||||
}
|
||||
|
||||
List<TimeProgress> _setLoadedTimeProgressList(
|
||||
List<TimeProgress> timeProgressList, TimeProgressListLoadedAction action) {
|
||||
return action.timeProgressList;
|
||||
}
|
||||
|
||||
List<TimeProgress> _addTimeProgress(
|
||||
List<TimeProgress> timeProgressList, AddTimeProgressAction action) =>
|
||||
List.from(timeProgressList)
|
||||
..add(action.timeProgress)
|
||||
..toList(growable: false);
|
||||
|
||||
List<TimeProgress> _updateTimeProgress(
|
||||
List<TimeProgress> timeProgressList, UpdateTimeProgressAction action) =>
|
||||
timeProgressList
|
||||
.map((timeProgress) =>
|
||||
timeProgress.id == action.id ? action.timeProgress : timeProgress)
|
||||
.toList(growable: false);
|
||||
|
||||
List<TimeProgress> _deleteTimeProgress(
|
||||
List<TimeProgress> timeProgressList, DeleteTimeProgressAction action) =>
|
||||
timeProgressList
|
||||
.where((timeProgress) => timeProgress.id != action.id)
|
||||
.toList(growable: false);
|
||||
|
||||
final appSettingsReducers = combineReducers<AppSettings>([
|
||||
TypedReducer<AppSettings, AppSettingsLoadedActions>(_updateAppSettings),
|
||||
TypedReducer<AppSettings, UpdateAppSettingsActions>(_updateAppSettings),
|
||||
TypedReducer<AppSettings, AppSettingsNotLoadedAction>(_setDefaultSettings)
|
||||
]);
|
||||
|
||||
AppSettings _setDefaultSettings(
|
||||
AppSettings appSettings, AppSettingsNotLoadedAction action) =>
|
||||
AppSettings.defaults();
|
||||
|
||||
AppSettings _updateAppSettings(
|
||||
AppSettings appSettings, AppSettingsAction action) =>
|
||||
action.appSettings;
|
58
lib/redux/redux_selectors.dart
Normal file
58
lib/redux/redux_selectors.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
|
||||
List<TimeProgress> timeProgressListSelector(AppState state) =>
|
||||
state.timeProgressList;
|
||||
|
||||
List<TimeProgress> activeTimeProgressesSelector(AppState state) {
|
||||
return state.timeProgressList
|
||||
.where((timeProgress) =>
|
||||
timeProgress.hasStarted() && !timeProgress.hasEnded())
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<TimeProgress> inactiveTimeProgressesSelector(AppState state) {
|
||||
return state.timeProgressList
|
||||
.where((timeProgress) =>
|
||||
!timeProgress.hasStarted() || timeProgress.hasEnded())
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Deprecated("use active TimeProgresses Selector instead.")
|
||||
List<TimeProgress> currentTimeProgressSelector(AppState state) {
|
||||
int currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||
return state.timeProgressList
|
||||
.where((tp) =>
|
||||
currentTime >= tp.startTime.millisecondsSinceEpoch &&
|
||||
tp.endTime.millisecondsSinceEpoch >= currentTime)
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<TimeProgress> futureTimeProgressesSelector(AppState state) =>
|
||||
state.timeProgressList
|
||||
.where((timeProgress) =>
|
||||
DateTime.now().millisecondsSinceEpoch <
|
||||
timeProgress.startTime.millisecondsSinceEpoch)
|
||||
.toList();
|
||||
|
||||
List<TimeProgress> pastTimeProgressesSelector(AppState state) =>
|
||||
state.timeProgressList
|
||||
.where((tp) =>
|
||||
tp.endTime.millisecondsSinceEpoch <
|
||||
DateTime.now().millisecondsSinceEpoch)
|
||||
.toList();
|
||||
|
||||
TimeProgress timeProgressByIdSelector(AppState state, String id) {
|
||||
if (state.timeProgressList.length < 1) return null;
|
||||
return state.timeProgressList
|
||||
.firstWhere((timeProgress) => timeProgress.id == id, orElse: () => null);
|
||||
}
|
||||
|
||||
AppSettings appSettingsSelector(AppState state) {
|
||||
return state.appSettings;
|
||||
}
|
||||
|
||||
Color doneColorSelector(AppState state) => state.appSettings.doneColor;
|
61
lib/redux/store_connectors/settings_store_connector.dart
Normal file
61
lib/redux/store_connectors/settings_store_connector.dart
Normal file
@ -0,0 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/app_settings_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/utils/helper_functions.dart';
|
||||
|
||||
class SettingsStoreConnector extends StatelessWidget {
|
||||
final Widget Function(BuildContext, SettingsViewModel) loadedBuilder;
|
||||
|
||||
SettingsStoreConnector({
|
||||
@required this.loadedBuilder,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, SettingsViewModel>(
|
||||
onInit: loadSettingsIfUnloaded,
|
||||
converter: (store) => SettingsViewModel._create(store),
|
||||
builder: (context, SettingsViewModel vm) {
|
||||
if (!vm.hasSettingsLoaded)
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return loadedBuilder(context, vm);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsViewModel {
|
||||
final AppSettings appSettings;
|
||||
final bool hasSettingsLoaded;
|
||||
|
||||
final void Function(Color) updateDoneColor, updateLeftColor;
|
||||
final void Function(Duration) updateDuration;
|
||||
|
||||
SettingsViewModel(
|
||||
this.appSettings,
|
||||
this.hasSettingsLoaded,
|
||||
this.updateDoneColor,
|
||||
this.updateLeftColor,
|
||||
this.updateDuration,
|
||||
);
|
||||
|
||||
factory SettingsViewModel._create(Store<AppState> store) {
|
||||
AppSettings _appSettings = store.state.appSettings;
|
||||
|
||||
void _updateDoneColor(Color dC) => store.dispatch(
|
||||
UpdateAppSettingsActions(_appSettings.copyWith(doneColor: dC)));
|
||||
void _updateLeftColor(Color lC) => store.dispatch(
|
||||
UpdateAppSettingsActions(_appSettings.copyWith(leftColor: lC)));
|
||||
|
||||
void _updateDuration(Duration d) => store
|
||||
.dispatch(UpdateAppSettingsActions(_appSettings.copyWith(duration: d)));
|
||||
|
||||
return SettingsViewModel(_appSettings, store.state.hasSettingsLoaded,
|
||||
_updateDoneColor, _updateLeftColor, _updateDuration);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
import 'package:time_progress_tracker/utils/helper_functions.dart';
|
||||
|
||||
class TimeProgressListStoreConnector extends StatelessWidget {
|
||||
final Widget Function(BuildContext, TimeProgressListViewModel) loadedBuilder;
|
||||
|
||||
TimeProgressListStoreConnector({
|
||||
@required this.loadedBuilder,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, TimeProgressListViewModel>(
|
||||
onInit: loadTimeProgressListIfUnloaded,
|
||||
converter: (store) => TimeProgressListViewModel._create(store),
|
||||
builder: (context, TimeProgressListViewModel vm) {
|
||||
if (!vm.hasTpListLoaded)
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
return loadedBuilder(context, vm);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TimeProgressListViewModel {
|
||||
final List<TimeProgress> tpList;
|
||||
final bool hasTpListLoaded;
|
||||
|
||||
TimeProgressListViewModel(this.tpList, this.hasTpListLoaded);
|
||||
|
||||
factory TimeProgressListViewModel._create(Store<AppState> store) =>
|
||||
TimeProgressListViewModel(
|
||||
store.state.timeProgressList, store.state.hasProgressesLoaded);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/time_progress_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
|
||||
import '../../utils/helper_functions.dart';
|
||||
|
||||
class TimeProgressStoreConnector extends StatelessWidget {
|
||||
final String timeProgressId;
|
||||
final Widget Function(BuildContext, TimeProgressViewModel) loadedBuilder;
|
||||
|
||||
TimeProgressStoreConnector({
|
||||
@required this.timeProgressId,
|
||||
@required this.loadedBuilder,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StoreConnector<AppState, TimeProgressViewModel>(
|
||||
onInit: loadTimeProgressListIfUnloaded,
|
||||
converter: (store) =>
|
||||
TimeProgressViewModel._create(store, timeProgressId),
|
||||
builder: (context, TimeProgressViewModel vm) {
|
||||
if (!vm.hasTpListLoaded)
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
if (vm.tp == null)
|
||||
return Center(
|
||||
child: Text("Error Invalid Time Progress"),
|
||||
);
|
||||
return loadedBuilder(context, vm);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TimeProgressViewModel {
|
||||
final TimeProgress tp;
|
||||
final bool hasTpListLoaded;
|
||||
|
||||
final void Function(TimeProgress) updateTimeProgress;
|
||||
final void Function() deleteTimeProgress;
|
||||
|
||||
TimeProgressViewModel(
|
||||
this.tp,
|
||||
this.hasTpListLoaded,
|
||||
this.updateTimeProgress,
|
||||
this.deleteTimeProgress,
|
||||
);
|
||||
|
||||
factory TimeProgressViewModel._create(Store<AppState> store, String id) {
|
||||
void _updateTimeProgress(TimeProgress tp) =>
|
||||
store.dispatch(UpdateTimeProgressAction(id, tp));
|
||||
void _deleteTimeProgress() => store.dispatch(DeleteTimeProgressAction(id));
|
||||
|
||||
return TimeProgressViewModel(
|
||||
selectProgressById(store.state.timeProgressList, id),
|
||||
store.state.hasProgressesLoaded,
|
||||
_updateTimeProgress,
|
||||
_deleteTimeProgress,
|
||||
);
|
||||
}
|
||||
}
|
70
lib/redux/store_middleware.dart
Normal file
70
lib/redux/store_middleware.dart
Normal file
@ -0,0 +1,70 @@
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:time_progress_tracker/models/app_settings.dart';
|
||||
import 'package:time_progress_tracker/models/time_progress.dart';
|
||||
import 'package:time_progress_tracker/persistence/app_settings.dart';
|
||||
import 'package:time_progress_tracker/persistence/time_progress.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/app_settings_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/actions/time_progress_actions.dart';
|
||||
import 'package:time_progress_tracker/redux/app_state.dart';
|
||||
import 'package:time_progress_tracker/redux/redux_selectors.dart';
|
||||
|
||||
List<Middleware<AppState>> createStoreMiddleware(
|
||||
TimeProgressRepository progressRepo, AppSettingsRepository settingsRepo) {
|
||||
final saveTimeProgressList = _createSaveTimeProgressList(progressRepo);
|
||||
final loadTimeProgressList = _createLoadTimeProgressList(progressRepo);
|
||||
|
||||
final saveSettings = _createSaveAppSettings(settingsRepo);
|
||||
final loadSettings = _createLoadAppSettings(settingsRepo);
|
||||
|
||||
return [
|
||||
TypedMiddleware<AppState, LoadTimeProgressListAction>(loadTimeProgressList),
|
||||
TypedMiddleware<AppState, AddTimeProgressAction>(saveTimeProgressList),
|
||||
TypedMiddleware<AppState, UpdateTimeProgressAction>(saveTimeProgressList),
|
||||
TypedMiddleware<AppState, DeleteTimeProgressAction>(saveTimeProgressList),
|
||||
TypedMiddleware<AppState, LoadAppSettingsAction>(loadSettings),
|
||||
TypedMiddleware<AppState, UpdateAppSettingsActions>(saveSettings)
|
||||
];
|
||||
}
|
||||
|
||||
Middleware<AppState> _createSaveTimeProgressList(
|
||||
TimeProgressRepository repository) {
|
||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
next(action);
|
||||
|
||||
repository.save(
|
||||
timeProgressListSelector(store.state)
|
||||
.map<TimeProgressEntity>((timeProgress) => timeProgress.toEntity())
|
||||
.toList(growable: false),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
Middleware<AppState> _createLoadTimeProgressList(
|
||||
TimeProgressRepository repository) {
|
||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
repository.load().then((timeProgresses) {
|
||||
List<TimeProgress> timeProgressList =
|
||||
timeProgresses.map<TimeProgress>(TimeProgress.fromEntity).toList();
|
||||
if (timeProgressList == null) {
|
||||
timeProgressList = [];
|
||||
}
|
||||
store.dispatch(TimeProgressListLoadedAction(
|
||||
timeProgressList,
|
||||
));
|
||||
}).catchError((_) => store.dispatch(TimeProgressListNotLoadedAction()));
|
||||
};
|
||||
}
|
||||
|
||||
Middleware<AppState> _createSaveAppSettings(AppSettingsRepository repo) =>
|
||||
(Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
next(action);
|
||||
repo.save(store.state.appSettings.toEntity());
|
||||
};
|
||||
|
||||
Middleware<AppState> _createLoadAppSettings(AppSettingsRepository repo) =>
|
||||
(Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
repo.load().then((appSettings) {
|
||||
store.dispatch(
|
||||
AppSettingsLoadedActions(AppSettings.fromEntity(appSettings)));
|
||||
});
|
||||
};
|
Reference in New Issue
Block a user