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';
// 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

View File

@ -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: '',

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/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<AppState> _initialState(bool isTesting) async {
}
return AppState(
uiState: UIState(
isTesting: isTesting,
prefState: prefState,
),
prefState: prefState,
);
}
@ -216,7 +212,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
@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<InvoiceNinjaApp> {
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<InvoiceNinjaApp> {
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<InvoiceNinjaApp> {
)
: InitScreen(),
locale: AppLocalization.createLocale(localeSelector(state)),
theme: state.uiState.enableDarkMode
theme: state.prefState.enableDarkMode
? ThemeData(
brightness: Brightness.dark,
accentColor: accentColor,

View File

@ -196,11 +196,12 @@ Middleware<AppState> _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<AppState> _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<AppState> _createLoadState(
final Completer<Null> completer = Completer<Null>();
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<AppState> _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)));

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/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<String>([

View File

@ -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<AppState, AppStateBuilder> {
factory AppState({
UIState uiState,
PrefState prefState,
}) {
return _$AppState._(
isLoading: false,
isSaving: false,
isTesting: false,
serverVersion: '',
lastError: '',
authState: AuthState(),
staticState: StaticState(),
userCompanyStates: BuiltList(List<int>.generate(10, (i) => i + 1)
.map((index) => UserCompanyState())
.toList()),
uiState: uiState ?? UIState(),
userCompanyStates: BuiltList(
List<int>.generate(kMaxNumberOfCompanies, (i) => i + 1)
.map((index) => UserCompanyState())
.toList()),
uiState: UIState(),
prefState: prefState ?? PrefState(),
);
}
@ -73,6 +78,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
bool get isSaving;
bool get isTesting;
String get lastError;
String get serverVersion;
@ -81,6 +88,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
StaticState get staticState;
PrefState get prefState;
UIState get uiState;
BuiltList<UserCompanyState> get userCompanyStates;
@ -110,6 +119,12 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
Credentials get credentials =>
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) {
switch (type) {
case EntityType.product:

View File

@ -24,6 +24,9 @@ class _$AppStateSerializer implements StructuredSerializer<AppState> {
'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<AppState> {
'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<AppState> {
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<AppState> {
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<UserCompanyState> 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<AppState, AppStateBuilder> {
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<AppState, AppStateBuilder> {
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<AppState, AppStateBuilder> {
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<AppState, AppStateBuilder> {
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<AppState, AppStateBuilder> {
authState.build();
_$failedField = 'staticState';
staticState.build();
_$failedField = 'prefState';
prefState.build();
_$failedField = 'uiState';
uiState.build();
_$failedField = 'userCompanyStates';

View File

@ -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:

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -193,7 +193,7 @@ Middleware<AppState> _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) {

View File

@ -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,

View File

@ -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),

View File

@ -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,

View File

@ -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,

View File

@ -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<HistoryRecord> _addToHistory(
} else {
return list.rebuild((b) => b
..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,
longPressSelectionIsDefault: longPressSelectionIsDefault ?? false,
addDocumentsToInvoice: false,
companyPrefs: BuiltList(List<int>.generate(10, (i) => i + 1)
.map((index) => CompanyPrefState())
.toList()),
companyPrefs: BuiltList(
List<int>.generate(kMaxNumberOfCompanies, (i) => i + 1)
.map((index) => CompanyPrefState())
.toList()),
);
}
@ -64,6 +65,12 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
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;
}

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/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 =

View File

@ -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<UIState, UIStateBuilder> {
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, UIStateBuilder> {
UIState._();
PrefState get prefState;
bool get isTesting;
int get selectedCompanyIndex;
String get currentRoute;
@ -134,39 +123,5 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
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,
{FullType specifiedType = FullType.unspecified}) {
final result = <Object>[
'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<UIState> {
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<UIState> {
}
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, UIStateBuilder> {
_$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<UIState, UIStateBuilder> {
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<UIState, UIStateBuilder> {
try {
_$result = _$v ??
new _$UIState._(
prefState: prefState.build(),
isTesting: isTesting,
selectedCompanyIndex: selectedCompanyIndex,
currentRoute: currentRoute,
previousRoute: previousRoute,
@ -669,9 +626,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
} catch (_) {
String _$failedField;
try {
_$failedField = 'prefState';
prefState.build();
_$failedField = 'dashboardUIState';
dashboardUIState.build();
_$failedField = 'productUIState';

View File

@ -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,

View File

@ -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,

View File

@ -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),

View File

@ -27,11 +27,7 @@ class HistoryDrawer extends StatelessWidget {
final state = store.state;
final widgets = <Widget>[];
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: <Widget>[
if (state.uiState.isHistoryFloated)
if (state.prefState.isHistoryFloated)
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.menu),

View File

@ -45,7 +45,7 @@ class _ListFilterState extends State<ListFilter> {
return StoreConnector<AppState, AppState>(
converter: (Store<AppState> 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(

View File

@ -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));

View File

@ -24,6 +24,7 @@ class MainScreen extends StatelessWidget {
onInit: (Store<AppState> store) => store.dispatch(LoadDashboard()),
builder: (BuildContext context, Store<AppState> 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: <Widget>[
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<AppState>(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<AppState>(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(),

View File

@ -141,7 +141,7 @@ class MenuDrawer extends StatelessWidget {
final Store<AppState> store = StoreProvider.of<AppState>(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));
},
),

View File

@ -15,10 +15,10 @@ class CachedImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final store = StoreProvider.of<AppState>(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,

View File

@ -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) {

View File

@ -147,7 +147,7 @@ class _ClientViewState extends State<ClientView>
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<ClientView>
expense: ExpenseEntity(
company: company,
client: client,
uiState: store.state.uiState),
prefState: store.state.prefState),
context: context));
},
)

View File

@ -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));

View File

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

View File

@ -59,14 +59,14 @@ class _DashboardScreenState extends State<DashboardScreen>
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<DashboardScreen>
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));

View File

@ -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) {

View File

@ -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) {

View File

@ -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(

View File

@ -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) {

View File

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

View File

@ -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],

View File

@ -237,7 +237,7 @@ class _PaymentEditState extends State<PaymentEdit> {
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),
),

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/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<String, InvoiceEntity> invoiceMap;
final UIState uiState;
final PrefState prefState;
final BuiltList<String> invoiceList;
final BuiltMap<String, ClientEntity> clientMap;
final BuiltList<String> clientList;

View File

@ -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],

View File

@ -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);

View File

@ -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) {

View File

@ -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,

View File

@ -31,7 +31,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
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<DeviceSettings> {
children: <Widget>[
AppDropdownButton<AppLayout>(
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<DeviceSettings> {
),
],
),
if (state.uiState.layout == AppLayout.tablet) ...[
if (state.prefState.layout == AppLayout.tablet) ...[
AppDropdownButton<AppSidebarMode>(
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<DeviceSettings> {
),
AppDropdownButton<AppSidebarMode>(
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<DeviceSettings> {
],
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<DeviceSettings> {
children: <Widget>[
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<DeviceSettings> {
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<DeviceSettings> {
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<DeviceSettings> {
? SwitchListTile(
title:
Text(AppLocalization.of(context).autoStartTasks),
value: uiState.autoStartTasks,
value: prefState.autoStartTasks,
onChanged: (value) =>
viewModel.onAutoStartTasksChanged(context, value),
secondary: Icon(

View File

@ -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],

View File

@ -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),

View File

@ -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) {

View File

@ -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));

View File

@ -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) {

View File

@ -33,7 +33,7 @@ AppLayout calculateLayout(BuildContext context) {
}
AppLayout getLayout(BuildContext context) =>
StoreProvider.of<AppState>(context).state.uiState.layout ??
StoreProvider.of<AppState>(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<AppState>(context).state.uiState.enableDarkMode;
StoreProvider.of<AppState>(context).state.prefState.enableDarkMode;
bool isSelfHosted(BuildContext context) =>
StoreProvider.of<AppState>(context).state.isSelfHosted;

View File

@ -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,