diff --git a/lib/constants.dart b/lib/constants.dart index 5877c930d..e9a87506b 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; // 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 kAppUrl = 'https://admin.invoiceninja.com'; //const String kAppUrl = 'https://staging.invoicing.co'; @@ -71,6 +71,8 @@ const int kMinMajorAppVersion = 0; const int kMinMinorAppVersion = 0; const int kMinPatchAppVersion = 0; +const int kMaxNumberOfCompanies = 10; +const int kMaxNumberOfHistory = 50; const int kMaxRecordsPerApiPage = 5000; const int kMillisecondsToRefreshData = 1000 * 60 * 15; // 15 minutes const int kMillisecondsToRefreshActivities = 1000 * 60 * 60 * 24; // 1 day diff --git a/lib/data/models/expense_model.dart b/lib/data/models/expense_model.dart index d71da3752..c289ca633 100644 --- a/lib/data/models/expense_model.dart +++ b/lib/data/models/expense_model.dart @@ -4,7 +4,7 @@ import 'package:built_value/serializer.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/data/models/entities.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'; part 'expense_model.g.dart'; @@ -70,7 +70,7 @@ abstract class ExpenseEntity extends Object factory ExpenseEntity( {String id, CompanyEntity company, - UIState uiState, + PrefState prefState, VendorEntity vendor, ClientEntity client}) { return _$ExpenseEntity._( @@ -79,7 +79,7 @@ abstract class ExpenseEntity extends Object privateNotes: '', publicNotes: '', shouldBeInvoiced: false, - invoiceDocuments: uiState?.prefState?.addDocumentsToInvoice ?? false, + invoiceDocuments: prefState?.addDocumentsToInvoice ?? false, transactionId: '', transactionReference: '', bankId: '', diff --git a/lib/main.dart b/lib/main.dart index 3a16399cc..7cc835830 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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/task/task_middleware.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/ui/app/app_builder.dart'; import 'package:invoiceninja_flutter/ui/app/main_screen.dart'; @@ -156,10 +155,7 @@ Future _initialState(bool isTesting) async { } return AppState( - uiState: UIState( - isTesting: isTesting, - prefState: prefState, - ), + prefState: prefState, ); } @@ -216,7 +212,7 @@ class InvoiceNinjaAppState extends State { @override void didChangeDependencies() { final state = widget.store.state; - if (state.uiState.requireAuthentication && !_authenticated) { + if (state.prefState.requireAuthentication && !_authenticated) { _authenticate(); } super.didChangeDependencies(); @@ -231,7 +227,7 @@ class InvoiceNinjaAppState extends State { Intl.defaultLocale = localeSelector(state); final localization = AppLocalization(Locale(Intl.defaultLocale)); final accentColor = - convertHexStringToColor(state.uiState.accentColor) ?? + convertHexStringToColor(state.accentColor) ?? Colors.lightBlueAccent; return MaterialApp( supportedLocales: kLanguages @@ -245,7 +241,7 @@ class InvoiceNinjaAppState extends State { GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate ], - home: state.uiState.requireAuthentication && !_authenticated + home: state.prefState.requireAuthentication && !_authenticated ? Material( color: Colors.grey, child: Column( @@ -280,7 +276,7 @@ class InvoiceNinjaAppState extends State { ) : InitScreen(), locale: AppLocalization.createLocale(localeSelector(state)), - theme: state.uiState.enableDarkMode + theme: state.prefState.enableDarkMode ? ThemeData( brightness: Brightness.dark, accentColor: accentColor, diff --git a/lib/redux/app/app_middleware.dart b/lib/redux/app/app_middleware.dart index c49a0f33e..25fc46c70 100644 --- a/lib/redux/app/app_middleware.dart +++ b/lib/redux/app/app_middleware.dart @@ -196,11 +196,12 @@ Middleware _createLoadState( companyStates.add(await companyRepositories[i].loadCompanyState(i)); } - final AppState appState = AppState().rebuild((b) => b - ..authState.replace(authState) - ..uiState.replace(uiState) - ..staticState.replace(staticState) - ..userCompanyStates.replace(companyStates)); + final AppState appState = AppState(prefState: store.state.prefState) + .rebuild((b) => b + ..authState.replace(authState) + ..uiState.replace(uiState) + ..staticState.replace(staticState) + ..userCompanyStates.replace(companyStates)); AppBuilder.of(action.context).rebuild(); store.dispatch(LoadStateSuccess(appState)); @@ -216,7 +217,7 @@ Middleware _createLoadState( uiState.currentRoute.isNotEmpty) { final NavigatorState navigator = Navigator.of(action.context); final routes = _getRoutes(appState); - if (uiState.layout == AppLayout.mobile) { + if (appState.prefState.layout == AppLayout.mobile) { bool isFirst = true; routes.forEach((route) { if (isFirst) { @@ -249,7 +250,7 @@ Middleware _createLoadState( final Completer completer = Completer(); completer.future.then((_) { final layout = calculateLayout(action.context); - if (store.state.uiState.layout == AppLayout.tablet && + if (store.state.prefState.layout == AppLayout.tablet && layout == AppLayout.mobile) { store.dispatch(UserSettingsChanged(layout: layout)); store.dispatch(ViewDashboard(context: action.context)); @@ -356,8 +357,8 @@ Middleware _createPersistPrefs() { return; } - final string = serializers.serializeWith( - PrefState.serializer, store.state.uiState.prefState); + final string = + serializers.serializeWith(PrefState.serializer, store.state.prefState); SharedPreferences.getInstance() .then((prefs) => prefs.setString(kSharedPrefs, json.encode(string))); diff --git a/lib/redux/app/app_reducer.dart b/lib/redux/app/app_reducer.dart index 9b058bba4..c5e1d8080 100644 --- a/lib/redux/app/app_reducer.dart +++ b/lib/redux/app/app_reducer.dart @@ -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/quote/quote_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:redux/redux.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 ..authState .replace(state.authState.rebuild((b) => b..isAuthenticated = false)) - //..uiState.enableDarkMode = state.uiState.enableDarkMode - ..uiState.isTesting = state.uiState.isTesting); + ..prefState.replace(state.prefState) + ..isTesting = state.isTesting); } else if (action is LoadStateSuccess) { return action.state.rebuild((b) => b ..isLoading = false @@ -41,7 +42,9 @@ AppState appReducer(AppState state, dynamic action) { ..staticState.replace(staticReducer(state.staticState, action)) ..userCompanyStates[state.uiState.selectedCompanyIndex] = companyReducer( 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([ diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index 49866efa8..c0f1a7b9f 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -1,6 +1,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.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/redux/auth/auth_state.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/ui/entity_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/vendor/vendor_selectors.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_state.dart'; @@ -51,19 +53,22 @@ part 'app_state.g.dart'; abstract class AppState implements Built { factory AppState({ - UIState uiState, + PrefState prefState, }) { return _$AppState._( isLoading: false, isSaving: false, + isTesting: false, serverVersion: '', lastError: '', authState: AuthState(), staticState: StaticState(), - userCompanyStates: BuiltList(List.generate(10, (i) => i + 1) - .map((index) => UserCompanyState()) - .toList()), - uiState: uiState ?? UIState(), + userCompanyStates: BuiltList( + List.generate(kMaxNumberOfCompanies, (i) => i + 1) + .map((index) => UserCompanyState()) + .toList()), + uiState: UIState(), + prefState: prefState ?? PrefState(), ); } @@ -73,6 +78,8 @@ abstract class AppState implements Built { bool get isSaving; + bool get isTesting; + String get lastError; String get serverVersion; @@ -81,6 +88,8 @@ abstract class AppState implements Built { StaticState get staticState; + PrefState get prefState; + UIState get uiState; BuiltList get userCompanyStates; @@ -110,6 +119,12 @@ abstract class AppState implements Built { Credentials get credentials => Credentials(token: userCompanyState.token.token, url: authState.url); + String get accentColor => + prefState.companyPrefs[uiState.selectedCompanyIndex].accentColor; + + BuiltList get historyList => + prefState.companyPrefs[uiState.selectedCompanyIndex].historyList; + BuiltMap getEntityMap(EntityType type) { switch (type) { case EntityType.product: diff --git a/lib/redux/app/app_state.g.dart b/lib/redux/app/app_state.g.dart index c20203130..bcfcfa7d9 100644 --- a/lib/redux/app/app_state.g.dart +++ b/lib/redux/app/app_state.g.dart @@ -24,6 +24,9 @@ class _$AppStateSerializer implements StructuredSerializer { 'isSaving', serializers.serialize(object.isSaving, specifiedType: const FullType(bool)), + 'isTesting', + serializers.serialize(object.isTesting, + specifiedType: const FullType(bool)), 'lastError', serializers.serialize(object.lastError, specifiedType: const FullType(String)), @@ -36,6 +39,9 @@ class _$AppStateSerializer implements StructuredSerializer { 'staticState', serializers.serialize(object.staticState, specifiedType: const FullType(StaticState)), + 'prefState', + serializers.serialize(object.prefState, + specifiedType: const FullType(PrefState)), 'uiState', serializers.serialize(object.uiState, specifiedType: const FullType(UIState)), @@ -67,6 +73,10 @@ class _$AppStateSerializer implements StructuredSerializer { result.isSaving = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; break; + case 'isTesting': + result.isTesting = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool; + break; case 'lastError': result.lastError = serializers.deserialize(value, specifiedType: const FullType(String)) as String; @@ -83,6 +93,10 @@ class _$AppStateSerializer implements StructuredSerializer { result.staticState.replace(serializers.deserialize(value, specifiedType: const FullType(StaticState)) as StaticState); break; + case 'prefState': + result.prefState.replace(serializers.deserialize(value, + specifiedType: const FullType(PrefState)) as PrefState); + break; case 'uiState': result.uiState.replace(serializers.deserialize(value, specifiedType: const FullType(UIState)) as UIState); @@ -106,6 +120,8 @@ class _$AppState extends AppState { @override final bool isSaving; @override + final bool isTesting; + @override final String lastError; @override final String serverVersion; @@ -114,6 +130,8 @@ class _$AppState extends AppState { @override final StaticState staticState; @override + final PrefState prefState; + @override final UIState uiState; @override final BuiltList userCompanyStates; @@ -124,10 +142,12 @@ class _$AppState extends AppState { _$AppState._( {this.isLoading, this.isSaving, + this.isTesting, this.lastError, this.serverVersion, this.authState, this.staticState, + this.prefState, this.uiState, this.userCompanyStates}) : super._() { @@ -137,6 +157,9 @@ class _$AppState extends AppState { if (isSaving == null) { throw new BuiltValueNullFieldError('AppState', 'isSaving'); } + if (isTesting == null) { + throw new BuiltValueNullFieldError('AppState', 'isTesting'); + } if (lastError == null) { throw new BuiltValueNullFieldError('AppState', 'lastError'); } @@ -149,6 +172,9 @@ class _$AppState extends AppState { if (staticState == null) { throw new BuiltValueNullFieldError('AppState', 'staticState'); } + if (prefState == null) { + throw new BuiltValueNullFieldError('AppState', 'prefState'); + } if (uiState == null) { throw new BuiltValueNullFieldError('AppState', 'uiState'); } @@ -170,10 +196,12 @@ class _$AppState extends AppState { return other is AppState && isLoading == other.isLoading && isSaving == other.isSaving && + isTesting == other.isTesting && lastError == other.lastError && serverVersion == other.serverVersion && authState == other.authState && staticState == other.staticState && + prefState == other.prefState && uiState == other.uiState && userCompanyStates == other.userCompanyStates; } @@ -185,11 +213,17 @@ class _$AppState extends AppState { $jc( $jc( $jc( - $jc($jc($jc(0, isLoading.hashCode), isSaving.hashCode), - lastError.hashCode), - serverVersion.hashCode), - authState.hashCode), - staticState.hashCode), + $jc( + $jc( + $jc( + $jc($jc(0, isLoading.hashCode), + isSaving.hashCode), + isTesting.hashCode), + lastError.hashCode), + serverVersion.hashCode), + authState.hashCode), + staticState.hashCode), + prefState.hashCode), uiState.hashCode), userCompanyStates.hashCode)); } @@ -206,6 +240,10 @@ class AppStateBuilder implements Builder { bool get isSaving => _$this._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 get lastError => _$this._lastError; set lastError(String lastError) => _$this._lastError = lastError; @@ -226,6 +264,11 @@ class AppStateBuilder implements Builder { set staticState(StaticStateBuilder staticState) => _$this._staticState = staticState; + PrefStateBuilder _prefState; + PrefStateBuilder get prefState => + _$this._prefState ??= new PrefStateBuilder(); + set prefState(PrefStateBuilder prefState) => _$this._prefState = prefState; + UIStateBuilder _uiState; UIStateBuilder get uiState => _$this._uiState ??= new UIStateBuilder(); set uiState(UIStateBuilder uiState) => _$this._uiState = uiState; @@ -242,10 +285,12 @@ class AppStateBuilder implements Builder { if (_$v != null) { _isLoading = _$v.isLoading; _isSaving = _$v.isSaving; + _isTesting = _$v.isTesting; _lastError = _$v.lastError; _serverVersion = _$v.serverVersion; _authState = _$v.authState?.toBuilder(); _staticState = _$v.staticState?.toBuilder(); + _prefState = _$v.prefState?.toBuilder(); _uiState = _$v.uiState?.toBuilder(); _userCompanyStates = _$v.userCompanyStates?.toBuilder(); _$v = null; @@ -274,10 +319,12 @@ class AppStateBuilder implements Builder { new _$AppState._( isLoading: isLoading, isSaving: isSaving, + isTesting: isTesting, lastError: lastError, serverVersion: serverVersion, authState: authState.build(), staticState: staticState.build(), + prefState: prefState.build(), uiState: uiState.build(), userCompanyStates: userCompanyStates.build()); } catch (_) { @@ -287,6 +334,8 @@ class AppStateBuilder implements Builder { authState.build(); _$failedField = 'staticState'; staticState.build(); + _$failedField = 'prefState'; + prefState.build(); _$failedField = 'uiState'; uiState.build(); _$failedField = 'userCompanyStates'; diff --git a/lib/redux/client/client_actions.dart b/lib/redux/client/client_actions.dart index 0dc489a4a..61b16fff4 100644 --- a/lib/redux/client/client_actions.dart +++ b/lib/redux/client/client_actions.dart @@ -19,7 +19,7 @@ class ViewClientList implements PersistUI { final bool force; } -class ViewClient implements PersistUI { +class ViewClient implements PersistUI, PersistPrefs { ViewClient({ @required this.clientId, @required this.context, @@ -31,7 +31,7 @@ class ViewClient implements PersistUI { final bool force; } -class EditClient implements PersistUI { +class EditClient implements PersistUI, PersistPrefs { EditClient( {@required this.client, @required this.context, @@ -303,7 +303,7 @@ void handleClientAction( case EntityAction.newExpense: store.dispatch(EditExpense( expense: ExpenseEntity( - company: company, client: client, uiState: state.uiState), + company: company, client: client, prefState: state.prefState), context: context)); break; case EntityAction.enterPayment: diff --git a/lib/redux/company_gateway/company_gateway_actions.dart b/lib/redux/company_gateway/company_gateway_actions.dart index fe3f0ec15..7e28e7c9f 100644 --- a/lib/redux/company_gateway/company_gateway_actions.dart +++ b/lib/redux/company_gateway/company_gateway_actions.dart @@ -17,7 +17,7 @@ class ViewCompanyGatewayList implements PersistUI { final bool force; } -class ViewCompanyGateway implements PersistUI { +class ViewCompanyGateway implements PersistUI, PersistPrefs { ViewCompanyGateway({ @required this.companyGatewayId, @required this.context, @@ -29,7 +29,7 @@ class ViewCompanyGateway implements PersistUI { final bool force; } -class EditCompanyGateway implements PersistUI { +class EditCompanyGateway implements PersistUI, PersistPrefs { EditCompanyGateway( {@required this.companyGateway, @required this.context, diff --git a/lib/redux/expense/expense_actions.dart b/lib/redux/expense/expense_actions.dart index 0b47f104d..240aeae60 100644 --- a/lib/redux/expense/expense_actions.dart +++ b/lib/redux/expense/expense_actions.dart @@ -19,7 +19,7 @@ class ViewExpenseList implements PersistUI { final bool force; } -class ViewExpense implements PersistUI { +class ViewExpense implements PersistUI, PersistPrefs { ViewExpense({ @required this.expenseId, @required this.context, @@ -31,7 +31,7 @@ class ViewExpense implements PersistUI { final bool force; } -class EditExpense implements PersistUI { +class EditExpense implements PersistUI, PersistPrefs { EditExpense( {@required this.expense, @required this.context, diff --git a/lib/redux/group/group_actions.dart b/lib/redux/group/group_actions.dart index d2267df55..2f4c8d1da 100644 --- a/lib/redux/group/group_actions.dart +++ b/lib/redux/group/group_actions.dart @@ -20,7 +20,7 @@ class ViewGroupList implements PersistUI { final bool force; } -class ViewGroup implements PersistUI { +class ViewGroup implements PersistUI, PersistPrefs { ViewGroup({ @required this.groupId, @required this.context, @@ -32,7 +32,7 @@ class ViewGroup implements PersistUI { final bool force; } -class EditGroup implements PersistUI { +class EditGroup implements PersistUI, PersistPrefs { EditGroup( {@required this.group, @required this.context, diff --git a/lib/redux/invoice/invoice_actions.dart b/lib/redux/invoice/invoice_actions.dart index 20d1368d5..15d6247a9 100644 --- a/lib/redux/invoice/invoice_actions.dart +++ b/lib/redux/invoice/invoice_actions.dart @@ -20,7 +20,7 @@ class ViewInvoiceList implements PersistUI { final bool force; } -class ViewInvoice implements PersistUI { +class ViewInvoice implements PersistUI, PersistPrefs { ViewInvoice({this.invoiceId, this.context, this.force = false}); final String invoiceId; @@ -28,7 +28,7 @@ class ViewInvoice implements PersistUI { final bool force; } -class EditInvoice implements PersistUI { +class EditInvoice implements PersistUI, PersistPrefs { EditInvoice( {this.invoice, this.context, diff --git a/lib/redux/payment/payment_actions.dart b/lib/redux/payment/payment_actions.dart index 75da32880..74863eee3 100644 --- a/lib/redux/payment/payment_actions.dart +++ b/lib/redux/payment/payment_actions.dart @@ -16,7 +16,7 @@ class ViewPaymentList implements PersistUI { final bool force; } -class ViewPayment implements PersistUI { +class ViewPayment implements PersistUI, PersistPrefs { ViewPayment({ @required this.paymentId, @required this.context, @@ -28,7 +28,7 @@ class ViewPayment implements PersistUI { final bool force; } -class EditPayment implements PersistUI { +class EditPayment implements PersistUI, PersistPrefs { EditPayment( {@required this.payment, @required this.context, diff --git a/lib/redux/payment/payment_middleware.dart b/lib/redux/payment/payment_middleware.dart index cb34a5be1..856c4fee5 100644 --- a/lib/redux/payment/payment_middleware.dart +++ b/lib/redux/payment/payment_middleware.dart @@ -193,7 +193,7 @@ Middleware _savePayment(PaymentRepository repository) { final action = dynamicAction as SavePaymentRequest; final PaymentEntity payment = action.payment; final bool sendEmail = - payment.isNew ? store.state.uiState.emailPayment : false; + payment.isNew ? store.state.prefState.emailPayment : false; repository .saveData(store.state.credentials, action.payment, sendEmail: sendEmail) .then((PaymentEntity payment) { diff --git a/lib/redux/product/product_actions.dart b/lib/redux/product/product_actions.dart index 564a612a4..f1327420a 100644 --- a/lib/redux/product/product_actions.dart +++ b/lib/redux/product/product_actions.dart @@ -18,7 +18,7 @@ class ViewProductList implements PersistUI { final bool force; } -class ViewProduct implements PersistUI { +class ViewProduct implements PersistUI, PersistPrefs { ViewProduct( {@required this.productId, @required this.context, this.force = false}); @@ -27,7 +27,7 @@ class ViewProduct implements PersistUI { final bool force; } -class EditProduct implements PersistUI { +class EditProduct implements PersistUI, PersistPrefs { EditProduct( {@required this.product, @required this.context, diff --git a/lib/redux/project/project_actions.dart b/lib/redux/project/project_actions.dart index 2645b138d..87e994a74 100644 --- a/lib/redux/project/project_actions.dart +++ b/lib/redux/project/project_actions.dart @@ -20,7 +20,7 @@ class ViewProjectList implements PersistUI { final bool force; } -class ViewProject implements PersistUI { +class ViewProject implements PersistUI, PersistPrefs { ViewProject({ @required this.projectId, @required this.context, @@ -32,7 +32,7 @@ class ViewProject implements PersistUI { final bool force; } -class EditProject implements PersistUI { +class EditProject implements PersistUI, PersistPrefs { EditProject( {@required this.project, @required this.context, @@ -270,7 +270,7 @@ void handleProjectAction( break; case EntityAction.newTask: store.dispatch(EditTask( - task: TaskEntity(isRunning: state.uiState.autoStartTasks) + task: TaskEntity(isRunning: state.prefState.autoStartTasks) .rebuild((b) => b ..projectId = project.id ..clientId = project.clientId), diff --git a/lib/redux/quote/quote_actions.dart b/lib/redux/quote/quote_actions.dart index 6ec044e35..aa9fb3daf 100644 --- a/lib/redux/quote/quote_actions.dart +++ b/lib/redux/quote/quote_actions.dart @@ -20,7 +20,7 @@ class ViewQuoteList implements PersistUI { final bool force; } -class ViewQuote implements PersistUI { +class ViewQuote implements PersistUI, PersistPrefs { ViewQuote({this.quoteId, this.context, this.force = false}); final String quoteId; @@ -28,7 +28,7 @@ class ViewQuote implements PersistUI { final bool force; } -class EditQuote implements PersistUI { +class EditQuote implements PersistUI, PersistPrefs { EditQuote( {this.quote, this.context, diff --git a/lib/redux/task/task_actions.dart b/lib/redux/task/task_actions.dart index de01a26c0..a226bc112 100644 --- a/lib/redux/task/task_actions.dart +++ b/lib/redux/task/task_actions.dart @@ -21,7 +21,7 @@ class ViewTaskList implements PersistUI { final bool force; } -class ViewTask implements PersistUI { +class ViewTask implements PersistUI, PersistPrefs { ViewTask({ @required this.taskId, @required this.context, @@ -33,7 +33,7 @@ class ViewTask implements PersistUI { final bool force; } -class EditTask implements PersistUI { +class EditTask implements PersistUI, PersistPrefs { EditTask( {this.task, this.taskTime, diff --git a/lib/redux/ui/pref_reducer.dart b/lib/redux/ui/pref_reducer.dart index 2c8d1e58e..54ac85c84 100644 --- a/lib/redux/ui/pref_reducer.dart +++ b/lib/redux/ui/pref_reducer.dart @@ -1,5 +1,6 @@ import 'dart:math'; 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/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; @@ -353,6 +354,6 @@ BuiltList _addToHistory( } else { return list.rebuild((b) => b ..insert(0, record) - ..sublist(0, min(200, list.length + 1))); + ..sublist(0, min(kMaxNumberOfHistory, list.length + 1))); } } diff --git a/lib/redux/ui/pref_state.dart b/lib/redux/ui/pref_state.dart index 557c33ff0..8fcb8697d 100644 --- a/lib/redux/ui/pref_state.dart +++ b/lib/redux/ui/pref_state.dart @@ -32,9 +32,10 @@ abstract class PrefState implements Built { autoStartTasks: false, longPressSelectionIsDefault: longPressSelectionIsDefault ?? false, addDocumentsToInvoice: false, - companyPrefs: BuiltList(List.generate(10, (i) => i + 1) - .map((index) => CompanyPrefState()) - .toList()), + companyPrefs: BuiltList( + List.generate(kMaxNumberOfCompanies, (i) => i + 1) + .map((index) => CompanyPrefState()) + .toList()), ); } @@ -64,6 +65,12 @@ abstract class PrefState implements Built { BuiltList get companyPrefs; + bool get isMenuFloated => + layout == AppLayout.mobile || menuSidebarMode == AppSidebarMode.float; + + bool get isHistoryFloated => + layout == AppLayout.mobile || historySidebarMode == AppSidebarMode.float; + static Serializer get serializer => _$prefStateSerializer; } diff --git a/lib/redux/ui/ui_reducer.dart b/lib/redux/ui/ui_reducer.dart index 06ccd9998..c1c809e92 100644 --- a/lib/redux/ui/ui_reducer.dart +++ b/lib/redux/ui/ui_reducer.dart @@ -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/settings/settings_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/ui_actions.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) { final currentRoute = currentRouteReducer(state.currentRoute, action); return state.rebuild((b) => b - ..prefState.replace( - prefReducer(state.prefState, action, state.selectedCompanyIndex)) ..filter = filterReducer(state.filter, action) ..filterClearedAt = filterClearedAtReducer(state.filterClearedAt, action) ..selectedCompanyIndex = diff --git a/lib/redux/ui/ui_state.dart b/lib/redux/ui/ui_state.dart index 0f1cdb3cc..5306beb77 100644 --- a/lib/redux/ui/ui_state.dart +++ b/lib/redux/ui/ui_state.dart @@ -1,4 +1,3 @@ -import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.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/invoice/invoice_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/redux/document/document_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'; abstract class UIState implements Built { - factory UIState({ - bool isTesting, - PrefState prefState, - }) { + factory UIState() { return _$UIState._( - prefState: prefState ?? PrefState(), selectedCompanyIndex: 0, filterClearedAt: 0, - isTesting: isTesting ?? false, currentRoute: LoginScreen.route, previousRoute: '', dashboardUIState: DashboardUIState(), @@ -57,10 +50,6 @@ abstract class UIState implements Built { UIState._(); - PrefState get prefState; - - bool get isTesting; - int get selectedCompanyIndex; String get currentRoute; @@ -134,39 +123,5 @@ abstract class UIState implements Built { 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 get historyList => companyPrefState.historyList; - - bool get isMenuFloated => - layout == AppLayout.mobile || prefState.menuSidebarMode == AppSidebarMode.float; - - bool get isHistoryFloated => - layout == AppLayout.mobile || prefState.historySidebarMode == AppSidebarMode.float; - } diff --git a/lib/redux/ui/ui_state.g.dart b/lib/redux/ui/ui_state.g.dart index 1dc02637a..8c1a852fc 100644 --- a/lib/redux/ui/ui_state.g.dart +++ b/lib/redux/ui/ui_state.g.dart @@ -18,12 +18,6 @@ class _$UIStateSerializer implements StructuredSerializer { Iterable serialize(Serializers serializers, UIState object, {FullType specifiedType = FullType.unspecified}) { final result = [ - 'prefState', - serializers.serialize(object.prefState, - specifiedType: const FullType(PrefState)), - 'isTesting', - serializers.serialize(object.isTesting, - specifiedType: const FullType(bool)), 'selectedCompanyIndex', serializers.serialize(object.selectedCompanyIndex, specifiedType: const FullType(int)), @@ -105,14 +99,6 @@ class _$UIStateSerializer implements StructuredSerializer { iterator.moveNext(); final dynamic value = iterator.current; 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': result.selectedCompanyIndex = serializers.deserialize(value, specifiedType: const FullType(int)) as int; @@ -209,10 +195,6 @@ class _$UIStateSerializer implements StructuredSerializer { } class _$UIState extends UIState { - @override - final PrefState prefState; - @override - final bool isTesting; @override final int selectedCompanyIndex; @override @@ -260,9 +242,7 @@ class _$UIState extends UIState { (new UIStateBuilder()..update(updates)).build(); _$UIState._( - {this.prefState, - this.isTesting, - this.selectedCompanyIndex, + {this.selectedCompanyIndex, this.currentRoute, this.previousRoute, this.filter, @@ -284,12 +264,6 @@ class _$UIState extends UIState { this.quoteUIState, this.settingsUIState}) : super._() { - if (prefState == null) { - throw new BuiltValueNullFieldError('UIState', 'prefState'); - } - if (isTesting == null) { - throw new BuiltValueNullFieldError('UIState', 'isTesting'); - } if (selectedCompanyIndex == null) { throw new BuiltValueNullFieldError('UIState', 'selectedCompanyIndex'); } @@ -363,8 +337,6 @@ class _$UIState extends UIState { bool operator ==(Object other) { if (identical(other, this)) return true; return other is UIState && - prefState == other.prefState && - isTesting == other.isTesting && selectedCompanyIndex == other.selectedCompanyIndex && currentRoute == other.currentRoute && previousRoute == other.previousRoute && @@ -408,7 +380,7 @@ class _$UIState extends UIState { $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), filter.hashCode), filterClearedAt.hashCode), @@ -433,8 +405,6 @@ class _$UIState extends UIState { @override String toString() { return (newBuiltValueToStringHelper('UIState') - ..add('prefState', prefState) - ..add('isTesting', isTesting) ..add('selectedCompanyIndex', selectedCompanyIndex) ..add('currentRoute', currentRoute) ..add('previousRoute', previousRoute) @@ -463,15 +433,6 @@ class _$UIState extends UIState { class UIStateBuilder implements Builder { _$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 get selectedCompanyIndex => _$this._selectedCompanyIndex; set selectedCompanyIndex(int selectedCompanyIndex) => @@ -596,8 +557,6 @@ class UIStateBuilder implements Builder { UIStateBuilder get _$this { if (_$v != null) { - _prefState = _$v.prefState?.toBuilder(); - _isTesting = _$v.isTesting; _selectedCompanyIndex = _$v.selectedCompanyIndex; _currentRoute = _$v.currentRoute; _previousRoute = _$v.previousRoute; @@ -643,8 +602,6 @@ class UIStateBuilder implements Builder { try { _$result = _$v ?? new _$UIState._( - prefState: prefState.build(), - isTesting: isTesting, selectedCompanyIndex: selectedCompanyIndex, currentRoute: currentRoute, previousRoute: previousRoute, @@ -669,9 +626,6 @@ class UIStateBuilder implements Builder { } catch (_) { String _$failedField; try { - _$failedField = 'prefState'; - prefState.build(); - _$failedField = 'dashboardUIState'; dashboardUIState.build(); _$failedField = 'productUIState'; diff --git a/lib/redux/user/user_actions.dart b/lib/redux/user/user_actions.dart index 91e7aa9c8..b555db68d 100644 --- a/lib/redux/user/user_actions.dart +++ b/lib/redux/user/user_actions.dart @@ -16,7 +16,7 @@ class ViewUserList implements PersistUI { final bool force; } -class ViewUser implements PersistUI { +class ViewUser implements PersistUI, PersistPrefs { ViewUser({ @required this.userId, @required this.context, @@ -28,7 +28,7 @@ class ViewUser implements PersistUI { final bool force; } -class EditUser implements PersistUI { +class EditUser implements PersistUI, PersistPrefs { EditUser( {@required this.user, @required this.context, diff --git a/lib/redux/vendor/vendor_actions.dart b/lib/redux/vendor/vendor_actions.dart index 3e9824aaf..d67c04e2c 100644 --- a/lib/redux/vendor/vendor_actions.dart +++ b/lib/redux/vendor/vendor_actions.dart @@ -17,7 +17,7 @@ class ViewVendorList implements PersistUI { final bool force; } -class ViewVendor implements PersistUI { +class ViewVendor implements PersistUI, PersistPrefs { ViewVendor({ @required this.vendorId, @required this.context, @@ -29,7 +29,7 @@ class ViewVendor implements PersistUI { final bool force; } -class EditVendor implements PersistUI { +class EditVendor implements PersistUI, PersistPrefs { EditVendor( {@required this.vendor, @required this.context, diff --git a/lib/ui/app/buttons/action_flat_button.dart b/lib/ui/app/buttons/action_flat_button.dart index d75b3849d..98c264e83 100644 --- a/lib/ui/app/buttons/action_flat_button.dart +++ b/lib/ui/app/buttons/action_flat_button.dart @@ -44,7 +44,7 @@ class ActionFlatButton extends StatelessWidget { tooltip, style: TextStyle( color: isDirty - ? (state.uiState.enableDarkMode + ? (state.prefState.enableDarkMode ? Theme.of(context).accentColor : Colors.yellowAccent) : Colors.white), diff --git a/lib/ui/app/history_drawer.dart b/lib/ui/app/history_drawer.dart index 0d1202b2d..ef59d9816 100644 --- a/lib/ui/app/history_drawer.dart +++ b/lib/ui/app/history_drawer.dart @@ -27,11 +27,7 @@ class HistoryDrawer extends StatelessWidget { final state = store.state; final widgets = []; - for (var history in state.uiState.historyList) { - if (widgets.length > 50) { - break; - } - + for (var history in state.historyList) { final entity = state.getEntityMap(history.entityType)[history.id] as BaseEntity; @@ -66,7 +62,7 @@ class HistoryDrawer extends StatelessWidget { automaticallyImplyLeading: false, title: Text(localization.history), actions: [ - if (state.uiState.isHistoryFloated) + if (state.prefState.isHistoryFloated) Builder( builder: (context) => IconButton( icon: Icon(Icons.menu), diff --git a/lib/ui/app/list_filter.dart b/lib/ui/app/list_filter.dart index da12f5f8c..a77dbca33 100644 --- a/lib/ui/app/list_filter.dart +++ b/lib/ui/app/list_filter.dart @@ -45,7 +45,7 @@ class _ListFilterState extends State { return StoreConnector( converter: (Store store) => store.state, builder: (BuildContext context, state) { - final bool enableDarkMode = state.uiState.enableDarkMode; + final bool enableDarkMode = state.prefState.enableDarkMode; return widget.filter == null ? Text('${widget.title ?? ''}') : Container( diff --git a/lib/ui/app/list_scaffold.dart b/lib/ui/app/list_scaffold.dart index 86702f493..45fb4a8e5 100644 --- a/lib/ui/app/list_scaffold.dart +++ b/lib/ui/app/list_scaffold.dart @@ -61,7 +61,7 @@ class ListScaffold extends StatelessWidget { child: IconButton( icon: Icon(Icons.menu), onPressed: () { - if (isMobile(context) || state.uiState.isMenuFloated) { + if (isMobile(context) || state.prefState.isMenuFloated) { Scaffold.of(context).openDrawer(); } else { store.dispatch(UserSettingsChanged(sidebar: AppSidebar.menu)); @@ -78,10 +78,10 @@ class ListScaffold extends StatelessWidget { return false; }, child: Scaffold( - drawer: isMobile(context) || state.uiState.isMenuFloated + drawer: isMobile(context) || state.prefState.isMenuFloated ? MenuDrawerBuilder() : null, - endDrawer: isMobile(context) || state.uiState.isHistoryFloated + endDrawer: isMobile(context) || state.prefState.isHistoryFloated ? HistoryDrawerBuilder() : null, appBar: AppBar( @@ -92,12 +92,12 @@ class ListScaffold extends StatelessWidget { ...appBarActions, if (!showCheckbox && !isSettings && - !state.uiState.isHistoryVisible) + !state.prefState.isHistoryVisible) Builder( builder: (context) => IconButton( icon: Icon(Icons.menu), onPressed: () { - if (isMobile(context) || state.uiState.isHistoryFloated) { + if (isMobile(context) || state.prefState.isHistoryFloated) { Scaffold.of(context).openEndDrawer(); } else { store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history)); diff --git a/lib/ui/app/main_screen.dart b/lib/ui/app/main_screen.dart index ff3847cf8..8a4960b49 100644 --- a/lib/ui/app/main_screen.dart +++ b/lib/ui/app/main_screen.dart @@ -24,6 +24,7 @@ class MainScreen extends StatelessWidget { onInit: (Store store) => store.dispatch(LoadDashboard()), builder: (BuildContext context, Store store) { final uiState = store.state.uiState; + final prefState = store.state.prefState; final mainRoute = '/' + uiState.mainRoute; Widget screen = BlankScreen(); @@ -35,8 +36,8 @@ class MainScreen extends StatelessWidget { child: DashboardScreenBuilder(), flex: 5, ), - if (uiState.isHistoryVisible && - uiState.historySidebarMode == AppSidebarMode.visible) ...[ + if (prefState.isHistoryVisible && + prefState.historySidebarMode == AppSidebarMode.visible) ...[ _CustomDivider(), Expanded( child: HistoryDrawerBuilder(), @@ -124,8 +125,8 @@ class MainScreen extends StatelessWidget { } return Row(children: [ - if (uiState.isMenuVisible && - uiState.menuSidebarMode == AppSidebarMode.visible) ...[ + if (prefState.isMenuVisible && + prefState.menuSidebarMode == AppSidebarMode.visible) ...[ MenuDrawerBuilder(), _CustomDivider(), ], @@ -244,6 +245,7 @@ class SettingsScreens extends StatelessWidget { final store = StoreProvider.of(context); final state = store.state; final uiState = state.uiState; + final prefState = state.prefState; Widget screen = BlankScreen(); @@ -350,8 +352,8 @@ class SettingsScreens extends StatelessWidget { flex: 3, child: screen, ), - if (uiState.isHistoryVisible && - uiState.historySidebarMode == AppSidebarMode.visible) ...[ + if (prefState.isHistoryVisible && + prefState.historySidebarMode == AppSidebarMode.visible) ...[ _CustomDivider(), Expanded( child: HistoryDrawerBuilder(), @@ -380,6 +382,7 @@ class EntityScreens extends StatelessWidget { final store = StoreProvider.of(context); final state = store.state; final uiState = state.uiState; + final prefState = state.prefState; final subRoute = uiState.subRoute; final entityUIState = state.getUIState(entityType); @@ -402,8 +405,8 @@ class EntityScreens extends StatelessWidget { ], ), ), - if (uiState.isHistoryVisible && - uiState.historySidebarMode == AppSidebarMode.visible) ...[ + if (prefState.isHistoryVisible && + prefState.historySidebarMode == AppSidebarMode.visible) ...[ _CustomDivider(), Expanded( child: HistoryDrawerBuilder(), diff --git a/lib/ui/app/menu_drawer.dart b/lib/ui/app/menu_drawer.dart index 13a67cec0..e32eacb0d 100644 --- a/lib/ui/app/menu_drawer.dart +++ b/lib/ui/app/menu_drawer.dart @@ -141,7 +141,7 @@ class MenuDrawer extends StatelessWidget { final Store store = StoreProvider.of(context); final NavigatorState navigator = Navigator.of(context); final state = store.state; - final enableDarkMode = state.uiState.enableDarkMode; + final enableDarkMode = state.prefState.enableDarkMode; final localization = AppLocalization.of(context); return Drawer( @@ -286,7 +286,7 @@ class MenuDrawer extends StatelessWidget { } store.dispatch(EditTask( task: TaskEntity( - isRunning: state.uiState.autoStartTasks), + isRunning: state.prefState.autoStartTasks), context: context)); }, ), @@ -318,7 +318,7 @@ class MenuDrawer extends StatelessWidget { } store.dispatch(EditExpense( expense: ExpenseEntity( - company: company, uiState: state.uiState), + company: company, prefState: state.prefState), context: context)); }, ), diff --git a/lib/ui/app/resources/cached_image.dart b/lib/ui/app/resources/cached_image.dart index 664cea925..ce72cf9a2 100644 --- a/lib/ui/app/resources/cached_image.dart +++ b/lib/ui/app/resources/cached_image.dart @@ -15,10 +15,10 @@ class CachedImage extends StatelessWidget { @override Widget build(BuildContext context) { final store = StoreProvider.of(context); - final uiState = store.state.uiState; + final state = store.state; // TODO remove this workaround - if (uiState.isTesting || (url ?? '').isEmpty) { + if (state.isTesting || (url ?? '').isEmpty) { return SizedBox( width: width, height: height, diff --git a/lib/ui/client/client_list.dart b/lib/ui/client/client_list.dart index 30b7fa330..fae0a0b63 100644 --- a/lib/ui/client/client_list.dart +++ b/lib/ui/client/client_list.dart @@ -74,7 +74,7 @@ class ClientList extends StatelessWidget { onTap: () => viewModel.onClientTap(context, client), onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/client/view/client_view.dart b/lib/ui/client/view/client_view.dart index 8b86d2438..5348eced4 100644 --- a/lib/ui/client/view/client_view.dart +++ b/lib/ui/client/view/client_view.dart @@ -147,7 +147,7 @@ class _ClientViewState extends State store.dispatch(EditTask( task: TaskEntity( isRunning: - store.state.uiState.autoStartTasks) + store.state.prefState.autoStartTasks) .rebuild((b) => b.clientId = client.id), context: context)); }, @@ -165,7 +165,7 @@ class _ClientViewState extends State expense: ExpenseEntity( company: company, client: client, - uiState: store.state.uiState), + prefState: store.state.prefState), context: context)); }, ) diff --git a/lib/ui/client/view/client_view_vm.dart b/lib/ui/client/view/client_view_vm.dart index 3b7b60ec0..748040e55 100644 --- a/lib/ui/client/view/client_view_vm.dart +++ b/lib/ui/client/view/client_view_vm.dart @@ -147,7 +147,7 @@ class ClientViewVM { if (longPress && client.isActive) { store.dispatch(EditTask( context: context, - task: TaskEntity(isRunning: state.uiState.autoStartTasks) + task: TaskEntity(isRunning: state.prefState.autoStartTasks) .rebuild((b) => b..clientId = client.id))); } else { store.dispatch(FilterTasksByEntity( @@ -162,7 +162,7 @@ class ClientViewVM { expense: ExpenseEntity( company: state.company, client: client, - uiState: state.uiState))); + prefState: state.prefState))); } else { store.dispatch(FilterExpensesByEntity( entityId: client.id, entityType: EntityType.client)); diff --git a/lib/ui/dashboard/dashboard_chart.dart b/lib/ui/dashboard/dashboard_chart.dart index 8798f296b..904cf1607 100644 --- a/lib/ui/dashboard/dashboard_chart.dart +++ b/lib/ui/dashboard/dashboard_chart.dart @@ -58,7 +58,7 @@ class _DashboardChartState extends State { final theme = Theme.of(context); final localization = AppLocalization.of(context); final state = StoreProvider.of(context).state; - final color = state.uiState.enableDarkMode + final color = state.prefState.enableDarkMode ? charts.MaterialPalette.white : charts.MaterialPalette.gray.shade700; diff --git a/lib/ui/dashboard/dashboard_screen.dart b/lib/ui/dashboard/dashboard_screen.dart index e3db80b99..da0f4afea 100644 --- a/lib/ui/dashboard/dashboard_screen.dart +++ b/lib/ui/dashboard/dashboard_screen.dart @@ -59,14 +59,14 @@ class _DashboardScreenState extends State return WillPopScope( onWillPop: () async => true, child: Scaffold( - drawer: isMobile(context) || state.uiState.isMenuFloated + drawer: isMobile(context) || state.prefState.isMenuFloated ? MenuDrawerBuilder() : null, - endDrawer: isMobile(context) || state.uiState.isHistoryFloated + endDrawer: isMobile(context) || state.prefState.isHistoryFloated ? HistoryDrawerBuilder() : null, appBar: AppBar( - leading: isMobile(context) || state.uiState.isMenuFloated + leading: isMobile(context) || state.prefState.isMenuFloated ? null : IconButton( icon: Icon(Icons.menu), @@ -88,12 +88,12 @@ class _DashboardScreenState extends State store.dispatch(FilterCompany(value)); }, ), - if (!state.uiState.isHistoryVisible) + if (!state.prefState.isHistoryVisible) Builder( builder: (context) => IconButton( icon: Icon(Icons.menu), onPressed: () { - if (isMobile(context) || state.uiState.isHistoryFloated) { + if (isMobile(context) || state.prefState.isHistoryFloated) { Scaffold.of(context).openEndDrawer(); } else { store.dispatch(UserSettingsChanged(sidebar: AppSidebar.history)); diff --git a/lib/ui/document/document_list.dart b/lib/ui/document/document_list.dart index 55e81a8d6..264a8ff3a 100644 --- a/lib/ui/document/document_list.dart +++ b/lib/ui/document/document_list.dart @@ -71,7 +71,7 @@ class DocumentList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/expense/expense_list.dart b/lib/ui/expense/expense_list.dart index 47db2acb4..708adac03 100644 --- a/lib/ui/expense/expense_list.dart +++ b/lib/ui/expense/expense_list.dart @@ -84,7 +84,7 @@ class ExpenseList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/expense/expense_screen.dart b/lib/ui/expense/expense_screen.dart index eb86e5ab0..77f103f4f 100644 --- a/lib/ui/expense/expense_screen.dart +++ b/lib/ui/expense/expense_screen.dart @@ -145,7 +145,7 @@ class ExpenseScreen extends StatelessWidget { onPressed: () { store.dispatch(EditExpense( expense: ExpenseEntity( - company: company, uiState: store.state.uiState), + company: company, prefState: store.state.prefState), context: context)); }, child: Icon( diff --git a/lib/ui/group/group_list.dart b/lib/ui/group/group_list.dart index 43c638c60..13d5391cb 100644 --- a/lib/ui/group/group_list.dart +++ b/lib/ui/group/group_list.dart @@ -68,7 +68,7 @@ class GroupList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/invoice/edit/invoice_item_selector.dart b/lib/ui/invoice/edit/invoice_item_selector.dart index 057f173d8..a4d8a924c 100644 --- a/lib/ui/invoice/edit/invoice_item_selector.dart +++ b/lib/ui/invoice/edit/invoice_item_selector.dart @@ -318,7 +318,7 @@ class _InvoiceItemSelectorState extends State _headerRow(), showTabBar ? TabBar( - labelColor: state.uiState.enableDarkMode + labelColor: state.prefState.enableDarkMode ? Colors.white : Colors.black, indicatorColor: Theme.of(context).accentColor, diff --git a/lib/ui/invoice/invoice_list.dart b/lib/ui/invoice/invoice_list.dart index 7124c573d..8a9c0fba1 100644 --- a/lib/ui/invoice/invoice_list.dart +++ b/lib/ui/invoice/invoice_list.dart @@ -81,7 +81,7 @@ class InvoiceList extends StatelessWidget { }, onLongPress: () async { final longPressIsSelection = - state.uiState.longPressSelectionIsDefault ?? + state.prefState.longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { handleInvoiceAction(context, [invoice], diff --git a/lib/ui/payment/edit/payment_edit.dart b/lib/ui/payment/edit/payment_edit.dart index 5523ce159..94e0b9993 100644 --- a/lib/ui/payment/edit/payment_edit.dart +++ b/lib/ui/payment/edit/payment_edit.dart @@ -237,7 +237,7 @@ class _PaymentEditState extends State { SwitchListTile( activeColor: Theme.of(context).accentColor, title: Text(localization.sendEmail), - value: viewModel.uiState.emailPayment, + value: viewModel.prefState.emailPayment, subtitle: Text(localization.emailReceipt), onChanged: (value) => viewModel.onEmailChanged(value), ), diff --git a/lib/ui/payment/edit/payment_edit_vm.dart b/lib/ui/payment/edit/payment_edit_vm.dart index 52d47a6d5..6d56b19a1 100644 --- a/lib/ui/payment/edit/payment_edit_vm.dart +++ b/lib/ui/payment/edit/payment_edit_vm.dart @@ -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/redux/app/app_actions.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_state.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/view/payment_view_vm.dart'; @@ -50,7 +50,7 @@ class PaymentEditVM { @required this.onChanged, @required this.onSavePressed, @required this.onEmailChanged, - @required this.uiState, + @required this.prefState, @required this.invoiceMap, @required this.invoiceList, @required this.clientMap, @@ -71,7 +71,7 @@ class PaymentEditVM { isDirty: payment.isNew, origPayment: state.paymentState.map[payment.id], payment: payment, - uiState: state.uiState, + prefState: state.prefState, staticState: state.staticState, invoiceMap: state.invoiceState.map, invoiceList: state.invoiceState.list, @@ -134,7 +134,7 @@ class PaymentEditVM { final Function(BuildContext) onCancelPressed; final Function(bool) onEmailChanged; final BuiltMap invoiceMap; - final UIState uiState; + final PrefState prefState; final BuiltList invoiceList; final BuiltMap clientMap; final BuiltList clientList; diff --git a/lib/ui/payment/payment_list.dart b/lib/ui/payment/payment_list.dart index 380e45c47..a74f32f72 100644 --- a/lib/ui/payment/payment_list.dart +++ b/lib/ui/payment/payment_list.dart @@ -77,7 +77,7 @@ class PaymentList extends StatelessWidget { }, onLongPress: () async { final longPressIsSelection = - state.uiState.longPressSelectionIsDefault ?? + state.prefState.longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { handlePaymentAction(context, [payment], diff --git a/lib/ui/product/product_list.dart b/lib/ui/product/product_list.dart index 3d5400417..13ff03d63 100644 --- a/lib/ui/product/product_list.dart +++ b/lib/ui/product/product_list.dart @@ -64,7 +64,7 @@ class ProductList extends StatelessWidget { onTap: () => viewModel.onProductTap(context, product), onLongPress: () async { final longPressIsSelection = - store.state.uiState.longPressSelectionIsDefault ?? true; + store.state.prefState.longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { handleProductAction( context, [product], EntityAction.toggleMultiselect); diff --git a/lib/ui/project/project_list.dart b/lib/ui/project/project_list.dart index cb2d89fa3..15025fc68 100644 --- a/lib/ui/project/project_list.dart +++ b/lib/ui/project/project_list.dart @@ -77,7 +77,7 @@ class ProjectList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/project/view/project_view_vm.dart b/lib/ui/project/view/project_view_vm.dart index 304595287..3a07e9f27 100644 --- a/lib/ui/project/view/project_view_vm.dart +++ b/lib/ui/project/view/project_view_vm.dart @@ -90,7 +90,7 @@ class ProjectViewVM { onTasksPressed: (BuildContext context, {bool longPress = false}) { if (longPress && project.isActive && client.isActive) { store.dispatch(EditTask( - task: TaskEntity(isRunning: state.uiState.autoStartTasks) + task: TaskEntity(isRunning: state.prefState.autoStartTasks) .rebuild((b) => b ..projectId = project.id ..clientId = project.clientId), @@ -104,7 +104,7 @@ class ProjectViewVM { onAddTaskPressed: (context) => store.dispatch(EditTask( context: context, task: - TaskEntity(isRunning: state.uiState.autoStartTasks).rebuild((b) => b + TaskEntity(isRunning: state.prefState.autoStartTasks).rebuild((b) => b ..projectId = project.id ..clientId = project.clientId), force: true, diff --git a/lib/ui/settings/device_settings_list.dart b/lib/ui/settings/device_settings_list.dart index 842d87768..e6f1c2834 100644 --- a/lib/ui/settings/device_settings_list.dart +++ b/lib/ui/settings/device_settings_list.dart @@ -31,7 +31,7 @@ class _DeviceSettingsState extends State { final localization = AppLocalization.of(context); final viewModel = widget.viewModel; final state = viewModel.state; - final uiState = state.uiState; + final prefState = state.prefState; return WillPopScope( onWillPop: () async { @@ -52,7 +52,7 @@ class _DeviceSettingsState extends State { children: [ AppDropdownButton( labelText: localization.layout, - value: viewModel.state.uiState.layout, + value: viewModel.state.prefState.layout, onChanged: (dynamic value) => viewModel.onLayoutChanged(context, value), items: [ @@ -66,10 +66,10 @@ class _DeviceSettingsState extends State { ), ], ), - if (state.uiState.layout == AppLayout.tablet) ...[ + if (state.prefState.layout == AppLayout.tablet) ...[ AppDropdownButton( labelText: localization.menuSidebar, - value: state.uiState.menuSidebarMode, + value: state.prefState.menuSidebarMode, items: [ DropdownMenuItem( child: Text(localization.showOrHide), @@ -91,7 +91,7 @@ class _DeviceSettingsState extends State { ), AppDropdownButton( labelText: localization.historySidebar, - value: state.uiState.historySidebarMode, + value: state.prefState.historySidebarMode, items: [ DropdownMenuItem( child: Text(localization.showOrHide), @@ -108,7 +108,7 @@ class _DeviceSettingsState extends State { ], FormColorPicker( labelText: localization.accentColor, - initialValue: uiState.accentColor, + initialValue: state.accentColor, showClear: false, onSelected: (value) => viewModel.onAccentColorChanged(context, value), @@ -119,7 +119,7 @@ class _DeviceSettingsState extends State { children: [ SwitchListTile( title: Text(AppLocalization.of(context).darkMode), - value: uiState.enableDarkMode, + value: prefState.enableDarkMode, onChanged: (value) => viewModel.onDarkModeChanged(context, value), secondary: Icon(kIsWeb @@ -130,12 +130,12 @@ class _DeviceSettingsState extends State { SwitchListTile( title: Text(AppLocalization.of(context) .longPressSelectionIsDefault), - value: uiState.longPressSelectionIsDefault, + value: prefState.longPressSelectionIsDefault, onChanged: (value) => viewModel.onLongPressSelectionIsDefault(context, value), secondary: Icon(kIsWeb ? Icons.check_box - : FontAwesomeIcons.checkSquare), + : FontAwesomeIcons.solidCheckSquare), activeColor: Theme.of(context).accentColor, ), FutureBuilder( @@ -145,10 +145,10 @@ class _DeviceSettingsState extends State { return SwitchListTile( title: Text(AppLocalization.of(context) .biometricAuthentication), - value: uiState.requireAuthentication, + value: prefState.requireAuthentication, onChanged: (value) => viewModel .onRequireAuthenticationChanged(context, value), - secondary: Icon(uiState.requireAuthentication + secondary: Icon(prefState.requireAuthentication ? FontAwesomeIcons.lock : FontAwesomeIcons.unlockAlt), activeColor: Theme.of(context).accentColor, @@ -163,7 +163,7 @@ class _DeviceSettingsState extends State { ? SwitchListTile( title: Text(AppLocalization.of(context).autoStartTasks), - value: uiState.autoStartTasks, + value: prefState.autoStartTasks, onChanged: (value) => viewModel.onAutoStartTasksChanged(context, value), secondary: Icon( diff --git a/lib/ui/task/task_list.dart b/lib/ui/task/task_list.dart index 2c20e6603..741e4987e 100644 --- a/lib/ui/task/task_list.dart +++ b/lib/ui/task/task_list.dart @@ -76,7 +76,7 @@ class TaskList extends StatelessWidget { }, onLongPress: () async { final longPressIsSelection = - state.uiState.longPressSelectionIsDefault ?? + state.prefState.longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { handleTaskAction(context, [task], diff --git a/lib/ui/task/task_screen.dart b/lib/ui/task/task_screen.dart index 53e941586..2fc887369 100644 --- a/lib/ui/task/task_screen.dart +++ b/lib/ui/task/task_screen.dart @@ -143,7 +143,7 @@ class TaskScreen extends StatelessWidget { onPressed: () { store.dispatch(EditTask( task: TaskEntity( - isRunning: store.state.uiState.autoStartTasks) + isRunning: store.state.prefState.autoStartTasks) .rebuild((b) => b ..clientId = store.state.taskListState.filterEntityId), diff --git a/lib/ui/tax_rate/tax_rate_list.dart b/lib/ui/tax_rate/tax_rate_list.dart index b7575f064..acb0563da 100644 --- a/lib/ui/tax_rate/tax_rate_list.dart +++ b/lib/ui/tax_rate/tax_rate_list.dart @@ -63,7 +63,7 @@ class TaxRateList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/ui/user/view/user_view_vm.dart b/lib/ui/user/view/user_view_vm.dart index 598db75c8..be2ad4f9a 100644 --- a/lib/ui/user/view/user_view_vm.dart +++ b/lib/ui/user/view/user_view_vm.dart @@ -142,7 +142,7 @@ class UserViewVM { if (longPress && user.isActive) { store.dispatch(EditTask( context: context, - task: TaskEntity(isRunning: state.uiState.autoStartTasks))); + task: TaskEntity(isRunning: state.prefState.autoStartTasks))); } else { store.dispatch(FilterTasksByEntity( entityId: user.id, entityType: EntityType.user)); @@ -154,7 +154,7 @@ class UserViewVM { store.dispatch(EditExpense( context: context, expense: ExpenseEntity( - company: state.company, uiState: state.uiState))); + company: state.company, prefState: state.prefState))); } else { store.dispatch(FilterExpensesByEntity( entityId: user.id, entityType: EntityType.user)); diff --git a/lib/ui/vendor/vendor_list.dart b/lib/ui/vendor/vendor_list.dart index 8fa0e11e8..20a56ab5d 100644 --- a/lib/ui/vendor/vendor_list.dart +++ b/lib/ui/vendor/vendor_list.dart @@ -62,7 +62,7 @@ class VendorList extends StatelessWidget { } }, onLongPress: () async { - final longPressIsSelection = store.state.uiState + final longPressIsSelection = store.state.prefState .longPressSelectionIsDefault ?? true; if (longPressIsSelection && !isInMultiselect) { diff --git a/lib/utils/platforms.dart b/lib/utils/platforms.dart index e4f589117..f185c716f 100644 --- a/lib/utils/platforms.dart +++ b/lib/utils/platforms.dart @@ -33,7 +33,7 @@ AppLayout calculateLayout(BuildContext context) { } AppLayout getLayout(BuildContext context) => - StoreProvider.of(context).state.uiState.layout ?? + StoreProvider.of(context).state.prefState.layout ?? 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 isDarkMode(BuildContext context) => - StoreProvider.of(context).state.uiState.enableDarkMode; + StoreProvider.of(context).state.prefState.enableDarkMode; bool isSelfHosted(BuildContext context) => StoreProvider.of(context).state.isSelfHosted; diff --git a/stubs/redux/stub/stub_actions b/stubs/redux/stub/stub_actions index a46c49078..088f04f8c 100644 --- a/stubs/redux/stub/stub_actions +++ b/stubs/redux/stub/stub_actions @@ -16,7 +16,7 @@ class ViewStubList implements PersistUI { final bool force; } -class ViewStub implements PersistUI { +class ViewStub implements PersistUI, PersistPrefs { ViewStub({ @required this.stubId, @required this.context, @@ -28,7 +28,7 @@ class ViewStub implements PersistUI { final bool force; } -class EditStub implements PersistUI { +class EditStub implements PersistUI, PersistPrefs { EditStub( {@required this.stub, @required this.context,