This commit is contained in:
Hillel Coren 2019-06-12 20:12:14 +03:00
parent b45ffe6bd3
commit a3014a86b6
17 changed files with 108 additions and 30 deletions

View File

@ -18,6 +18,7 @@ const String kSharedPrefEmailPayment = 'email_payment';
const String kSharedPrefAutoStartTasks = 'auto_start_tasks';
const String kSharedPrefAppVersion = 'app_version';
const String kSharedPrefRequireAuthentication = 'require_authentication';
const String kSharedPrefAddDocumentsToInvoice = 'add_documents_to_invoice';
String getCompanyTokenKey([int companyIndex = 0]) =>
'${kSharedPrefToken}_$companyIndex';

View File

@ -135,6 +135,8 @@ abstract class BaseEntity implements SelectableEntity {
bool get isNew => id == null || id < 0;
bool get isOld => !isNew;
bool get isActive => archivedAt == null || archivedAt == 0;
bool get isArchived => archivedAt != null && archivedAt > 0 && !isDeleted;

View File

@ -4,6 +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/utils/formatting.dart';
part 'expense_model.g.dart';
@ -67,13 +68,13 @@ abstract class ExpenseEntity extends Object
with BaseEntity, SelectableEntity, BelongsToClient
implements Built<ExpenseEntity, ExpenseEntityBuilder> {
factory ExpenseEntity(
{CompanyEntity company, VendorEntity vendor, ClientEntity client}) {
{CompanyEntity company, UIState uiState, VendorEntity vendor, ClientEntity client}) {
return _$ExpenseEntity._(
id: --ExpenseEntity.counter,
privateNotes: '',
publicNotes: '',
shouldBeInvoiced: false,
invoiceDocuments: false,
invoiceDocuments: uiState?.addDocumentsToInvoice ?? false,
transactionId: '',
transactionReference: '',
bankId: 0,

View File

@ -30,12 +30,14 @@ class UserSettingsChanged implements PersistUI {
{this.enableDarkMode,
this.emailPayment,
this.requireAuthentication,
this.autoStartTasks});
this.autoStartTasks,
this.addDocumentsToInvoice});
final bool enableDarkMode;
final bool emailPayment;
final bool requireAuthentication;
final bool autoStartTasks;
final bool addDocumentsToInvoice;
}
class LoadDataSuccess {

View File

@ -43,17 +43,15 @@ void _loadAuthLocal(Store<AppState> store, dynamic action) async {
final String secret = prefs.getString(kSharedPrefSecret) ?? '';
store.dispatch(UserLoginLoaded(email, url, secret));
final bool enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
final bool emailPayment = prefs.getBool(kSharedPrefEmailPayment) ?? false;
final bool autoStartTasks = prefs.getBool(kSharedPrefAutoStartTasks) ?? false;
final bool requireAuthentication =
prefs.getBool(kSharedPrefRequireAuthentication) ?? false;
store.dispatch(UserSettingsChanged(
enableDarkMode: enableDarkMode,
emailPayment: emailPayment,
requireAuthentication: requireAuthentication,
autoStartTasks: autoStartTasks));
enableDarkMode: prefs.getBool(kSharedPrefEnableDarkMode) ?? false,
emailPayment: prefs.getBool(kSharedPrefEmailPayment) ?? false,
requireAuthentication:
prefs.getBool(kSharedPrefRequireAuthentication) ?? false,
autoStartTasks: prefs.getBool(kSharedPrefAutoStartTasks) ?? false,
addDocumentsToInvoice:
prefs.getBool(kSharedPrefAddDocumentsToInvoice) ?? false,
));
}
Middleware<AppState> _createLoginInit() {

View File

@ -32,6 +32,8 @@ UIState uiReducer(UIState state, dynamic action) {
..requireAuthentication =
requireAuthenticationReducer(state.requireAuthentication, action)
..emailPayment = emailPaymentReducer(state.emailPayment, action)
..addDocumentsToInvoice =
addDocumentsToInvoiceReducer(state.addDocumentsToInvoice, action)
..productUIState.replace(productUIReducer(state.productUIState, action))
..clientUIState.replace(clientUIReducer(state.clientUIState, action))
..invoiceUIState.replace(invoiceUIReducer(state.invoiceUIState, action))
@ -79,6 +81,15 @@ bool updateAutoStartTasksReducer(
return action.autoStartTasks ?? autoStartTasks;
}
Reducer<bool> addDocumentsToInvoiceReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>(updateAddDocumentsToInvoiceReducer),
]);
bool updateAddDocumentsToInvoiceReducer(
bool addDocumentsToInvoice, UserSettingsChanged action) {
return action.addDocumentsToInvoice ?? addDocumentsToInvoice;
}
Reducer<bool> requireAuthenticationReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>(updateRequireAuthenticationReducer),
]);

