This commit is contained in:
Hillel Coren 2019-11-17 01:04:48 +02:00
parent 75c7d06fe0
commit e3a1c612ed
57 changed files with 217 additions and 238 deletions

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// This version must be updated in tandem with the pubspec version. // This version must be updated in tandem with the pubspec version.
const String kAppVersion = '2.0.0'; const String kAppVersion = '2.0.1';
const String kSiteUrl = 'https://invoiceninja.com'; const String kSiteUrl = 'https://invoiceninja.com';
const String kAppUrl = 'https://admin.invoiceninja.com'; const String kAppUrl = 'https://admin.invoiceninja.com';
//const String kAppUrl = 'https://staging.invoicing.co'; //const String kAppUrl = 'https://staging.invoicing.co';
@ -71,6 +71,8 @@ const int kMinMajorAppVersion = 0;
const int kMinMinorAppVersion = 0; const int kMinMinorAppVersion = 0;
const int kMinPatchAppVersion = 0; const int kMinPatchAppVersion = 0;
const int kMaxNumberOfCompanies = 10;
const int kMaxNumberOfHistory = 50;
const int kMaxRecordsPerApiPage = 5000; const int kMaxRecordsPerApiPage = 5000;
const int kMillisecondsToRefreshData = 1000 * 60 * 15; // 15 minutes const int kMillisecondsToRefreshData = 1000 * 60 * 15; // 15 minutes
const int kMillisecondsToRefreshActivities = 1000 * 60 * 60 * 24; // 1 day const int kMillisecondsToRefreshActivities = 1000 * 60 * 60 * 24; // 1 day

View File