View File

@ -32,6 +32,7 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
requireAuthentication: requireAuthentication ?? false,
emailPayment: false,
autoStartTasks: false,
addDocumentsToInvoice: false,
dashboardUIState: DashboardUIState(),
productUIState: ProductUIState(),
clientUIState: ClientUIState(),
@ -60,6 +61,8 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
bool get autoStartTasks;
bool get addDocumentsToInvoice;
@nullable
String get filter;

View File

@ -49,6 +49,9 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
'autoStartTasks',
serializers.serialize(object.autoStartTasks,
specifiedType: const FullType(bool)),
'addDocumentsToInvoice',
serializers.serialize(object.addDocumentsToInvoice,
specifiedType: const FullType(bool)),
'dashboardUIState',
serializers.serialize(object.dashboardUIState,
specifiedType: const FullType(DashboardUIState)),
@ -125,6 +128,10 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
result.autoStartTasks = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'addDocumentsToInvoice':
result.addDocumentsToInvoice = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'filter':
result.filter = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
@ -191,6 +198,8 @@ class _$UIState extends UIState {
@override
final bool autoStartTasks;
@override
final bool addDocumentsToInvoice;
@override
final String filter;
@override
final DashboardUIState dashboardUIState;
@ -223,6 +232,7 @@ class _$UIState extends UIState {
this.requireAuthentication,
this.emailPayment,
this.autoStartTasks,
this.addDocumentsToInvoice,
this.filter,
this.dashboardUIState,
this.productUIState,
@ -253,6 +263,9 @@ class _$UIState extends UIState {
if (autoStartTasks == null) {
throw new BuiltValueNullFieldError('UIState', 'autoStartTasks');
}
if (addDocumentsToInvoice == null) {
throw new BuiltValueNullFieldError('UIState', 'addDocumentsToInvoice');
}
if (dashboardUIState == null) {
throw new BuiltValueNullFieldError('UIState', 'dashboardUIState');
}
@ -302,6 +315,7 @@ class _$UIState extends UIState {
requireAuthentication == other.requireAuthentication &&
emailPayment == other.emailPayment &&
autoStartTasks == other.autoStartTasks &&
addDocumentsToInvoice == other.addDocumentsToInvoice &&
filter == other.filter &&
dashboardUIState == other.dashboardUIState &&
productUIState == other.productUIState &&
@ -332,6 +346,7 @@ class _$UIState extends UIState {
$jc(
$jc(
$jc(
$jc(
$jc(
$jc(
0,
@ -343,8 +358,12 @@ class _$UIState extends UIState {
.hashCode),
requireAuthentication
.hashCode),
emailPayment.hashCode),
autoStartTasks.hashCode),
emailPayment
.hashCode),
autoStartTasks
.hashCode),
addDocumentsToInvoice
.hashCode),
filter.hashCode),
dashboardUIState.hashCode),
productUIState.hashCode),
@ -367,6 +386,7 @@ class _$UIState extends UIState {
..add('requireAuthentication', requireAuthentication)
..add('emailPayment', emailPayment)
..add('autoStartTasks', autoStartTasks)
..add('addDocumentsToInvoice', addDocumentsToInvoice)
..add('filter', filter)
..add('dashboardUIState', dashboardUIState)
..add('productUIState', productUIState)
@ -413,6 +433,11 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
set autoStartTasks(bool autoStartTasks) =>
_$this._autoStartTasks = autoStartTasks;
bool _addDocumentsToInvoice;
bool get addDocumentsToInvoice => _$this._addDocumentsToInvoice;
set addDocumentsToInvoice(bool addDocumentsToInvoice) =>
_$this._addDocumentsToInvoice = addDocumentsToInvoice;
String _filter;
String get filter => _$this._filter;
set filter(String filter) => _$this._filter = filter;
@ -487,6 +512,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
_requireAuthentication = _$v.requireAuthentication;
_emailPayment = _$v.emailPayment;
_autoStartTasks = _$v.autoStartTasks;
_addDocumentsToInvoice = _$v.addDocumentsToInvoice;
_filter = _$v.filter;
_dashboardUIState = _$v.dashboardUIState?.toBuilder();
_productUIState = _$v.productUIState?.toBuilder();
@ -528,6 +554,7 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
requireAuthentication: requireAuthentication,
emailPayment: emailPayment,
autoStartTasks: autoStartTasks,
addDocumentsToInvoice: addDocumentsToInvoice,
filter: filter,
dashboardUIState: dashboardUIState.build(),
productUIState: productUIState.build(),

View File

@ -264,7 +264,9 @@ class AppDrawer extends StatelessWidget {
onCreateTap: () {
navigator.pop();
store.dispatch(EditExpense(
expense: ExpenseEntity(company: company), context: context));
expense:
ExpenseEntity(company: company, uiState: state.uiState),
context: context));
},
),

View File

@ -94,7 +94,10 @@ class ClientListVM {
break;
case EntityAction.newExpense:
store.dispatch(EditExpense(
expense: ExpenseEntity(company: state.selectedCompany, client: client),
expense: ExpenseEntity(
company: state.selectedCompany,
client: client,
uiState: state.uiState),
context: context));
break;
case EntityAction.enterPayment:

View File

@ -160,7 +160,9 @@ class _ClientViewState extends State<ClientView>
Navigator.of(context).pop();
store.dispatch(EditExpense(
expense: ExpenseEntity(
company: company, client: client),
company: company,
client: client,
uiState: store.state.uiState),
context: context));
},
)

View File

@ -155,7 +155,9 @@ class ClientViewVM {
store.dispatch(EditExpense(
context: context,
expense: ExpenseEntity(
company: state.selectedCompany, client: client)));
company: state.selectedCompany,
client: client,
uiState: state.uiState)));
} else {
store.dispatch(FilterExpensesByEntity(
entityId: client.id, entityType: EntityType.client));
@ -183,7 +185,9 @@ class ClientViewVM {
case EntityAction.newExpense:
store.dispatch(EditExpense(
expense: ExpenseEntity(
company: state.selectedCompany, client: client),
company: state.selectedCompany,
client: client,
uiState: state.uiState),
context: context));
break;
case EntityAction.enterPayment:

View File

@ -67,8 +67,11 @@ class ExpenseEditDocumentsState extends State<ExpenseEditDocuments> {
activeColor: Theme.of(context).accentColor,
title: Text(localization.addDocumentsToInvoice),
value: expense.invoiceDocuments,
onChanged: (value) => viewModel.onChanged(
expense.rebuild((b) => b..invoiceDocuments = value)),
onChanged: (value) {
viewModel.onChanged(
expense.rebuild((b) => b..invoiceDocuments = value));
viewModel.onAddDocumentsChanged(value);
}
)
],
),

View File

@ -138,8 +138,10 @@ class ExpenseEditSettingsState extends State<ExpenseEditSettings> {
activeColor: Theme.of(context).accentColor,
title: Text(localization.markBillable),
value: expense.shouldBeInvoiced,
onChanged: (value) => viewModel.onChanged(
expense.rebuild((b) => b..shouldBeInvoiced = value)),
onChanged: (value) {
viewModel.onChanged(
expense.rebuild((b) => b..shouldBeInvoiced = value));
},
),
SwitchListTile(
activeColor: Theme.of(context).accentColor,

View File

@ -2,6 +2,8 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
@ -16,6 +18,7 @@ import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
import 'package:invoiceninja_flutter/data/models/expense_model.dart';
import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ExpenseEditScreen extends StatelessWidget {
const ExpenseEditScreen({Key key}) : super(key: key);
@ -49,6 +52,7 @@ class ExpenseEditVM {
@required this.isLoading,
@required this.onAddClientPressed,
@required this.onAddVendorPressed,
@required this.onAddDocumentsChanged,
});
factory ExpenseEditVM.fromStore(Store<AppState> store) {
@ -120,6 +124,14 @@ class ExpenseEditVM {
});
});
},
onAddDocumentsChanged: (value) async {
if (expense.isOld) {
return;
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(kSharedPrefEmailPayment, value);
store.dispatch(UserSettingsChanged(addDocumentsToInvoice: value));
},
);
}
@ -136,4 +148,5 @@ class ExpenseEditVM {
onAddClientPressed;
final Function(BuildContext context, Completer<SelectableEntity> completer)
onAddVendorPressed;
final Function(bool) onAddDocumentsChanged;
}

View File

@ -91,7 +91,8 @@ class ExpenseScreen extends StatelessWidget {
backgroundColor: Theme.of(context).primaryColorDark,
onPressed: () {
store.dispatch(EditExpense(
expense: ExpenseEntity(company: company),
expense: ExpenseEntity(
company: company, uiState: store.state.uiState),
context: context));
},
child: Icon(

View File

@ -78,6 +78,9 @@ class PaymentEditVM {
store.dispatch(UpdatePayment(payment));
},
onEmailChanged: (value) async {
if (payment.isOld) {
return;
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(kSharedPrefEmailPayment, value);
store.dispatch(UserSettingsChanged(emailPayment: value));