@ -4,7 +4,7 @@ import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
part 'expense_model.g.dart'; part 'expense_model.g.dart';
@ -70,7 +70,7 @@ abstract class ExpenseEntity extends Object
factory ExpenseEntity( factory ExpenseEntity(
{String id, {String id,
CompanyEntity company, CompanyEntity company,
UIState uiState, PrefState prefState,
VendorEntity vendor, VendorEntity vendor,
ClientEntity client}) { ClientEntity client}) {
return _$ExpenseEntity._( return _$ExpenseEntity._(
@ -79,7 +79,7 @@ abstract class ExpenseEntity extends Object
privateNotes: '', privateNotes: '',
publicNotes: '', publicNotes: '',
shouldBeInvoiced: false, shouldBeInvoiced: false,
invoiceDocuments: uiState?.prefState?.addDocumentsToInvoice ?? false, invoiceDocuments: prefState?.addDocumentsToInvoice ?? false,
transactionId: '', transactionId: '',
transactionReference: '', transactionReference: '',
bankId: '', bankId: '',

View File

@ -27,7 +27,6 @@ import 'package:invoiceninja_flutter/redux/quote/quote_middleware.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_middleware.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_middleware.dart';
import 'package:invoiceninja_flutter/redux/task/task_middleware.dart'; import 'package:invoiceninja_flutter/redux/task/task_middleware.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart'; import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_middleware.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_middleware.dart';
import 'package:invoiceninja_flutter/ui/app/app_builder.dart'; import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
import 'package:invoiceninja_flutter/ui/app/main_screen.dart'; import 'package:invoiceninja_flutter/ui/app/main_screen.dart';
@ -156,10 +155,7 @@ Future<AppState> _initialState(bool isTesting) async {
} }
return AppState( return AppState(
uiState: UIState( prefState: prefState,
isTesting: isTesting,
prefState: prefState,
),
); );
} }
@ -216,7 +212,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
@override @override
void didChangeDependencies() { void didChangeDependencies() {
final state = widget.store.state; final state = widget.store.state;
if (state.uiState.requireAuthentication && !_authenticated) { if (state.prefState.requireAuthentication && !_authenticated) {
_authenticate(); _authenticate();
} }
super.didChangeDependencies(); super.didChangeDependencies();
@ -231,7 +227,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
Intl.defaultLocale = localeSelector(state); Intl.defaultLocale = localeSelector(state);
final localization = AppLocalization(Locale(Intl.defaultLocale)); final localization = AppLocalization(Locale(Intl.defaultLocale));
final accentColor = final accentColor =
convertHexStringToColor(state.uiState.accentColor) ?? convertHexStringToColor(state.accentColor) ??
Colors.lightBlueAccent; Colors.lightBlueAccent;
return MaterialApp( return MaterialApp(
supportedLocales: kLanguages supportedLocales: kLanguages
@ -245,7 +241,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
GlobalWidgetsLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
GlobalMaterialLocalizations.delegate GlobalMaterialLocalizations.delegate
], ],
home: state.uiState.requireAuthentication && !_authenticated home: state.prefState.requireAuthentication && !_authenticated
? Material( ? Material(
color: Colors.grey, color: Colors.grey,
child: Column( child: Column(
@ -280,7 +276,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
) )
: InitScreen(), : InitScreen(),
locale: AppLocalization.createLocale(localeSelector(state)), locale: AppLocalization.createLocale(localeSelector(state)),
theme: state.uiState.enableDarkMode theme: state.prefState.enableDarkMode
? ThemeData( ? ThemeData(
brightness: Brightness.dark, brightness: Brightness.dark,
accentColor: accentColor, accentColor: accentColor,

View File

@ -196,11 +196,12 @@ Middleware<AppState> _createLoadState(
companyStates.add(await companyRepositories[i].loadCompanyState(i)); companyStates.add(await companyRepositories[i].loadCompanyState(i));
} }
final AppState appState = AppState().rebuild((b) => b final AppState appState = AppState(prefState: store.state.prefState)
..authState.replace(authState) .rebuild((b) => b
..uiState.replace(uiState) ..authState.replace(authState)
..staticState.replace(staticState) ..uiState.replace(uiState)
..userCompanyStates.replace(companyStates)); ..staticState.replace(staticState)
..userCompanyStates.replace(companyStates));
AppBuilder.of(action.context).rebuild(); AppBuilder.of(action.context).rebuild();
store.dispatch(LoadStateSuccess(appState)); store.dispatch(LoadStateSuccess(appState));
@ -216,7 +217,7 @@ Middleware<AppState> _createLoadState(
uiState.currentRoute.isNotEmpty) { uiState.currentRoute.isNotEmpty) {
final NavigatorState navigator = Navigator.of(action.context); final NavigatorState navigator = Navigator.of(action.context);
final routes = _getRoutes(appState); final routes = _getRoutes(appState);
if (uiState.layout == AppLayout.mobile) { if (appState.prefState.layout == AppLayout.mobile) {
bool isFirst = true; bool isFirst = true;
routes.forEach((route) { routes.forEach((route) {
if (isFirst) { if (isFirst) {
@ -249,7 +250,7 @@ Middleware<AppState> _createLoadState(
final Completer<Null> completer = Completer<Null>(); final Completer<Null> completer = Completer<Null>();
completer.future.then((_) { completer.future.then((_) {
final layout = calculateLayout(action.context); final layout = calculateLayout(action.context);
if (store.state.uiState.layout == AppLayout.tablet && if (store.state.prefState.layout == AppLayout.tablet &&
layout == AppLayout.mobile) { layout == AppLayout.mobile) {
store.dispatch(UserSettingsChanged(layout: layout)); store.dispatch(UserSettingsChanged(layout: layout));
store.dispatch(ViewDashboard(context: action.context)); store.dispatch(ViewDashboard(context: action.context));
@ -356,8 +357,8 @@ Middleware<AppState> _createPersistPrefs() {
return; return;
} }
final string = serializers.serializeWith( final string =
PrefState.serializer, store.state.uiState.prefState); serializers.serializeWith(PrefState.serializer, store.state.prefState);
SharedPreferences.getInstance() SharedPreferences.getInstance()
.then((prefs) => prefs.setString(kSharedPrefs, json.encode(string))); .then((prefs) => prefs.setString(kSharedPrefs, json.encode(string)));

View File

@ -8,6 +8,7 @@ import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
import 'package:invoiceninja_flutter/redux/project/project_actions.dart'; import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:invoiceninja_flutter/redux/task/task_actions.dart'; import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_reducer.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_reducer.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_reducer.dart';
@ -24,8 +25,8 @@ AppState appReducer(AppState state, dynamic action) {
return AppState().rebuild((b) => b return AppState().rebuild((b) => b
..authState ..authState
.replace(state.authState.rebuild((b) => b..isAuthenticated = false)) .replace(state.authState.rebuild((b) => b..isAuthenticated = false))
//..uiState.enableDarkMode = state.uiState.enableDarkMode ..prefState.replace(state.prefState)
..uiState.isTesting = state.uiState.isTesting); ..isTesting = state.isTesting);
} else if (action is LoadStateSuccess) { } else if (action is LoadStateSuccess) {
return action.state.rebuild((b) => b return action.state.rebuild((b) => b
..isLoading = false ..isLoading = false
@ -41,7 +42,9 @@ AppState appReducer(AppState state, dynamic action) {
..staticState.replace(staticReducer(state.staticState, action)) ..staticState.replace(staticReducer(state.staticState, action))
..userCompanyStates[state.uiState.selectedCompanyIndex] = companyReducer( ..userCompanyStates[state.uiState.selectedCompanyIndex] = companyReducer(
state.userCompanyStates[state.uiState.selectedCompanyIndex], action) state.userCompanyStates[state.uiState.selectedCompanyIndex], action)
..uiState.replace(uiReducer(state.uiState, action))); ..uiState.replace(uiReducer(state.uiState, action))
..prefState.replace(prefReducer(
state.prefState, action, state.uiState.selectedCompanyIndex)));
} }
final serverVersionReducer = combineReducers<String>([ final serverVersionReducer = combineReducers<String>([

View File

@ -1,6 +1,7 @@
import 'package:built_collection/built_collection.dart'; import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart'; import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart'; import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_state.dart'; import 'package:invoiceninja_flutter/redux/auth/auth_state.dart';
import 'package:invoiceninja_flutter/redux/client/client_selectors.dart'; import 'package:invoiceninja_flutter/redux/client/client_selectors.dart';
@ -28,6 +29,7 @@ import 'package:invoiceninja_flutter/redux/task/task_state.dart';
import 'package:invoiceninja_flutter/redux/tax_rate/tax_rate_selectors.dart'; import 'package:invoiceninja_flutter/redux/tax_rate/tax_rate_selectors.dart';
import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/entity_ui_state.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_selectors.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_selectors.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_state.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_state.dart';
@ -51,19 +53,22 @@ part 'app_state.g.dart';
abstract class AppState implements Built<AppState, AppStateBuilder> { abstract class AppState implements Built<AppState, AppStateBuilder> {
factory AppState({ factory AppState({
UIState uiState, PrefState prefState,
}) { }) {
return _$AppState._( return _$AppState._(
isLoading: false, isLoading: false,
isSaving: false, isSaving: false,
isTesting: false,
serverVersion: '', serverVersion: '',
lastError: '', lastError: '',
authState: AuthState(), authState: AuthState(),
staticState: StaticState(), staticState: StaticState(),
userCompanyStates: BuiltList(List<int>.generate(10, (i) => i + 1) userCompanyStates: BuiltList(
.map((index) => UserCompanyState()) List<int>.generate(kMaxNumberOfCompanies, (i) => i + 1)
.toList()), .map((index) => UserCompanyState())
uiState: uiState ?? UIState(), .toList()),
uiState: UIState(),
prefState: prefState ?? PrefState(),
); );
} }
@ -73,6 +78,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
bool get isSaving; bool get isSaving;
bool get isTesting;
String get lastError; String get lastError;
String get serverVersion; String get serverVersion;
@ -81,6 +88,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
StaticState get staticState; StaticState get staticState;
PrefState get prefState;
UIState get uiState; UIState get uiState;
BuiltList<UserCompanyState> get userCompanyStates; BuiltList<UserCompanyState> get userCompanyStates;
@ -110,6 +119,12 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
Credentials get credentials => Credentials get credentials =>
Credentials(token: userCompanyState.token.token, url: authState.url); Credentials(token: userCompanyState.token.token, url: authState.url);
String get accentColor =>
prefState.companyPrefs[uiState.selectedCompanyIndex].accentColor;
BuiltList<HistoryRecord> get historyList =>
prefState.companyPrefs[uiState.selectedCompanyIndex].historyList;
BuiltMap<String, SelectableEntity> getEntityMap(EntityType type) { BuiltMap<String, SelectableEntity> getEntityMap(EntityType type) {
switch (type) { switch (type) {
case EntityType.product: case EntityType.product:

View File

@ -24,6 +24,9 @@ class _$AppStateSerializer implements StructuredSerializer<AppState> {
'isSaving', 'isSaving',
serializers.serialize(object.isSaving, serializers.serialize(object.isSaving,
specifiedType: const FullType(bool)), specifiedType: const FullType(bool)),
'isTesting',
serializers.serialize(object.isTesting,
specifiedType: const FullType(bool)),
'lastError', 'lastError',
serializers.serialize(object.lastError, serializers.serialize(object.lastError,
specifiedType: const FullType(String)), specifiedType: const FullType(String)),
@ -36,6 +39,9 @@ class _$AppStateSerializer implements StructuredSerializer<AppState> {
'staticState', 'staticState',
serializers.serialize(object.staticState, serializers.serialize(object.staticState,
specifiedType: const FullType(StaticState)), specifiedType: const FullType(StaticState)),
'prefState',
serializers.serialize(object.prefState,
specifiedType: const FullType(PrefState)),
'uiState', 'uiState',
serializers.serialize(object.uiState, serializers.serialize(object.uiState,
specifiedType: const FullType(UIState)), specifiedType: const FullType(UIState)),
@ -67,6 +73,10 @@ class _$AppStateSerializer implements StructuredSerializer<AppState> {
result.isSaving = serializers.deserialize(value, result.isSaving = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool; specifiedType: const FullType(bool)) as bool;
break; break;
case 'isTesting':
result.isTesting = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'lastError': case 'lastError':
result.lastError = serializers.deserialize(value, result.lastError = serializers.deserialize(value,
specifiedType: const FullType(String)) as String; specifiedType: const FullType(String)) as String;
@ -83,6 +93,10 @@ class _$AppStateSerializer implements StructuredSerializer<AppState> {
result.staticState.replace(serializers.deserialize(value, result.staticState.replace(serializers.deserialize(value,
specifiedType: const FullType(StaticState)) as StaticState); specifiedType: const FullType(StaticState)) as StaticState);
break; break;
case 'prefState':
result.prefState.replace(serializers.deserialize(value,
specifiedType: const FullType(PrefState)) as PrefState);
break;
case 'uiState': case 'uiState':
result.uiState.replace(serializers.deserialize(value, result.uiState.replace(serializers.deserialize(value,
specifiedType: const FullType(UIState)) as UIState); specifiedType: const FullType(UIState)) as UIState);
@ -106,6 +120,8 @@ class _$AppState extends AppState {
@override @override
final bool isSaving; final bool isSaving;
@override @override
final bool isTesting;
@override
final String lastError; final String lastError;
@override @override
final String serverVersion; final String serverVersion;
@ -114,6 +130,8 @@ class _$AppState extends AppState {
@override @override
final StaticState staticState; final StaticState staticState;
@override @override
final PrefState prefState;
@override
final UIState uiState; final UIState uiState;
@override @override
final BuiltList<UserCompanyState> userCompanyStates; final BuiltList<UserCompanyState> userCompanyStates;
@ -124,10 +142,12 @@ class _$AppState extends AppState {
_$AppState._( _$AppState._(
{this.isLoading, {this.isLoading,
this.isSaving, this.isSaving,
this.isTesting,
this.lastError, this.lastError,
this.serverVersion, this.serverVersion,
this.authState, this.authState,
this.staticState, this.staticState,
this.prefState,
this.uiState, this.uiState,
this.userCompanyStates}) this.userCompanyStates})
: super._() { : super._() {
@ -137,6 +157,9 @@ class _$AppState extends AppState {
if (isSaving == null) { if (isSaving == null) {
throw new BuiltValueNullFieldError('AppState', 'isSaving'); throw new BuiltValueNullFieldError('AppState', 'isSaving');
} }
if (isTesting == null) {
throw new BuiltValueNullFieldError('AppState', 'isTesting');
}
if (lastError == null) { if (lastError == null) {
throw new BuiltValueNullFieldError('AppState', 'lastError'); throw new BuiltValueNullFieldError('AppState', 'lastError');
} }
@ -149,6 +172,9 @@ class _$AppState extends AppState {
if (staticState == null) { if (staticState == null) {
throw new BuiltValueNullFieldError('AppState', 'staticState'); throw new BuiltValueNullFieldError('AppState', 'staticState');
} }
if (prefState == null) {
throw new BuiltValueNullFieldError('AppState', 'prefState');
}
if (uiState == null) { if (uiState == null) {
throw new BuiltValueNullFieldError('AppState', 'uiState'); throw new BuiltValueNullFieldError('AppState', 'uiState');
} }
@ -170,10 +196,12 @@ class _$AppState extends AppState {
return other is AppState && return other is AppState &&
isLoading == other.isLoading && isLoading == other.isLoading &&
isSaving == other.isSaving && isSaving == other.isSaving &&
isTesting == other.isTesting &&
lastError == other.lastError && lastError == other.lastError &&
serverVersion == other.serverVersion && serverVersion == other.serverVersion &&
authState == other.authState && authState == other.authState &&
staticState == other.staticState && staticState == other.staticState &&
prefState == other.prefState &&
uiState == other.uiState && uiState == other.uiState &&
userCompanyStates == other.userCompanyStates; userCompanyStates == other.userCompanyStates;
} }
@ -185,11 +213,17 @@ class _$AppState extends AppState {
$jc( $jc(
$jc( $jc(
$jc( $jc(
$jc($jc($jc(0, isLoading.hashCode), isSaving.hashCode), $jc(
lastError.hashCode), $jc(
serverVersion.hashCode), $jc(
authState.hashCode), $jc($jc(0, isLoading.hashCode),
staticState.hashCode), isSaving.hashCode),
isTesting.hashCode),
lastError.hashCode),
serverVersion.hashCode),
authState.hashCode),
staticState.hashCode),
prefState.hashCode),
uiState.hashCode), uiState.hashCode),
userCompanyStates.hashCode)); userCompanyStates.hashCode));
} }
@ -206,6 +240,10 @@ class AppStateBuilder implements Builder<AppState, AppStateBuilder> {
bool get isSaving => _$this._isSaving; bool get isSaving => _$this._isSaving;
set isSaving(bool isSaving) => _$this._isSaving = isSaving; set isSaving(bool isSaving) => _$this._isSaving = isSaving;
bool _isTesting;
bool get isTesting => _$this._isTesting;
set isTesting(bool isTesting) => _$this._isTesting = isTesting;
String _lastError; String _lastError;
String get lastError => _$this._lastError; String get lastError => _$this._lastError;
set lastError(String lastError) => _$this._lastError = lastError; set lastError(String lastError) => _$this._lastError = lastError;
@ -226,6 +264,11 @@ class AppStateBuilder implements Builder<AppState, AppStateBuilder> {
set staticState(StaticStateBuilder staticState) => set staticState(StaticStateBuilder staticState) =>
_$this._staticState = staticState; _$this._staticState = staticState;
PrefStateBuilder _prefState;
PrefStateBuilder get prefState =>
_$this._prefState ??= new PrefStateBuilder();
set prefState(PrefStateBuilder prefState) => _$this._prefState = prefState;
UIStateBuilder _uiState; UIStateBuilder _uiState;
UIStateBuilder get uiState => _$this._uiState ??= new UIStateBuilder(); UIStateBuilder get uiState => _$this._uiState ??= new UIStateBuilder();
set uiState(UIStateBuilder uiState) => _$this._uiState = uiState; set uiState(UIStateBuilder uiState) => _$this._uiState = uiState;
@ -242,10 +285,12 @@ class AppStateBuilder implements Builder<AppState, AppStateBuilder> {
if (_$v != null) { if (_$v != null) {
_isLoading = _$v.isLoading; _isLoading = _$v.isLoading;
_isSaving = _$v.isSaving; _isSaving = _$v.isSaving;
_isTesting = _$v.isTesting;
_lastError = _$v.lastError; _lastError = _$v.lastError;
_serverVersion = _$v.serverVersion; _serverVersion = _$v.serverVersion;
_authState = _$v.authState?.toBuilder(); _authState = _$v.authState?.toBuilder();
_staticState = _$v.staticState?.toBuilder(); _staticState = _$v.staticState?.toBuilder();
_prefState = _$v.prefState?.toBuilder();
_uiState = _$v.uiState?.toBuilder(); _uiState = _$v.uiState?.toBuilder();
_userCompanyStates = _$v.userCompanyStates?.toBuilder(); _userCompanyStates = _$v.userCompanyStates?.toBuilder();
_$v = null; _$v = null;
@ -274,10 +319,12 @@ class AppStateBuilder implements Builder<AppState, AppStateBuilder> {
new _$AppState._( new _$AppState._(
isLoading: isLoading, isLoading: isLoading,
isSaving: isSaving, isSaving: isSaving,
isTesting: isTesting,
lastError: lastError, lastError: lastError,
serverVersion: serverVersion, serverVersion: serverVersion,
authState: authState.build(), authState: authState.build(),
staticState: staticState.build(), staticState: staticState.build(),
prefState: prefState.build(),
uiState: uiState.build(), uiState: uiState.build(),
userCompanyStates: userCompanyStates.build()); userCompanyStates: userCompanyStates.build());
} catch (_) { } catch (_) {
@ -287,6 +334,8 @@ class AppStateBuilder implements Builder<AppState, AppStateBuilder> {
authState.build(); authState.build();
_$failedField = 'staticState'; _$failedField = 'staticState';
staticState.build(); staticState.build();
_$failedField = 'prefState';
prefState.build();
_$failedField = 'uiState'; _$failedField = 'uiState';
uiState.build(); uiState.build();
_$failedField = 'userCompanyStates'; _$failedField = 'userCompanyStates';

View File

@ -19,7 +19,7 @@ class ViewClientList implements PersistUI {
final bool force; final bool force;
} }
class ViewClient implements PersistUI { class ViewClient implements PersistUI, PersistPrefs {
ViewClient({ ViewClient({
@required this.clientId, @required this.clientId,
@required this.context, @required this.context,
@ -31,7 +31,7 @@ class ViewClient implements PersistUI {
final bool force; final bool force;
} }
class EditClient implements PersistUI { class EditClient implements PersistUI, PersistPrefs {
EditClient( EditClient(
{@required this.client, {@required this.client,
@required this.context, @required this.context,
@ -303,7 +303,7 @@ void handleClientAction(
case EntityAction.newExpense: case EntityAction.newExpense:
store.dispatch(EditExpense( store.dispatch(EditExpense(
expense: ExpenseEntity( expense: ExpenseEntity(
company: company, client: client, uiState: state.uiState), company: company, client: client, prefState: state.prefState),
context: context)); context: context));
break; break;
case EntityAction.enterPayment: case EntityAction.enterPayment:

View File

@ -17,7 +17,7 @@ class ViewCompanyGatewayList implements PersistUI {
final bool force; final bool force;
} }
class ViewCompanyGateway implements PersistUI { class ViewCompanyGateway implements PersistUI, PersistPrefs {
ViewCompanyGateway({ ViewCompanyGateway({
@required this.companyGatewayId, @required this.companyGatewayId,
@required this.context, @required this.context,
@ -29,7 +29,7 @@ class ViewCompanyGateway implements PersistUI {
final bool force; final bool force;
} }
class EditCompanyGateway implements PersistUI { class EditCompanyGateway implements PersistUI, PersistPrefs {
EditCompanyGateway( EditCompanyGateway(
{@required this.companyGateway, {@required this.companyGateway,
@required this.context, @required this.context,

View File

@ -19,7 +19,7 @@ class ViewExpenseList implements PersistUI {
final bool force; final bool force;
} }
class ViewExpense implements PersistUI { class ViewExpense implements PersistUI, PersistPrefs {
ViewExpense({ ViewExpense({
@required this.expenseId, @required this.expenseId,
@required this.context, @required this.context,
@ -31,7 +31,7 @@ class ViewExpense implements PersistUI {
final bool force; final bool force;
} }
class EditExpense implements PersistUI { class EditExpense implements PersistUI, PersistPrefs {
EditExpense( EditExpense(
{@required this.expense, {@required this.expense,
@required this.context, @required this.context,

View File

@ -20,7 +20,7 @@ class ViewGroupList implements PersistUI {
final bool force; final bool force;
} }
class ViewGroup implements PersistUI { class ViewGroup implements PersistUI, PersistPrefs {
ViewGroup({ ViewGroup({
@required this.groupId, @required this.groupId,
@required this.context, @required this.context,
@ -32,7 +32,7 @@ class ViewGroup implements PersistUI {
final bool force; final bool force;
} }
class EditGroup implements PersistUI { class EditGroup implements PersistUI, PersistPrefs {
EditGroup( EditGroup(
{@required this.group, {@required this.group,
@required this.context, @required this.context,

View File

@ -20,7 +20,7 @@ class ViewInvoiceList implements PersistUI {
final bool force; final bool force;
} }
class ViewInvoice implements PersistUI { class ViewInvoice implements PersistUI, PersistPrefs {
ViewInvoice({this.invoiceId, this.context, this.force = false}); ViewInvoice({this.invoiceId, this.context, this.force = false});
final String invoiceId; final String invoiceId;
@ -28,7 +28,7 @@ class ViewInvoice implements PersistUI {
final bool force; final bool force;
} }
class EditInvoice implements PersistUI { class EditInvoice implements PersistUI, PersistPrefs {
EditInvoice( EditInvoice(
{this.invoice, {this.invoice,
this.context, this.context,

View File

@ -16,7 +16,7 @@ class ViewPaymentList implements PersistUI {
final bool force; final bool force;
} }
class ViewPayment implements PersistUI { class ViewPayment implements PersistUI, PersistPrefs {
ViewPayment({ ViewPayment({
@required this.paymentId, @required this.paymentId,
@required this.context, @required this.context,
@ -28,7 +28,7 @@ class ViewPayment implements PersistUI {
final bool force; final bool force;
} }
class EditPayment implements PersistUI { class EditPayment implements PersistUI, PersistPrefs {
EditPayment( EditPayment(
{@required this.payment, {@required this.payment,
@required this.context, @required this.context,

View File

@ -193,7 +193,7 @@ Middleware<AppState> _savePayment(PaymentRepository repository) {
final action = dynamicAction as SavePaymentRequest; final action = dynamicAction as SavePaymentRequest;
final PaymentEntity payment = action.payment; final PaymentEntity payment = action.payment;
final bool sendEmail = final bool sendEmail =
payment.isNew ? store.state.uiState.emailPayment : false; payment.isNew ? store.state.prefState.emailPayment : false;
repository repository
.saveData(store.state.credentials, action.payment, sendEmail: sendEmail) .saveData(store.state.credentials, action.payment, sendEmail: sendEmail)
.then((PaymentEntity payment) { .then((PaymentEntity payment) {

View File

@ -18,7 +18,7 @@ class ViewProductList implements PersistUI {
final bool force; final bool force;
} }
class ViewProduct implements PersistUI { class ViewProduct implements PersistUI, PersistPrefs {
ViewProduct( ViewProduct(
{@required this.productId, @required this.context, this.force = false}); {@required this.productId, @required this.context, this.force = false});
@ -27,7 +27,7 @@ class ViewProduct implements PersistUI {
final bool force; final bool force;
} }
class EditProduct implements PersistUI { class EditProduct implements PersistUI, PersistPrefs {
EditProduct( EditProduct(
{@required this.product, {@required this.product,
@required this.context, @required this.context,

View File

@ -20,7 +20,7 @@ class ViewProjectList implements PersistUI {
final bool force; final bool force;
} }
class ViewProject implements PersistUI { class ViewProject implements PersistUI, PersistPrefs {
ViewProject({ ViewProject({
@required this.projectId, @required this.projectId,
@required this.context, @required this.context,
@ -32,7 +32,7 @@ class ViewProject implements PersistUI {
final bool force; final bool force;
} }
class EditProject implements PersistUI { class EditProject implements PersistUI, PersistPrefs {
EditProject( EditProject(
{@required this.project, {@required this.project,
@required this.context, @required this.context,
@ -270,7 +270,7 @@ void handleProjectAction(
break; break;
case EntityAction.newTask: case EntityAction.newTask:
store.dispatch(EditTask( store.dispatch(EditTask(
task: TaskEntity(isRunning: state.uiState.autoStartTasks) task: TaskEntity(isRunning: state.prefState.autoStartTasks)
.rebuild((b) => b .rebuild((b) => b
..projectId = project.id ..projectId = project.id
..clientId = project.clientId), ..clientId = project.clientId),

View File

@ -20,7 +20,7 @@ class ViewQuoteList implements PersistUI {
final bool force; final bool force;
} }
class ViewQuote implements PersistUI { class ViewQuote implements PersistUI, PersistPrefs {
ViewQuote({this.quoteId, this.context, this.force = false}); ViewQuote({this.quoteId, this.context, this.force = false});
final String quoteId; final String quoteId;
@ -28,7 +28,7 @@ class ViewQuote implements PersistUI {
final bool force; final bool force;
} }
class EditQuote implements PersistUI { class EditQuote implements PersistUI, PersistPrefs {
EditQuote( EditQuote(
{this.quote, {this.quote,
this.context, this.context,

View File

@ -21,7 +21,7 @@ class ViewTaskList implements PersistUI {
final bool force; final bool force;
} }
class ViewTask implements PersistUI { class ViewTask implements PersistUI, PersistPrefs {
ViewTask({ ViewTask({
@required this.taskId, @required this.taskId,
@required this.context, @required this.context,
@ -33,7 +33,7 @@ class ViewTask implements PersistUI {
final bool force; final bool force;
} }
class EditTask implements PersistUI { class EditTask implements PersistUI, PersistPrefs {
EditTask( EditTask(
{this.task, {this.task,
this.taskTime, this.taskTime,

View File

@ -1,5 +1,6 @@
import 'dart:math'; import 'dart:math';
import 'package:built_collection/built_collection.dart'; import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
@ -353,6 +354,6 @@ BuiltList<HistoryRecord> _addToHistory(
} else { } else {
return list.rebuild((b) => b return list.rebuild((b) => b
..insert(0, record) ..insert(0, record)
..sublist(0, min(200, list.length + 1))); ..sublist(0, min(kMaxNumberOfHistory, list.length + 1)));
} }
} }

View File

@ -32,9 +32,10 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
autoStartTasks: false, autoStartTasks: false,
longPressSelectionIsDefault: longPressSelectionIsDefault ?? false, longPressSelectionIsDefault: longPressSelectionIsDefault ?? false,
addDocumentsToInvoice: false, addDocumentsToInvoice: false,
companyPrefs: BuiltList(List<int>.generate(10, (i) => i + 1) companyPrefs: BuiltList(
.map((index) => CompanyPrefState()) List<int>.generate(kMaxNumberOfCompanies, (i) => i + 1)
.toList()), .map((index) => CompanyPrefState())
.toList()),
); );
} }
@ -64,6 +65,12 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
BuiltList<CompanyPrefState> get companyPrefs; BuiltList<CompanyPrefState> get companyPrefs;
bool get isMenuFloated =>
layout == AppLayout.mobile || menuSidebarMode == AppSidebarMode.float;
bool get isHistoryFloated =>
layout == AppLayout.mobile || historySidebarMode == AppSidebarMode.float;
static Serializer<PrefState> get serializer => _$prefStateSerializer; static Serializer<PrefState> get serializer => _$prefStateSerializer;
} }

View File

@ -18,7 +18,6 @@ import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/redux/task/task_actions.dart'; import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_reducer.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart'; import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
@ -47,8 +46,6 @@ import 'package:invoiceninja_flutter/redux/group/group_reducer.dart';
UIState uiReducer(UIState state, dynamic action) { UIState uiReducer(UIState state, dynamic action) {
final currentRoute = currentRouteReducer(state.currentRoute, action); final currentRoute = currentRouteReducer(state.currentRoute, action);
return state.rebuild((b) => b return state.rebuild((b) => b
..prefState.replace(
prefReducer(state.prefState, action, state.selectedCompanyIndex))
..filter = filterReducer(state.filter, action) ..filter = filterReducer(state.filter, action)
..filterClearedAt = filterClearedAtReducer(state.filterClearedAt, action) ..filterClearedAt = filterClearedAtReducer(state.filterClearedAt, action)
..selectedCompanyIndex = ..selectedCompanyIndex =

View File

@ -1,4 +1,3 @@
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart'; import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart'; import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/redux/client/client_state.dart'; import 'package:invoiceninja_flutter/redux/client/client_state.dart';
@ -6,7 +5,6 @@ import 'package:invoiceninja_flutter/redux/company/company_state.dart';
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_state.dart'; import 'package:invoiceninja_flutter/redux/dashboard/dashboard_state.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_state.dart'; import 'package:invoiceninja_flutter/redux/invoice/invoice_state.dart';
import 'package:invoiceninja_flutter/redux/product/product_state.dart'; import 'package:invoiceninja_flutter/redux/product/product_state.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart'; import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
import 'package:invoiceninja_flutter/redux/document/document_state.dart'; import 'package:invoiceninja_flutter/redux/document/document_state.dart';
import 'package:invoiceninja_flutter/redux/expense/expense_state.dart'; import 'package:invoiceninja_flutter/redux/expense/expense_state.dart';
@ -24,15 +22,10 @@ import 'package:invoiceninja_flutter/redux/group/group_state.dart';
part 'ui_state.g.dart'; part 'ui_state.g.dart';
abstract class UIState implements Built<UIState, UIStateBuilder> { abstract class UIState implements Built<UIState, UIStateBuilder> {
factory UIState({ factory UIState() {
bool isTesting,
PrefState prefState,
}) {
return _$UIState._( return _$UIState._(
prefState: prefState ?? PrefState(),
selectedCompanyIndex: 0, selectedCompanyIndex: 0,
filterClearedAt: 0, filterClearedAt: 0,
isTesting: isTesting ?? false,
currentRoute: LoginScreen.route, currentRoute: LoginScreen.route,
previousRoute: '', previousRoute: '',
dashboardUIState: DashboardUIState(), dashboardUIState: DashboardUIState(),
@ -57,10 +50,6 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
UIState._(); UIState._();
PrefState get prefState;
bool get isTesting;
int get selectedCompanyIndex; int get selectedCompanyIndex;
String get currentRoute; String get currentRoute;
@ -134,39 +123,5 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
bool get isEditing => currentRoute.endsWith('edit'); bool get isEditing => currentRoute.endsWith('edit');
AppLayout get layout => prefState.layout;
AppSidebarMode get historySidebarMode => prefState.historySidebarMode;
AppSidebarMode get menuSidebarMode => prefState.menuSidebarMode;
bool get isMenuVisible => prefState.isMenuVisible;
bool get isHistoryVisible => prefState.isHistoryVisible;
bool get enableDarkMode => prefState.enableDarkMode;
bool get longPressSelectionIsDefault => prefState.longPressSelectionIsDefault;
bool get requireAuthentication => prefState.requireAuthentication;
bool get emailPayment => prefState.emailPayment;
bool get autoStartTasks => prefState.autoStartTasks;
bool get addDocumentsToInvoice => prefState.addDocumentsToInvoice;
CompanyPrefState get companyPrefState => prefState.companyPrefs[selectedCompanyIndex];
String get accentColor => companyPrefState.accentColor;
BuiltList<HistoryRecord> get historyList => companyPrefState.historyList;
bool get isMenuFloated =>
layout == AppLayout.mobile || prefState.menuSidebarMode == AppSidebarMode.float;
bool get isHistoryFloated =>
layout == AppLayout.mobile || prefState.historySidebarMode == AppSidebarMode.float;
} }

View File

@ -18,12 +18,6 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
Iterable<Object> serialize(Serializers serializers, UIState object, Iterable<Object> serialize(Serializers serializers, UIState object,
{FullType specifiedType = FullType.unspecified}) { {FullType specifiedType = FullType.unspecified}) {
final result = <Object>[ final result = <Object>[
'prefState',
serializers.serialize(object.prefState,
specifiedType: const FullType(PrefState)),
'isTesting',
serializers.serialize(object.isTesting,
specifiedType: const FullType(bool)),
'selectedCompanyIndex', 'selectedCompanyIndex',
serializers.serialize(object.selectedCompanyIndex, serializers.serialize(object.selectedCompanyIndex,
specifiedType: const FullType(int)), specifiedType: const FullType(int)),
@ -105,14 +99,6 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
iterator.moveNext(); iterator.moveNext();
final dynamic value = iterator.current; final dynamic value = iterator.current;
switch (key) { switch (key) {
case 'prefState':
result.prefState.replace(serializers.deserialize(value,
specifiedType: const FullType(PrefState)) as PrefState);
break;
case 'isTesting':
result.isTesting = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'selectedCompanyIndex': case 'selectedCompanyIndex':
result.selectedCompanyIndex = serializers.deserialize(value, result.selectedCompanyIndex = serializers.deserialize(value,
specifiedType: const FullType(int)) as int; specifiedType: const FullType(int)) as int;
@ -209,10 +195,6 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
} }
class _$UIState extends UIState { class _$UIState extends UIState {
@override
final PrefState prefState;
@override
final bool isTesting;
@override @override
final int selectedCompanyIndex; final int selectedCompanyIndex;
@override @override
@ -260,9 +242,7 @@ class _$UIState extends UIState {
(new UIStateBuilder()..update(updates)).build(); (new UIStateBuilder()..update(updates)).build();
_$UIState._( _$UIState._(
{this.prefState, {this.selectedCompanyIndex,
this.isTesting,
this.selectedCompanyIndex,
this.currentRoute, this.currentRoute,
this.previousRoute, this.previousRoute,
this.filter, this.filter,
@ -284,12 +264,6 @@ class _$UIState extends UIState {
this.quoteUIState, this.quoteUIState,
this.settingsUIState}) this.settingsUIState})
: super._() { : super._() {
if (prefState == null) {
throw new BuiltValueNullFieldError('UIState', 'prefState');
}
if (isTesting == null) {
throw new BuiltValueNullFieldError('UIState', 'isTesting');
}
if (selectedCompanyIndex == null) { if (selectedCompanyIndex == null) {
throw new BuiltValueNullFieldError('UIState', 'selectedCompanyIndex'); throw new BuiltValueNullFieldError('UIState', 'selectedCompanyIndex');
} }
@ -363,8 +337,6 @@ class _$UIState extends UIState {
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(other, this)) return true; if (identical(other, this)) return true;
return other is UIState && return other is UIState &&
prefState == other.prefState &&
isTesting == other.isTesting &&
selectedCompanyIndex == other.selectedCompanyIndex && selectedCompanyIndex == other.selectedCompanyIndex &&
currentRoute == other.currentRoute && currentRoute == other.currentRoute &&
previousRoute == other.previousRoute && previousRoute == other.previousRoute &&
@ -408,7 +380,7 @@ class _$UIState extends UIState {
$jc( $jc(
$jc( $jc(
$jc( $jc(
$jc($jc($jc($jc($jc(0, prefState.hashCode), isTesting.hashCode), selectedCompanyIndex.hashCode), currentRoute.hashCode), $jc($jc($jc(0, selectedCompanyIndex.hashCode), currentRoute.hashCode),
previousRoute.hashCode), previousRoute.hashCode),
filter.hashCode), filter.hashCode),
filterClearedAt.hashCode), filterClearedAt.hashCode),
@ -433,8 +405,6 @@ class _$UIState extends UIState {
@override @override
String toString() { String toString() {
return (newBuiltValueToStringHelper('UIState') return (newBuiltValueToStringHelper('UIState')
..add('prefState', prefState)
..add('isTesting', isTesting)
..add('selectedCompanyIndex', selectedCompanyIndex) ..add('selectedCompanyIndex', selectedCompanyIndex)
..add('currentRoute', currentRoute) ..add('currentRoute', currentRoute)
..add('previousRoute', previousRoute) ..add('previousRoute', previousRoute)
@ -463,15 +433,6 @@ class _$UIState extends UIState {
class UIStateBuilder implements Builder<UIState, UIStateBuilder> { class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
_$UIState _$v; _$UIState _$v;
PrefStateBuilder _prefState;
PrefStateBuilder get prefState =>
_$this._prefState ??= new PrefStateBuilder();
set prefState(PrefStateBuilder prefState) => _$this._prefState = prefState;
bool _isTesting;
bool get isTesting => _$this._isTesting;
set isTesting(bool isTesting) => _$this._isTesting = isTesting;
int _selectedCompanyIndex; int _selectedCompanyIndex;
int get selectedCompanyIndex => _$this._selectedCompanyIndex; int get selectedCompanyIndex => _$this._selectedCompanyIndex;
set selectedCompanyIndex(int selectedCompanyIndex) => set selectedCompanyIndex(int selectedCompanyIndex) =>
@ -596,8 +557,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
UIStateBuilder get _$this { UIStateBuilder get _$this {
if (_$v != null) { if (_$v != null) {
_prefState = _$v.prefState?.toBuilder();
_isTesting = _$v.isTesting;
_selectedCompanyIndex = _$v.selectedCompanyIndex; _selectedCompanyIndex = _$v.selectedCompanyIndex;
_currentRoute = _$v.currentRoute; _currentRoute = _$v.currentRoute;
_previousRoute = _$v.previousRoute; _previousRoute = _$v.previousRoute;
@ -643,8 +602,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
try { try {
_$result = _$v ?? _$result = _$v ??
new _$UIState._( new _$UIState._(
prefState: prefState.build(),
isTesting: isTesting,
selectedCompanyIndex: selectedCompanyIndex, selectedCompanyIndex: selectedCompanyIndex,
currentRoute: currentRoute, currentRoute: currentRoute,
previousRoute: previousRoute, previousRoute: previousRoute,
@ -669,9 +626,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
} catch (_) { } catch (_) {
String _$failedField; String _$failedField;
try { try {
_$failedField = 'prefState';
prefState.build();
_$failedField = 'dashboardUIState'; _$failedField = 'dashboardUIState';
dashboardUIState.build(); dashboardUIState.build();
_$failedField = 'productUIState'; _$failedField = 'productUIState';

View File

@ -16,7 +16,7 @@ class ViewUserList implements PersistUI {
final bool force; final bool force;
} }
class ViewUser implements PersistUI { class ViewUser implements PersistUI, PersistPrefs {
ViewUser({ ViewUser({
@required this.userId, @required this.userId,
@required this.context, @required this.context,
@ -28,7 +28,7 @@ class ViewUser implements PersistUI {
final bool force; final bool force;
} }
class EditUser implements PersistUI { class EditUser implements PersistUI, PersistPrefs {
EditUser( EditUser(
{@required this.user, {@required this.user,
@required this.context, @required this.context,

View File

@ -17,7 +17,7 @@ class ViewVendorList implements PersistUI {
final bool force; final bool force;
} }
class ViewVendor implements PersistUI { class ViewVendor implements PersistUI, PersistPrefs {
ViewVendor({ ViewVendor({
@required this.vendorId, @required this.vendorId,
@required this.context, @required this.context,
@ -29,7 +29,7 @@ class ViewVendor implements PersistUI {
final bool force; final bool force;
} }
class EditVendor implements PersistUI { class EditVendor implements PersistUI, PersistPrefs {
EditVendor( EditVendor(
{@required this.vendor, {@required this.vendor,
@required this.context, @required this.context,

View File

@ -44,7 +44,7 @@ class ActionFlatButton extends StatelessWidget {
tooltip, tooltip,
style: TextStyle( style: TextStyle(
color: isDirty color: isDirty
? (state.uiState.enableDarkMode ? (state.prefState.enableDarkMode
? Theme.of(context).accentColor ? Theme.of(context).accentColor
: Colors.yellowAccent) : Colors.yellowAccent)
: Colors.white), : Colors.white),

View File

@ -27,11 +27,7 @@ class HistoryDrawer extends StatelessWidget {
final state = store.state; final state = store.state;
final widgets = <Widget>[]; final widgets = <Widget>[];
for (var history in state.uiState.historyList) { for (var history in state.historyList) {
if (widgets.length > 50) {
break;
}
final entity = final entity =
state.getEntityMap(history.entityType)[history.id] as BaseEntity; state.getEntityMap(history.entityType)[history.id] as BaseEntity;
@ -66,7 +62,7 @@ class HistoryDrawer extends StatelessWidget {
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
title: Text(localization.history), title: Text(localization.history),
actions: <Widget>[ actions: <Widget>[
if (state.uiState.isHistoryFloated) if (state.prefState.isHistoryFloated)
Builder( Builder(
builder: (context) => IconButton( builder: (context) => IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu),

View File

@ -45,7 +45,7 @@ class _ListFilterState extends State<ListFilter> {
return StoreConnector<AppState, AppState>( return StoreConnector<AppState, AppState>(
converter: (Store<AppState> store) => store.state, converter: (Store<AppState> store) => store.state,
builder: (BuildContext context, state) { builder: (BuildContext context, state) {
final bool enableDarkMode = state.uiState.enableDarkMode; final bool enableDarkMode = state.prefState.enableDarkMode;
return widget.filter == null return widget.filter == null
? Text('${widget.title ?? ''}') ? Text('${widget.title ?? ''}')
: Container( : Container(

View File

@ -61,7 +61,7 @@ class ListScaffold extends StatelessWidget {
child: IconButton( child: IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu),
onPressed: () { onPressed: () {
if (isMobile(context) || state.uiState.isMenuFloated) { if (isMobile(context) || state.prefState.isMenuFloated) {
Scaffold.of(context).openDrawer(); Scaffold.of(context).openDrawer();
} else { } else {
store.dispatch(UserSettingsChanged(sidebar: AppSidebar.menu)); store.dispatch(UserSettingsChanged(sidebar: AppSidebar.menu));
@ -78,10 +78,10 @@ class ListScaffold extends StatelessWidget {
return false; return false;
}, },
child: Scaffold( child: Scaffold(
drawer: isMobile(context) || state.uiState.isMenuFloated drawer: isMobile(context) || state.prefState.isMenuFloated
? MenuDrawerBuilder() ? MenuDrawerBuilder()
: null, : null,
endDrawer: isMobile(context) || state.uiState.isHistoryFloated endDrawer: isMobile(context) || state.prefState.isHistoryFloated
? HistoryDrawerBuilder() ? HistoryDrawerBuilder()
: null, : null,
appBar: AppBar( appBar: AppBar(
@ -92,12 +92,12 @@ class ListScaffold extends StatelessWidget {
...appBarActions, ...appBarActions,
if (!showCheckbox && if (!showCheckbox &&
!isSettings && !isSettings &&
!state.uiState.isHistoryVisible) !state.prefState.isHistoryVisible)
Builder( Builder(
builder: (context) => IconButton( builder: (context) => IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu),
onPressed: () { onPressed: () {
if (isMobile(context) || state.uiState.isHistoryFloated) { if (isMobile(context) || state.prefState.isHistoryFloated) {
Scaffold.of(context).openEndDrawer(); Scaffold.of(context).openEndDrawer();
} else { } else {
store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history)); store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history));

View File

@ -24,6 +24,7 @@ class MainScreen extends StatelessWidget {
onInit: (Store<AppState> store) => store.dispatch(LoadDashboard()), onInit: (Store<AppState> store) => store.dispatch(LoadDashboard()),
builder: (BuildContext context, Store<AppState> store) { builder: (BuildContext context, Store<AppState> store) {
final uiState = store.state.uiState; final uiState = store.state.uiState;
final prefState = store.state.prefState;
final mainRoute = '/' + uiState.mainRoute; final mainRoute = '/' + uiState.mainRoute;
Widget screen = BlankScreen(); Widget screen = BlankScreen();
@ -35,8 +36,8 @@ class MainScreen extends StatelessWidget {
child: DashboardScreenBuilder(), child: DashboardScreenBuilder(),
flex: 5, flex: 5,
), ),
if (uiState.isHistoryVisible && if (prefState.isHistoryVisible &&
uiState.historySidebarMode == AppSidebarMode.visible) ...[ prefState.historySidebarMode == AppSidebarMode.visible) ...[
_CustomDivider(), _CustomDivider(),
Expanded( Expanded(
child: HistoryDrawerBuilder(), child: HistoryDrawerBuilder(),
@ -124,8 +125,8 @@ class MainScreen extends StatelessWidget {
} }
return Row(children: <Widget>[ return Row(children: <Widget>[
if (uiState.isMenuVisible && if (prefState.isMenuVisible &&
uiState.menuSidebarMode == AppSidebarMode.visible) ...[ prefState.menuSidebarMode == AppSidebarMode.visible) ...[
MenuDrawerBuilder(), MenuDrawerBuilder(),
_CustomDivider(), _CustomDivider(),
], ],
@ -244,6 +245,7 @@ class SettingsScreens extends StatelessWidget {
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final state = store.state; final state = store.state;
final uiState = state.uiState; final uiState = state.uiState;
final prefState = state.prefState;
Widget screen = BlankScreen(); Widget screen = BlankScreen();
@ -350,8 +352,8 @@ class SettingsScreens extends StatelessWidget {
flex: 3, flex: 3,
child: screen, child: screen,
), ),
if (uiState.isHistoryVisible && if (prefState.isHistoryVisible &&
uiState.historySidebarMode == AppSidebarMode.visible) ...[ prefState.historySidebarMode == AppSidebarMode.visible) ...[
_CustomDivider(), _CustomDivider(),
Expanded( Expanded(
child: HistoryDrawerBuilder(), child: HistoryDrawerBuilder(),
@ -380,6 +382,7 @@ class EntityScreens extends StatelessWidget {
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final state = store.state; final state = store.state;
final uiState = state.uiState; final uiState = state.uiState;
final prefState = state.prefState;
final subRoute = uiState.subRoute; final subRoute = uiState.subRoute;
final entityUIState = state.getUIState(entityType); final entityUIState = state.getUIState(entityType);
@ -402,8 +405,8 @@ class EntityScreens extends StatelessWidget {
], ],
), ),
), ),
if (uiState.isHistoryVisible && if (prefState.isHistoryVisible &&
uiState.historySidebarMode == AppSidebarMode.visible) ...[ prefState.historySidebarMode == AppSidebarMode.visible) ...[
_CustomDivider(), _CustomDivider(),
Expanded( Expanded(
child: HistoryDrawerBuilder(), child: HistoryDrawerBuilder(),

View File

@ -141,7 +141,7 @@ class MenuDrawer extends StatelessWidget {
final Store<AppState> store = StoreProvider.of<AppState>(context); final Store<AppState> store = StoreProvider.of<AppState>(context);
final NavigatorState navigator = Navigator.of(context); final NavigatorState navigator = Navigator.of(context);
final state = store.state; final state = store.state;
final enableDarkMode = state.uiState.enableDarkMode; final enableDarkMode = state.prefState.enableDarkMode;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
return Drawer( return Drawer(
@ -286,7 +286,7 @@ class MenuDrawer extends StatelessWidget {
} }
store.dispatch(EditTask( store.dispatch(EditTask(
task: TaskEntity( task: TaskEntity(
isRunning: state.uiState.autoStartTasks), isRunning: state.prefState.autoStartTasks),
context: context)); context: context));
}, },
), ),
@ -318,7 +318,7 @@ class MenuDrawer extends StatelessWidget {
} }
store.dispatch(EditExpense( store.dispatch(EditExpense(
expense: ExpenseEntity( expense: ExpenseEntity(
company: company, uiState: state.uiState), company: company, prefState: state.prefState),
context: context)); context: context));
}, },
), ),

View File

@ -15,10 +15,10 @@ class CachedImage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final uiState = store.state.uiState; final state = store.state;
// TODO remove this workaround // TODO remove this workaround
if (uiState.isTesting || (url ?? '').isEmpty) { if (state.isTesting || (url ?? '').isEmpty) {
return SizedBox( return SizedBox(
width: width, width: width,
height: height, height: height,

View File

@ -74,7 +74,7 @@ class ClientList extends StatelessWidget {
onTap: () => onTap: () =>
viewModel.onClientTap(context, client), viewModel.onClientTap(context, client),
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -147,7 +147,7 @@ class _ClientViewState extends State<ClientView>
store.dispatch(EditTask( store.dispatch(EditTask(
task: TaskEntity( task: TaskEntity(
isRunning: isRunning:
store.state.uiState.autoStartTasks) store.state.prefState.autoStartTasks)
.rebuild((b) => b.clientId = client.id), .rebuild((b) => b.clientId = client.id),
context: context)); context: context));
}, },
@ -165,7 +165,7 @@ class _ClientViewState extends State<ClientView>
expense: ExpenseEntity( expense: ExpenseEntity(
company: company, company: company,
client: client, client: client,
uiState: store.state.uiState), prefState: store.state.prefState),
context: context)); context: context));
}, },
) )

View File

@ -147,7 +147,7 @@ class ClientViewVM {
if (longPress && client.isActive) { if (longPress && client.isActive) {
store.dispatch(EditTask( store.dispatch(EditTask(
context: context, context: context,
task: TaskEntity(isRunning: state.uiState.autoStartTasks) task: TaskEntity(isRunning: state.prefState.autoStartTasks)
.rebuild((b) => b..clientId = client.id))); .rebuild((b) => b..clientId = client.id)));
} else { } else {
store.dispatch(FilterTasksByEntity( store.dispatch(FilterTasksByEntity(
@ -162,7 +162,7 @@ class ClientViewVM {
expense: ExpenseEntity( expense: ExpenseEntity(
company: state.company, company: state.company,
client: client, client: client,
uiState: state.uiState))); prefState: state.prefState)));
} else { } else {
store.dispatch(FilterExpensesByEntity( store.dispatch(FilterExpensesByEntity(
entityId: client.id, entityType: EntityType.client)); entityId: client.id, entityType: EntityType.client));

View File

@ -58,7 +58,7 @@ class _DashboardChartState extends State<DashboardChart> {
final theme = Theme.of(context); final theme = Theme.of(context);
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final state = StoreProvider.of<AppState>(context).state; final state = StoreProvider.of<AppState>(context).state;
final color = state.uiState.enableDarkMode final color = state.prefState.enableDarkMode
? charts.MaterialPalette.white ? charts.MaterialPalette.white
: charts.MaterialPalette.gray.shade700; : charts.MaterialPalette.gray.shade700;

View File

@ -59,14 +59,14 @@ class _DashboardScreenState extends State<DashboardScreen>
return WillPopScope( return WillPopScope(
onWillPop: () async => true, onWillPop: () async => true,
child: Scaffold( child: Scaffold(
drawer: isMobile(context) || state.uiState.isMenuFloated drawer: isMobile(context) || state.prefState.isMenuFloated
? MenuDrawerBuilder() ? MenuDrawerBuilder()
: null, : null,
endDrawer: isMobile(context) || state.uiState.isHistoryFloated endDrawer: isMobile(context) || state.prefState.isHistoryFloated
? HistoryDrawerBuilder() ? HistoryDrawerBuilder()
: null, : null,
appBar: AppBar( appBar: AppBar(
leading: isMobile(context) || state.uiState.isMenuFloated leading: isMobile(context) || state.prefState.isMenuFloated
? null ? null
: IconButton( : IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu),
@ -88,12 +88,12 @@ class _DashboardScreenState extends State<DashboardScreen>
store.dispatch(FilterCompany(value)); store.dispatch(FilterCompany(value));
}, },
), ),
if (!state.uiState.isHistoryVisible) if (!state.prefState.isHistoryVisible)
Builder( Builder(
builder: (context) => IconButton( builder: (context) => IconButton(
icon: Icon(Icons.menu), icon: Icon(Icons.menu),
onPressed: () { onPressed: () {
if (isMobile(context) || state.uiState.isHistoryFloated) { if (isMobile(context) || state.prefState.isHistoryFloated) {
Scaffold.of(context).openEndDrawer(); Scaffold.of(context).openEndDrawer();
} else { } else {
store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history)); store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history));

View File

@ -71,7 +71,7 @@ class DocumentList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -84,7 +84,7 @@ class ExpenseList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -145,7 +145,7 @@ class ExpenseScreen extends StatelessWidget {
onPressed: () { onPressed: () {
store.dispatch(EditExpense( store.dispatch(EditExpense(
expense: ExpenseEntity( expense: ExpenseEntity(
company: company, uiState: store.state.uiState), company: company, prefState: store.state.prefState),
context: context)); context: context));
}, },
child: Icon( child: Icon(

View File

@ -68,7 +68,7 @@ class GroupList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -318,7 +318,7 @@ class _InvoiceItemSelectorState extends State<InvoiceItemSelector>
_headerRow(), _headerRow(),
showTabBar showTabBar
? TabBar( ? TabBar(
labelColor: state.uiState.enableDarkMode labelColor: state.prefState.enableDarkMode
? Colors.white ? Colors.white
: Colors.black, : Colors.black,
indicatorColor: Theme.of(context).accentColor, indicatorColor: Theme.of(context).accentColor,

View File

@ -81,7 +81,7 @@ class InvoiceList extends StatelessWidget {
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = final longPressIsSelection =
state.uiState.longPressSelectionIsDefault ?? state.prefState.longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {
handleInvoiceAction(context, [invoice], handleInvoiceAction(context, [invoice],

View File

@ -237,7 +237,7 @@ class _PaymentEditState extends State<PaymentEdit> {
SwitchListTile( SwitchListTile(
activeColor: Theme.of(context).accentColor, activeColor: Theme.of(context).accentColor,
title: Text(localization.sendEmail), title: Text(localization.sendEmail),
value: viewModel.uiState.emailPayment, value: viewModel.prefState.emailPayment,
subtitle: Text(localization.emailReceipt), subtitle: Text(localization.emailReceipt),
onChanged: (value) => viewModel.onEmailChanged(value), onChanged: (value) => viewModel.onEmailChanged(value),
), ),

View File

@ -9,8 +9,8 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/invoice_model.dart'; import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart'; import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
import 'package:invoiceninja_flutter/ui/payment/payment_screen.dart'; import 'package:invoiceninja_flutter/ui/payment/payment_screen.dart';
import 'package:invoiceninja_flutter/ui/payment/view/payment_view_vm.dart'; import 'package:invoiceninja_flutter/ui/payment/view/payment_view_vm.dart';
@ -50,7 +50,7 @@ class PaymentEditVM {
@required this.onChanged, @required this.onChanged,
@required this.onSavePressed, @required this.onSavePressed,
@required this.onEmailChanged, @required this.onEmailChanged,
@required this.uiState, @required this.prefState,
@required this.invoiceMap, @required this.invoiceMap,
@required this.invoiceList, @required this.invoiceList,
@required this.clientMap, @required this.clientMap,
@ -71,7 +71,7 @@ class PaymentEditVM {
isDirty: payment.isNew, isDirty: payment.isNew,
origPayment: state.paymentState.map[payment.id], origPayment: state.paymentState.map[payment.id],
payment: payment, payment: payment,
uiState: state.uiState, prefState: state.prefState,
staticState: state.staticState, staticState: state.staticState,
invoiceMap: state.invoiceState.map, invoiceMap: state.invoiceState.map,
invoiceList: state.invoiceState.list, invoiceList: state.invoiceState.list,
@ -134,7 +134,7 @@ class PaymentEditVM {
final Function(BuildContext) onCancelPressed; final Function(BuildContext) onCancelPressed;
final Function(bool) onEmailChanged; final Function(bool) onEmailChanged;
final BuiltMap<String, InvoiceEntity> invoiceMap; final BuiltMap<String, InvoiceEntity> invoiceMap;
final UIState uiState; final PrefState prefState;
final BuiltList<String> invoiceList; final BuiltList<String> invoiceList;
final BuiltMap<String, ClientEntity> clientMap; final BuiltMap<String, ClientEntity> clientMap;
final BuiltList<String> clientList; final BuiltList<String> clientList;

View File

@ -77,7 +77,7 @@ class PaymentList extends StatelessWidget {
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = final longPressIsSelection =
state.uiState.longPressSelectionIsDefault ?? state.prefState.longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {
handlePaymentAction(context, [payment], handlePaymentAction(context, [payment],

View File

@ -64,7 +64,7 @@ class ProductList extends StatelessWidget {
onTap: () => viewModel.onProductTap(context, product), onTap: () => viewModel.onProductTap(context, product),
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = final longPressIsSelection =
store.state.uiState.longPressSelectionIsDefault ?? true; store.state.prefState.longPressSelectionIsDefault ?? true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {
handleProductAction( handleProductAction(
context, [product], EntityAction.toggleMultiselect); context, [product], EntityAction.toggleMultiselect);

View File

@ -77,7 +77,7 @@ class ProjectList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -90,7 +90,7 @@ class ProjectViewVM {
onTasksPressed: (BuildContext context, {bool longPress = false}) { onTasksPressed: (BuildContext context, {bool longPress = false}) {
if (longPress && project.isActive && client.isActive) { if (longPress && project.isActive && client.isActive) {
store.dispatch(EditTask( store.dispatch(EditTask(
task: TaskEntity(isRunning: state.uiState.autoStartTasks) task: TaskEntity(isRunning: state.prefState.autoStartTasks)
.rebuild((b) => b .rebuild((b) => b
..projectId = project.id ..projectId = project.id
..clientId = project.clientId), ..clientId = project.clientId),
@ -104,7 +104,7 @@ class ProjectViewVM {
onAddTaskPressed: (context) => store.dispatch(EditTask( onAddTaskPressed: (context) => store.dispatch(EditTask(
context: context, context: context,
task: task:
TaskEntity(isRunning: state.uiState.autoStartTasks).rebuild((b) => b TaskEntity(isRunning: state.prefState.autoStartTasks).rebuild((b) => b
..projectId = project.id ..projectId = project.id
..clientId = project.clientId), ..clientId = project.clientId),
force: true, force: true,

View File

@ -31,7 +31,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
final state = viewModel.state; final state = viewModel.state;
final uiState = state.uiState; final prefState = state.prefState;
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
@ -52,7 +52,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
children: <Widget>[ children: <Widget>[
AppDropdownButton<AppLayout>( AppDropdownButton<AppLayout>(
labelText: localization.layout, labelText: localization.layout,
value: viewModel.state.uiState.layout, value: viewModel.state.prefState.layout,
onChanged: (dynamic value) => onChanged: (dynamic value) =>
viewModel.onLayoutChanged(context, value), viewModel.onLayoutChanged(context, value),
items: [ items: [
@ -66,10 +66,10 @@ class _DeviceSettingsState extends State<DeviceSettings> {
), ),
], ],
), ),
if (state.uiState.layout == AppLayout.tablet) ...[ if (state.prefState.layout == AppLayout.tablet) ...[
AppDropdownButton<AppSidebarMode>( AppDropdownButton<AppSidebarMode>(
labelText: localization.menuSidebar, labelText: localization.menuSidebar,
value: state.uiState.menuSidebarMode, value: state.prefState.menuSidebarMode,
items: [ items: [
DropdownMenuItem( DropdownMenuItem(
child: Text(localization.showOrHide), child: Text(localization.showOrHide),
@ -91,7 +91,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
), ),
AppDropdownButton<AppSidebarMode>( AppDropdownButton<AppSidebarMode>(
labelText: localization.historySidebar, labelText: localization.historySidebar,
value: state.uiState.historySidebarMode, value: state.prefState.historySidebarMode,
items: [ items: [
DropdownMenuItem( DropdownMenuItem(
child: Text(localization.showOrHide), child: Text(localization.showOrHide),
@ -108,7 +108,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
], ],
FormColorPicker( FormColorPicker(
labelText: localization.accentColor, labelText: localization.accentColor,
initialValue: uiState.accentColor, initialValue: state.accentColor,
showClear: false, showClear: false,
onSelected: (value) => onSelected: (value) =>
viewModel.onAccentColorChanged(context, value), viewModel.onAccentColorChanged(context, value),
@ -119,7 +119,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
children: <Widget>[ children: <Widget>[
SwitchListTile( SwitchListTile(
title: Text(AppLocalization.of(context).darkMode), title: Text(AppLocalization.of(context).darkMode),
value: uiState.enableDarkMode, value: prefState.enableDarkMode,
onChanged: (value) => onChanged: (value) =>
viewModel.onDarkModeChanged(context, value), viewModel.onDarkModeChanged(context, value),
secondary: Icon(kIsWeb secondary: Icon(kIsWeb
@ -130,12 +130,12 @@ class _DeviceSettingsState extends State<DeviceSettings> {
SwitchListTile( SwitchListTile(
title: Text(AppLocalization.of(context) title: Text(AppLocalization.of(context)
.longPressSelectionIsDefault), .longPressSelectionIsDefault),
value: uiState.longPressSelectionIsDefault, value: prefState.longPressSelectionIsDefault,
onChanged: (value) => onChanged: (value) =>
viewModel.onLongPressSelectionIsDefault(context, value), viewModel.onLongPressSelectionIsDefault(context, value),
secondary: Icon(kIsWeb secondary: Icon(kIsWeb
? Icons.check_box ? Icons.check_box
: FontAwesomeIcons.checkSquare), : FontAwesomeIcons.solidCheckSquare),
activeColor: Theme.of(context).accentColor, activeColor: Theme.of(context).accentColor,
), ),
FutureBuilder( FutureBuilder(
@ -145,10 +145,10 @@ class _DeviceSettingsState extends State<DeviceSettings> {
return SwitchListTile( return SwitchListTile(
title: Text(AppLocalization.of(context) title: Text(AppLocalization.of(context)
.biometricAuthentication), .biometricAuthentication),
value: uiState.requireAuthentication, value: prefState.requireAuthentication,
onChanged: (value) => viewModel onChanged: (value) => viewModel
.onRequireAuthenticationChanged(context, value), .onRequireAuthenticationChanged(context, value),
secondary: Icon(uiState.requireAuthentication secondary: Icon(prefState.requireAuthentication
? FontAwesomeIcons.lock ? FontAwesomeIcons.lock
: FontAwesomeIcons.unlockAlt), : FontAwesomeIcons.unlockAlt),
activeColor: Theme.of(context).accentColor, activeColor: Theme.of(context).accentColor,
@ -163,7 +163,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
? SwitchListTile( ? SwitchListTile(
title: title:
Text(AppLocalization.of(context).autoStartTasks), Text(AppLocalization.of(context).autoStartTasks),
value: uiState.autoStartTasks, value: prefState.autoStartTasks,
onChanged: (value) => onChanged: (value) =>
viewModel.onAutoStartTasksChanged(context, value), viewModel.onAutoStartTasksChanged(context, value),
secondary: Icon( secondary: Icon(

View File

@ -76,7 +76,7 @@ class TaskList extends StatelessWidget {
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = final longPressIsSelection =
state.uiState.longPressSelectionIsDefault ?? state.prefState.longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {
handleTaskAction(context, [task], handleTaskAction(context, [task],

View File

@ -143,7 +143,7 @@ class TaskScreen extends StatelessWidget {
onPressed: () { onPressed: () {
store.dispatch(EditTask( store.dispatch(EditTask(
task: TaskEntity( task: TaskEntity(
isRunning: store.state.uiState.autoStartTasks) isRunning: store.state.prefState.autoStartTasks)
.rebuild((b) => b .rebuild((b) => b
..clientId = ..clientId =
store.state.taskListState.filterEntityId), store.state.taskListState.filterEntityId),

View File

@ -63,7 +63,7 @@ class TaxRateList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -142,7 +142,7 @@ class UserViewVM {
if (longPress && user.isActive) { if (longPress && user.isActive) {
store.dispatch(EditTask( store.dispatch(EditTask(
context: context, context: context,
task: TaskEntity(isRunning: state.uiState.autoStartTasks))); task: TaskEntity(isRunning: state.prefState.autoStartTasks)));
} else { } else {
store.dispatch(FilterTasksByEntity( store.dispatch(FilterTasksByEntity(
entityId: user.id, entityType: EntityType.user)); entityId: user.id, entityType: EntityType.user));
@ -154,7 +154,7 @@ class UserViewVM {
store.dispatch(EditExpense( store.dispatch(EditExpense(
context: context, context: context,
expense: ExpenseEntity( expense: ExpenseEntity(
company: state.company, uiState: state.uiState))); company: state.company, prefState: state.prefState)));
} else { } else {
store.dispatch(FilterExpensesByEntity( store.dispatch(FilterExpensesByEntity(
entityId: user.id, entityType: EntityType.user)); entityId: user.id, entityType: EntityType.user));

View File

@ -62,7 +62,7 @@ class VendorList extends StatelessWidget {
} }
}, },
onLongPress: () async { onLongPress: () async {
final longPressIsSelection = store.state.uiState final longPressIsSelection = store.state.prefState
.longPressSelectionIsDefault ?? .longPressSelectionIsDefault ??
true; true;
if (longPressIsSelection && !isInMultiselect) { if (longPressIsSelection && !isInMultiselect) {

View File

@ -33,7 +33,7 @@ AppLayout calculateLayout(BuildContext context) {
} }
AppLayout getLayout(BuildContext context) => AppLayout getLayout(BuildContext context) =>
StoreProvider.of<AppState>(context).state.uiState.layout ?? StoreProvider.of<AppState>(context).state.prefState.layout ??
AppLayout.mobile; AppLayout.mobile;
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile; bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;
@ -43,7 +43,7 @@ bool isTablet(BuildContext context) => getLayout(context) == AppLayout.tablet;
bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop; bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop;
bool isDarkMode(BuildContext context) => bool isDarkMode(BuildContext context) =>
StoreProvider.of<AppState>(context).state.uiState.enableDarkMode; StoreProvider.of<AppState>(context).state.prefState.enableDarkMode;
bool isSelfHosted(BuildContext context) => bool isSelfHosted(BuildContext context) =>
StoreProvider.of<AppState>(context).state.isSelfHosted; StoreProvider.of<AppState>(context).state.isSelfHosted;

View File

@ -16,7 +16,7 @@ class ViewStubList implements PersistUI {
final bool force; final bool force;
} }
class ViewStub implements PersistUI { class ViewStub implements PersistUI, PersistPrefs {
ViewStub({ ViewStub({
@required this.stubId, @required this.stubId,
@required this.context, @required this.context,
@ -28,7 +28,7 @@ class ViewStub implements PersistUI {
final bool force; final bool force;
} }
class EditStub implements PersistUI { class EditStub implements PersistUI, PersistPrefs {
EditStub( EditStub(
{@required this.stub, {@required this.stub,
@required this.context, @required this.context,