This commit is contained in:
Hillel Coren 2019-11-03 16:58:40 +02:00
parent d12787d7a3
commit a01af6ad8e
38 changed files with 396 additions and 360 deletions

View File

@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart'; import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/templates.dart'; import 'package:invoiceninja_flutter/utils/templates.dart';
@ -29,6 +30,7 @@ class _InvoiceEmailViewState extends State<InvoiceEmailView> {
String emailSubject; String emailSubject;
String emailBody; String emailBody;
final _debouncer = Debouncer();
final _subjectController = TextEditingController(); final _subjectController = TextEditingController();
final _bodyController = TextEditingController(); final _bodyController = TextEditingController();
@ -59,10 +61,12 @@ class _InvoiceEmailViewState extends State<InvoiceEmailView> {
} }
void _onChanged() { void _onChanged() {
setState(() { _debouncer.run(() {
emailSubject = _subjectController.text; setState(() {
emailBody = _bodyController.text; emailSubject = _subjectController.text;
updateTemplate(); emailBody = _bodyController.text;
updateTemplate();
});
}); });
} }

View File

@ -9,7 +9,6 @@ import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
import 'package:invoiceninja_flutter/ui/app/link_text.dart'; import 'package:invoiceninja_flutter/ui/app/link_text.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart'; import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -31,7 +30,6 @@ class LoginView extends StatefulWidget {
class _LoginState extends State<LoginView> { class _LoginState extends State<LoginView> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
final _firstNameController = TextEditingController(); final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController(); final _lastNameController = TextEditingController();

View File

@ -7,7 +7,6 @@ import 'package:invoiceninja_flutter/ui/client/edit/client_edit_notes.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_settings.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_settings.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_shipping_address.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_shipping_address.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/action_icon_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/action_icon_button.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart';
@ -28,7 +27,6 @@ class _ClientEditState extends State<ClientEdit>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
TabController _controller; TabController _controller;
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
@override @override
void initState() { void initState() {

View File

@ -4,6 +4,7 @@ import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
@ -28,6 +29,7 @@ class ClientEditBillingAddressState extends State<ClientEditBillingAddress> {
final _postalCodeController = TextEditingController(); final _postalCodeController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -66,15 +68,17 @@ class ClientEditBillingAddressState extends State<ClientEditBillingAddress> {
} }
void _onChanged() { void _onChanged() {
final client = widget.viewModel.client.rebuild((b) => b _debouncer.run(() {
..address1 = _address1Controller.text.trim() final client = widget.viewModel.client.rebuild((b) => b
..address2 = _address2Controller.text.trim() ..address1 = _address1Controller.text.trim()
..city = _cityController.text.trim() ..address2 = _address2Controller.text.trim()
..state = _stateController.text.trim() ..city = _cityController.text.trim()
..postalCode = _postalCodeController.text.trim()); ..state = _stateController.text.trim()
if (client != widget.viewModel.client) { ..postalCode = _postalCodeController.text.trim());
widget.viewModel.onChanged(client); if (client != widget.viewModel.client) {
} widget.viewModel.onChanged(client);
}
});
} }
@override @override

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/app/responsive_padding.dart'; import 'package:invoiceninja_flutter/ui/app/responsive_padding.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_contacts_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_contacts_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
class ClientEditContacts extends StatefulWidget { class ClientEditContacts extends StatefulWidget {
@ -160,6 +161,7 @@ class ContactEditDetailsState extends State<ContactEditDetails> {
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final _debouncer = Debouncer();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
@override @override
@ -206,17 +208,19 @@ class ContactEditDetailsState extends State<ContactEditDetails> {
} }
void _onChanged() { void _onChanged() {
final contact = widget.contact.rebuild((b) => b _debouncer.run(() {
..firstName = _firstNameController.text.trim() final contact = widget.contact.rebuild((b) => b
..lastName = _lastNameController.text.trim() ..firstName = _firstNameController.text.trim()
..email = _emailController.text.trim() ..lastName = _lastNameController.text.trim()
..password = _passwordController.text.trim() ..email = _emailController.text.trim()
..phone = _phoneController.text.trim() ..password = _passwordController.text.trim()
..customValue1 = _custom1Controller.text.trim() ..phone = _phoneController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (contact != widget.contact) { ..customValue2 = _custom2Controller.text.trim());
widget.viewModel.onChangedContact(contact, widget.index); if (contact != widget.contact) {
} widget.viewModel.onChangedContact(contact, widget.index);
}
});
} }
@override @override

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -30,6 +31,7 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final _debouncer = Debouncer();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
@override @override
@ -73,18 +75,20 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final client = viewModel.client.rebuild((b) => b final viewModel = widget.viewModel;
..name = _nameController.text.trim() final client = viewModel.client.rebuild((b) => b
..idNumber = _idNumberController.text.trim() ..name = _nameController.text.trim()
..vatNumber = _vatNumberController.text.trim() ..idNumber = _idNumberController.text.trim()
..website = _websiteController.text.trim() ..vatNumber = _vatNumberController.text.trim()
..phone = _phoneController.text.trim() ..website = _websiteController.text.trim()
..customValue1 = _custom1Controller.text.trim() ..phone = _phoneController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (client != viewModel.client) { ..customValue2 = _custom2Controller.text.trim());
viewModel.onChanged(client); if (client != viewModel.client) {
} viewModel.onChanged(client);
}
});
} }
@override @override

View File

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
@ -24,6 +25,7 @@ class ClientEditNotesState extends State<ClientEditNotes> {
final _privateNotesController = TextEditingController(); final _privateNotesController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -56,13 +58,15 @@ class ClientEditNotesState extends State<ClientEditNotes> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final client = viewModel.client.rebuild((b) => b final viewModel = widget.viewModel;
..publicNotes = _publicNotesController.text final client = viewModel.client.rebuild((b) => b
..privateNotes = _privateNotesController.text); ..publicNotes = _publicNotesController.text
if (client != viewModel.client) { ..privateNotes = _privateNotesController.text);
viewModel.onChanged(client); if (client != viewModel.client) {
} viewModel.onChanged(client);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -27,6 +28,7 @@ class ClientEditSettingsState extends State<ClientEditSettings> {
final _paymentTermsController = TextEditingController(); final _paymentTermsController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -62,12 +64,14 @@ class ClientEditSettingsState extends State<ClientEditSettings> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final client = viewModel.client.rebuild((b) => final viewModel = widget.viewModel;
b..settings.defaultTaskRate = parseDouble(_taskRateController.text)); final client = viewModel.client.rebuild((b) =>
if (client != viewModel.client) { b..settings.defaultTaskRate = parseDouble(_taskRateController.text));
viewModel.onChanged(client); if (client != viewModel.client) {
} viewModel.onChanged(client);
}
});
} }
@override @override

View File

@ -3,6 +3,7 @@ import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
@ -29,6 +30,7 @@ class ClientEditShippingAddressState extends State<ClientEditShippingAddress> {
final _shippingPostalCodeController = TextEditingController(); final _shippingPostalCodeController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -67,15 +69,17 @@ class ClientEditShippingAddressState extends State<ClientEditShippingAddress> {
} }
void _onChanged() { void _onChanged() {
final client = widget.viewModel.client.rebuild((b) => b _debouncer.run(() {
..shippingAddress1 = _shippingAddress1Controller.text.trim() final client = widget.viewModel.client.rebuild((b) => b
..shippingAddress2 = _shippingAddress2Controller.text.trim() ..shippingAddress1 = _shippingAddress1Controller.text.trim()
..shippingCity = _shippingCityController.text.trim() ..shippingAddress2 = _shippingAddress2Controller.text.trim()
..shippingState = _shippingStateController.text.trim() ..shippingCity = _shippingCityController.text.trim()
..shippingPostalCode = _shippingPostalCodeController.text.trim()); ..shippingState = _shippingStateController.text.trim()
if (client != widget.viewModel.client) { ..shippingPostalCode = _shippingPostalCodeController.text.trim());
widget.viewModel.onChanged(client); if (client != widget.viewModel.client) {
} widget.viewModel.onChanged(client);
}
});
} }
@override @override

View File

@ -32,7 +32,6 @@ class CompanyGatewayEdit extends StatefulWidget {
class _CompanyGatewayEditState extends State<CompanyGatewayEdit> class _CompanyGatewayEditState extends State<CompanyGatewayEdit>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
final FocusScopeNode _focusNode = FocusScopeNode(); final FocusScopeNode _focusNode = FocusScopeNode();
TabController _controller; TabController _controller;
@ -322,6 +321,7 @@ class GatewayConfigField extends StatefulWidget {
class _GatewayConfigFieldState extends State<GatewayConfigField> { class _GatewayConfigFieldState extends State<GatewayConfigField> {
bool autoValidate = false; bool autoValidate = false;
TextEditingController _textController; TextEditingController _textController;
final _debouncer = Debouncer();
@override @override
void initState() { void initState() {
@ -347,7 +347,9 @@ class _GatewayConfigFieldState extends State<GatewayConfigField> {
} }
void _onChanged() { void _onChanged() {
widget.onChanged(_textController.text.trim()); _debouncer.run(() {
widget.onChanged(_textController.text.trim());
});
} }
bool _obscureText(String field) { bool _obscureText(String field) {
@ -432,6 +434,8 @@ class LimitEditor extends StatefulWidget {
} }
class _LimitEditorState extends State<LimitEditor> { class _LimitEditorState extends State<LimitEditor> {
final _debouncer = Debouncer();
bool _enableMin = false; bool _enableMin = false;
bool _enableMax = false; bool _enableMax = false;
@ -481,16 +485,19 @@ class _LimitEditorState extends State<LimitEditor> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final companyGateway = viewModel.companyGateway; final viewModel = widget.viewModel;
final companyGateway = viewModel.companyGateway;
final updatedGateway = companyGateway.rebuild((b) => b final updatedGateway = companyGateway.rebuild((b) => b
..minLimit = _enableMin ? parseDouble(_minController.text.trim()) : null ..minLimit = _enableMin ? parseDouble(_minController.text.trim()) : null
..maxLimit = _enableMax ? parseDouble(_maxController.text.trim()) : null); ..maxLimit =
_enableMax ? parseDouble(_maxController.text.trim()) : null);
if (companyGateway != updatedGateway) { if (companyGateway != updatedGateway) {
viewModel.onChanged(updatedGateway); viewModel.onChanged(updatedGateway);
} }
});
} }
@override @override
@ -600,6 +607,7 @@ class _FeesEditorState extends State<FeesEditor> {
final _capController = TextEditingController(); final _capController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void dispose() { void dispose() {
@ -638,22 +646,24 @@ class _FeesEditorState extends State<FeesEditor> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final companyGateway = viewModel.companyGateway; final viewModel = widget.viewModel;
final companyGateway = viewModel.companyGateway;
final amount = parseDouble(_amountController.text.trim()); final amount = parseDouble(_amountController.text.trim());
final percent = parseDouble(_percentController.text.trim()); final percent = parseDouble(_percentController.text.trim());
final cap = parseDouble(_capController.text.trim()); final cap = parseDouble(_capController.text.trim());
final feesEnabled = amount != 0 || percent != 0; final feesEnabled = amount != 0 || percent != 0;
final updatedGateway = companyGateway.rebuild((b) => b final updatedGateway = companyGateway.rebuild((b) => b
..feeAmount = feesEnabled ? amount : null ..feeAmount = feesEnabled ? amount : null
..feePercent = feesEnabled ? percent : null ..feePercent = feesEnabled ? percent : null
..feeCap = feesEnabled ? cap : null); ..feeCap = feesEnabled ? cap : null);
if (companyGateway != updatedGateway) { if (companyGateway != updatedGateway) {
viewModel.onChanged(updatedGateway); viewModel.onChanged(updatedGateway);
} }
});
} }
@override @override

View File

@ -54,12 +54,14 @@ class _DocumentEditState extends State<DocumentEdit> {
} }
void _onChanged() { void _onChanged() {
final document = widget.viewModel.document.rebuild((b) => b _debouncer.run(() {
// STARTER: set value - do not remove comment final document = widget.viewModel.document.rebuild((b) => b
); // STARTER: set value - do not remove comment
if (document != widget.viewModel.document) { );
widget.viewModel.onChanged(document); if (document != widget.viewModel.document) {
} widget.viewModel.onChanged(document);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart'; import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart';
import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -31,6 +32,7 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -66,14 +68,16 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final expense = viewModel.expense.rebuild((b) => b final viewModel = widget.viewModel;
..amount = parseDouble(_amountController.text) final expense = viewModel.expense.rebuild((b) => b
..customValue1 = _custom1Controller.text.trim() ..amount = parseDouble(_amountController.text)
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (expense != viewModel.expense) { ..customValue2 = _custom2Controller.text.trim());
viewModel.onChanged(expense); if (expense != viewModel.expense) {
} viewModel.onChanged(expense);
}
});
} }
@override @override

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -21,6 +22,7 @@ class ExpenseEditNotesState extends State<ExpenseEditNotes> {
final _privateNotesController = TextEditingController(); final _privateNotesController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -53,13 +55,15 @@ class ExpenseEditNotesState extends State<ExpenseEditNotes> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final expense = viewModel.expense.rebuild((b) => b final viewModel = widget.viewModel;
..publicNotes = _publicNotesController.text.trim() final expense = viewModel.expense.rebuild((b) => b
..privateNotes = _privateNotesController.text.trim()); ..publicNotes = _publicNotesController.text.trim()
if (expense != viewModel.expense) { ..privateNotes = _privateNotesController.text.trim());
viewModel.onChanged(expense); if (expense != viewModel.expense) {
} viewModel.onChanged(expense);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart'; import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/tax_rate_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/invoice/tax_rate_dropdown.dart';
import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -31,6 +32,7 @@ class ExpenseEditSettingsState extends State<ExpenseEditSettings> {
final _exchangeRateController = TextEditingController(); final _exchangeRateController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -68,13 +70,15 @@ class ExpenseEditSettingsState extends State<ExpenseEditSettings> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final expense = viewModel.expense.rebuild((b) => b final viewModel = widget.viewModel;
..transactionReference = _transactionReferenceController.text.trim() final expense = viewModel.expense.rebuild((b) => b
..exchangeRate = parseDouble(_exchangeRateController.text)); ..transactionReference = _transactionReferenceController.text.trim()
if (expense != viewModel.expense) { ..exchangeRate = parseDouble(_exchangeRateController.text));
viewModel.onChanged(expense); if (expense != viewModel.expense) {
} viewModel.onChanged(expense);
}
});
} }
void _setCurrency(CurrencyEntity currency) { void _setCurrency(CurrencyEntity currency) {

View File

@ -24,13 +24,13 @@ class GroupEdit extends StatefulWidget {
class _GroupEditState extends State<GroupEdit> { class _GroupEditState extends State<GroupEdit> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
final _nameController = TextEditingController(); final _nameController = TextEditingController();
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -63,13 +63,15 @@ class _GroupEditState extends State<GroupEdit> {
} }
void _onChanged() { void _onChanged() {
final group = widget.viewModel.group.rebuild((b) => b _debouncer.run(() {
..name = _nameController.text.trim() final group = widget.viewModel.group.rebuild((b) => b
..customValue1 = _custom1Controller.text.trim() ..name = _nameController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (group != widget.viewModel.group) { ..customValue2 = _custom2Controller.text.trim());
widget.viewModel.onChanged(group); if (group != widget.viewModel.group) {
} widget.viewModel.onChanged(group);
}
});
} }
@override @override
@ -102,7 +104,8 @@ class _GroupEditState extends State<GroupEdit> {
ActionIconButton( ActionIconButton(
icon: Icons.cloud_upload, icon: Icons.cloud_upload,
tooltip: localization.save, tooltip: localization.save,
isVisible: !(group.isDeleted ?? false), // TODO remove this isVisible: !(group.isDeleted ?? false),
// TODO remove this
isDirty: group.isNew || group != viewModel.origGroup, isDirty: group.isNew || group != viewModel.origGroup,
isSaving: viewModel.isSaving, isSaving: viewModel.isSaving,
onPressed: () { onPressed: () {

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/invoice/invoice_item_view.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/tax_rate_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/invoice/tax_rate_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/responsive_padding.dart'; import 'package:invoiceninja_flutter/ui/app/responsive_padding.dart';
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_items_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_items_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
@ -114,6 +115,7 @@ class ItemEditDetailsState extends State<ItemEditDetails> {
TaxRateEntity _taxRate2; TaxRateEntity _taxRate2;
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -160,25 +162,27 @@ class ItemEditDetailsState extends State<ItemEditDetails> {
} }
void _onChanged() { void _onChanged() {
var invoiceItem = widget.invoiceItem.rebuild((b) => b _debouncer.run(() {
..productKey = _productKeyController.text.trim() var invoiceItem = widget.invoiceItem.rebuild((b) => b
..notes = _notesController.text ..productKey = _productKeyController.text.trim()
..cost = parseDouble(_costController.text) ..notes = _notesController.text
..quantity = parseDouble(_qtyController.text) ..cost = parseDouble(_costController.text)
..discount = parseDouble(_discountController.text) ..quantity = parseDouble(_qtyController.text)
..customValue1 = _custom1Controller.text.trim() ..discount = parseDouble(_discountController.text)
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
..customValue2 = _custom2Controller.text.trim());
if (_taxRate1 != null) { if (_taxRate1 != null) {
invoiceItem = invoiceItem.applyTax(_taxRate1); invoiceItem = invoiceItem.applyTax(_taxRate1);
} }
if (_taxRate2 != null) { if (_taxRate2 != null) {
invoiceItem = invoiceItem.applyTax(_taxRate2, isSecond: true); invoiceItem = invoiceItem.applyTax(_taxRate2, isSecond: true);
} }
if (invoiceItem != widget.invoiceItem) { if (invoiceItem != widget.invoiceItem) {
widget.viewModel.onChangedInvoiceItem(invoiceItem, widget.index); widget.viewModel.onChangedInvoiceItem(invoiceItem, widget.index);
} }
});
} }
@override @override

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_notes_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_notes_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
class InvoiceEditNotes extends StatefulWidget { class InvoiceEditNotes extends StatefulWidget {
@ -22,6 +23,7 @@ class InvoiceEditNotesState extends State<InvoiceEditNotes> {
final _footerController = TextEditingController(); final _footerController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -58,14 +60,16 @@ class InvoiceEditNotesState extends State<InvoiceEditNotes> {
} }
void _onChanged() { void _onChanged() {
final invoice = widget.viewModel.invoice.rebuild((b) => b _debouncer.run(() {
..publicNotes = _publicNotesController.text.trim() final invoice = widget.viewModel.invoice.rebuild((b) => b
..privateNotes = _privateNotesController.text.trim() ..publicNotes = _publicNotesController.text.trim()
..terms = _termsController.text.trim() ..privateNotes = _privateNotesController.text.trim()
..footer = _footerController.text.trim()); ..terms = _termsController.text.trim()
if (invoice != widget.viewModel.invoice) { ..footer = _footerController.text.trim());
widget.viewModel.onChanged(invoice); if (invoice != widget.viewModel.invoice) {
} widget.viewModel.onChanged(invoice);
}
});
} }
@override @override

View File

@ -30,14 +30,13 @@ class PaymentEdit extends StatefulWidget {
class _PaymentEditState extends State<PaymentEdit> { class _PaymentEditState extends State<PaymentEdit> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
final _amountController = TextEditingController(); final _amountController = TextEditingController();
final _transactionReferenceController = TextEditingController(); final _transactionReferenceController = TextEditingController();
final _privateNotesController = TextEditingController(); final _privateNotesController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
bool autoValidate = false; bool autoValidate = false;
@override @override
@ -72,13 +71,15 @@ class _PaymentEditState extends State<PaymentEdit> {
} }
void _onChanged() { void _onChanged() {
final payment = widget.viewModel.payment.rebuild((b) => b _debouncer.run(() {
..amount = parseDouble(_amountController.text) final payment = widget.viewModel.payment.rebuild((b) => b
..transactionReference = _transactionReferenceController.text.trim() ..amount = parseDouble(_amountController.text)
..privateNotes = _privateNotesController.text.trim()); ..transactionReference = _transactionReferenceController.text.trim()
if (payment != widget.viewModel.payment) { ..privateNotes = _privateNotesController.text.trim());
widget.viewModel.onChanged(payment); if (payment != widget.viewModel.payment) {
} widget.viewModel.onChanged(payment);
}
});
} }
@override @override

View File

@ -40,6 +40,7 @@ class _ProductEditState extends State<ProductEdit> {
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -85,17 +86,19 @@ class _ProductEditState extends State<ProductEdit> {
} }
void _onChanged() { void _onChanged() {
final product = widget.viewModel.product.rebuild((b) => b _debouncer.run(() {
..productKey = _productKeyController.text.trim() final product = widget.viewModel.product.rebuild((b) => b
..notes = _notesController.text.trim() ..productKey = _productKeyController.text.trim()
..price = parseDouble(_priceController.text) ..notes = _notesController.text.trim()
..quantity = parseDouble(_quantityController.text) ..price = parseDouble(_priceController.text)
..cost = parseDouble(_costController.text) ..quantity = parseDouble(_quantityController.text)
..customValue1 = _custom1Controller.text.trim() ..cost = parseDouble(_costController.text)
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (product != widget.viewModel.product) { ..customValue2 = _custom2Controller.text.trim());
widget.viewModel.onChanged(product); if (product != widget.viewModel.product) {
} widget.viewModel.onChanged(product);
}
});
} }
@override @override

View File

@ -83,16 +83,18 @@ class _ProjectEditState extends State<ProjectEdit> {
} }
void _onChanged() { void _onChanged() {
final project = widget.viewModel.project.rebuild((b) => b _debouncer.run(() {
..name = _nameController.text.trim() final project = widget.viewModel.project.rebuild((b) => b
..budgetedHours = parseDouble(_hoursController.text) ..name = _nameController.text.trim()
..taskRate = parseDouble(_taskRateController.text) ..budgetedHours = parseDouble(_hoursController.text)
..privateNotes = _privateNotesController.text.trim() ..taskRate = parseDouble(_taskRateController.text)
..customValue1 = _custom1Controller.text.trim() ..privateNotes = _privateNotesController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (project != widget.viewModel.project) { ..customValue2 = _custom2Controller.text.trim());
widget.viewModel.onChanged(project); if (project != widget.viewModel.project) {
} widget.viewModel.onChanged(project);
}
});
} }
@override @override

View File

@ -56,15 +56,7 @@ class _BuyNowButtonsState extends State<BuyNowButtons> {
super.didChangeDependencies(); super.didChangeDependencies();
} }
void _onChanged() { void _onChanged() {}
/*
final product = widget.viewModel.product.rebuild((b) => b
..customValue2 = _custom2Controller.text.trim());
if (product != widget.viewModel.product) {
widget.viewModel.onChanged(product);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -83,15 +83,7 @@ class _ClientPortalState extends State<ClientPortal>
super.didChangeDependencies(); super.didChangeDependencies();
} }
void _onChanged() { void _onChanged() {}
/*
final product = widget.viewModel.product.rebuild((b) => b
..customValue2 = _custom2Controller.text.trim());
if (product != widget.viewModel.product) {
widget.viewModel.onChanged(product);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -64,15 +64,7 @@ class _CreditCardsAndBanksState extends State<CreditCardsAndBanks>
super.didChangeDependencies(); super.didChangeDependencies();
} }
void _onChanged() { void _onChanged() {}
/*
final product = widget.viewModel.product.rebuild((b) => b
..customValue2 = _custom2Controller.text.trim());
if (product != widget.viewModel.product) {
widget.viewModel.onChanged(product);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -138,6 +138,7 @@ class _CustomFieldsSettingsState extends State<CustomFieldsSettings> {
final _customField4Controller = TextEditingController(); final _customField4Controller = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void dispose() { void dispose() {
@ -174,21 +175,23 @@ class _CustomFieldsSettingsState extends State<CustomFieldsSettings> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final fieldType = widget.fieldType; final viewModel = widget.viewModel;
final company = widget.viewModel.company; final fieldType = widget.fieldType;
final origFields = company.customFields; final company = widget.viewModel.company;
final origFields = company.customFields;
final updatedFields = origFields.rebuild((b) => b final updatedFields = origFields.rebuild((b) => b
..addAll({'${fieldType}1': _customField1Controller.text.trim()}) ..addAll({'${fieldType}1': _customField1Controller.text.trim()})
..addAll({'${fieldType}2': _customField2Controller.text.trim()}) ..addAll({'${fieldType}2': _customField2Controller.text.trim()})
..addAll({'${fieldType}3': _customField3Controller.text.trim()}) ..addAll({'${fieldType}3': _customField3Controller.text.trim()})
..addAll({'${fieldType}4': _customField4Controller.text.trim()})); ..addAll({'${fieldType}4': _customField4Controller.text.trim()}));
if (viewModel.company.customFields != updatedFields) { if (viewModel.company.customFields != updatedFields) {
viewModel.onCompanyChanged( viewModel.onCompanyChanged(
company.rebuild((b) => b..customFields.replace(updatedFields))); company.rebuild((b) => b..customFields.replace(updatedFields)));
} }
});
} }
@override @override

View File

@ -27,7 +27,6 @@ class GeneratedNumbers extends StatefulWidget {
class _GeneratedNumbersState extends State<GeneratedNumbers> class _GeneratedNumbersState extends State<GeneratedNumbers>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
FocusScopeNode _focusNode; FocusScopeNode _focusNode;
TabController _controller; TabController _controller;
@ -37,6 +36,7 @@ class _GeneratedNumbersState extends State<GeneratedNumbers>
final _recurringPrefixController = TextEditingController(); final _recurringPrefixController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void initState() { void initState() {
@ -75,12 +75,15 @@ class _GeneratedNumbersState extends State<GeneratedNumbers>
} }
void _onChanged() { void _onChanged() {
final settings = widget.viewModel.settings.rebuild((b) => b _debouncer.run(() {
..recurringInvoiceNumberPrefix = _recurringPrefixController.text.trim()); final settings = widget.viewModel.settings.rebuild((b) => b
..recurringInvoiceNumberPrefix =
_recurringPrefixController.text.trim());
if (settings != widget.viewModel.settings) { if (settings != widget.viewModel.settings) {
widget.viewModel.onSettingsChanged(settings); widget.viewModel.onSettingsChanged(settings);
} }
});
} }
@override @override
@ -260,6 +263,7 @@ class _EntityNumberSettingsState extends State<EntityNumberSettings> {
final _patternController = TextEditingController(); final _patternController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void dispose() { void dispose() {
@ -290,12 +294,14 @@ class _EntityNumberSettingsState extends State<EntityNumberSettings> {
} }
void _onChanged() { void _onChanged() {
final int counter = parseDouble(_counterController.text.trim()).toInt(); _debouncer.run(() {
final String pattern = _patternController.text.trim(); final int counter = parseDouble(_counterController.text.trim()).toInt();
final String pattern = _patternController.text.trim();
if (counter != widget.counterValue || pattern != widget.patternValue) { if (counter != widget.counterValue || pattern != widget.patternValue) {
widget.onChanged(counter, pattern); widget.onChanged(counter, pattern);
} }
});
} }
@override @override

View File

@ -31,15 +31,10 @@ class InvoiceDesign extends StatefulWidget {
class _InvoiceDesignState extends State<InvoiceDesign> class _InvoiceDesignState extends State<InvoiceDesign>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
TabController _controller; TabController _controller;
FocusScopeNode _focusNode; FocusScopeNode _focusNode;
//final _fontSizeController = TextEditingController();
List<TextEditingController> _controllers = [];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -51,39 +46,9 @@ class _InvoiceDesignState extends State<InvoiceDesign>
void dispose() { void dispose() {
_controller.dispose(); _controller.dispose();
_focusNode.dispose(); _focusNode.dispose();
_controllers.forEach((dynamic controller) {
controller.removeListener(_onChanged);
controller.dispose();
});
super.dispose(); super.dispose();
} }
@override
void didChangeDependencies() {
_controllers = [
//_fontSizeController,
];
_controllers
.forEach((dynamic controller) => controller.removeListener(_onChanged));
//final settings = widget.viewModel.settings;
_controllers
.forEach((dynamic controller) => controller.addListener(_onChanged));
super.didChangeDependencies();
}
void _onChanged() {
/*
final settings = widget.viewModel.settings.rebuild((b) => b..
if (settings != widget.viewModel.settings) {
widget.viewModel.onSettingsChanged(settings);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);

View File

@ -63,15 +63,7 @@ class _LocalizationSettingsState extends State<LocalizationSettings> {
super.didChangeDependencies(); super.didChangeDependencies();
} }
void _onChanged() { void _onChanged() {}
/*
final product = widget.viewModel.product.rebuild((b) => b
..customValue2 = _custom2Controller.text.trim());
if (product != widget.viewModel.product) {
widget.viewModel.onChanged(product);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -61,15 +61,7 @@ class _OnlinePaymentsState extends State<OnlinePayments>
super.didChangeDependencies(); super.didChangeDependencies();
} }
void _onChanged() { void _onChanged() {}
/*
final product = widget.viewModel.product.rebuild((b) => b
..customValue2 = _custom2Controller.text.trim());
if (product != widget.viewModel.product) {
widget.viewModel.onChanged(product);
}
*/
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -22,7 +22,6 @@ class UserDetails extends StatefulWidget {
class _UserDetailsState extends State<UserDetails> { class _UserDetailsState extends State<UserDetails> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
bool autoValidate = false; bool autoValidate = false;
@ -32,6 +31,7 @@ class _UserDetailsState extends State<UserDetails> {
final _emailController = TextEditingController(); final _emailController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void dispose() { void dispose() {
@ -67,14 +67,16 @@ class _UserDetailsState extends State<UserDetails> {
} }
void _onChanged() { void _onChanged() {
final user = widget.viewModel.user.rebuild((b) => b _debouncer.run(() {
..firstName = _firstNameController.text.trim() final user = widget.viewModel.user.rebuild((b) => b
..lastName = _lastNameController.text.trim() ..firstName = _firstNameController.text.trim()
..email = _emailController.text.trim() ..lastName = _lastNameController.text.trim()
..firstName = _firstNameController.text.trim()); ..email = _emailController.text.trim()
if (user != widget.viewModel.user) { ..firstName = _firstNameController.text.trim());
widget.viewModel.onChanged(user); if (user != widget.viewModel.user) {
} widget.viewModel.onChanged(user);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/task/edit/task_edit_details_vm.dart'; import 'package:invoiceninja_flutter/ui/task/edit/task_edit_details_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/redux/client/client_selectors.dart'; import 'package:invoiceninja_flutter/redux/client/client_selectors.dart';
import 'package:invoiceninja_flutter/redux/project/project_selectors.dart'; import 'package:invoiceninja_flutter/redux/project/project_selectors.dart';
@ -26,6 +27,7 @@ class _TaskEditDetailsState extends State<TaskEditDetails> {
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final _debouncer = Debouncer();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
@override @override
@ -59,13 +61,15 @@ class _TaskEditDetailsState extends State<TaskEditDetails> {
} }
void _onChanged() { void _onChanged() {
final task = widget.viewModel.task.rebuild((b) => b _debouncer.run(() {
..description = _descriptionController.text.trim() final task = widget.viewModel.task.rebuild((b) => b
..customValue1 = _custom1Controller.text.trim() ..description = _descriptionController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (task != widget.viewModel.task) { ..customValue2 = _custom2Controller.text.trim());
widget.viewModel.onChanged(task); if (task != widget.viewModel.task) {
} widget.viewModel.onChanged(task);
}
});
} }
@override @override

View File

@ -23,7 +23,6 @@ class TaxRateEdit extends StatefulWidget {
class _TaxRateEditState extends State<TaxRateEdit> { class _TaxRateEditState extends State<TaxRateEdit> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer();
bool autoValidate = false; bool autoValidate = false;
@ -31,6 +30,7 @@ class _TaxRateEditState extends State<TaxRateEdit> {
final _rateController = TextEditingController(); final _rateController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -62,12 +62,14 @@ class _TaxRateEditState extends State<TaxRateEdit> {
} }
void _onChanged() { void _onChanged() {
final taxRate = widget.viewModel.taxRate.rebuild((b) => b _debouncer.run(() {
..name = _nameController.text.trim() final taxRate = widget.viewModel.taxRate.rebuild((b) => b
..rate = parseDouble(_rateController.text)); ..name = _nameController.text.trim()
if (taxRate != widget.viewModel.taxRate) { ..rate = parseDouble(_rateController.text));
widget.viewModel.onChanged(taxRate); if (taxRate != widget.viewModel.taxRate) {
} widget.viewModel.onChanged(taxRate);
}
});
} }
@override @override

View File

@ -67,14 +67,16 @@ class _UserEditState extends State<UserEdit> {
} }
void _onChanged() { void _onChanged() {
final user = widget.viewModel.user.rebuild((b) => b _debouncer.run(() {
..firstName = _firstNameController.text.trim() final user = widget.viewModel.user.rebuild((b) => b
..lastName = _lastNameController.text.trim() ..firstName = _firstNameController.text.trim()
..email = _emailController.text.trim() ..lastName = _lastNameController.text.trim()
..phone = _phoneController.text.trim()); ..email = _emailController.text.trim()
if (user != widget.viewModel.user) { ..phone = _phoneController.text.trim());
widget.viewModel.onChanged(user); if (user != widget.viewModel.user) {
} widget.viewModel.onChanged(user);
}
});
} }
@override @override

View File

@ -3,6 +3,7 @@ import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
@ -26,6 +27,7 @@ class VendorEditAddressState extends State<VendorEditAddress> {
final _postalCodeController = TextEditingController(); final _postalCodeController = TextEditingController();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -64,15 +66,17 @@ class VendorEditAddressState extends State<VendorEditAddress> {
} }
void _onChanged() { void _onChanged() {
final vendor = widget.viewModel.vendor.rebuild((b) => b _debouncer.run(() {
..address1 = _address1Controller.text.trim() final vendor = widget.viewModel.vendor.rebuild((b) => b
..address2 = _address2Controller.text.trim() ..address1 = _address1Controller.text.trim()
..city = _cityController.text.trim() ..address2 = _address2Controller.text.trim()
..state = _stateController.text.trim() ..city = _cityController.text.trim()
..postalCode = _postalCodeController.text.trim()); ..state = _stateController.text.trim()
if (vendor != widget.viewModel.vendor) { ..postalCode = _postalCodeController.text.trim());
widget.viewModel.onChanged(vendor); if (vendor != widget.viewModel.vendor) {
} widget.viewModel.onChanged(vendor);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_contacts_vm.dart'; import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_contacts_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
class VendorEditContacts extends StatefulWidget { class VendorEditContacts extends StatefulWidget {
@ -157,6 +158,7 @@ class ContactEditDetailsState extends State<ContactEditDetails> {
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final _debouncer = Debouncer();
List<TextEditingController> _controllers = []; List<TextEditingController> _controllers = [];
@override @override
@ -201,14 +203,16 @@ class ContactEditDetailsState extends State<ContactEditDetails> {
} }
void _onChanged() { void _onChanged() {
final contact = widget.contact.rebuild((b) => b _debouncer.run(() {
..firstName = _firstNameController.text.trim() final contact = widget.contact.rebuild((b) => b
..lastName = _lastNameController.text.trim() ..firstName = _firstNameController.text.trim()
..email = _emailController.text.trim() ..lastName = _lastNameController.text.trim()
..phone = _phoneController.text.trim()); ..email = _emailController.text.trim()
if (contact != widget.contact) { ..phone = _phoneController.text.trim());
widget.viewModel.onChangedContact(contact, widget.index); if (contact != widget.contact) {
} widget.viewModel.onChangedContact(contact, widget.index);
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
class VendorEditDetails extends StatefulWidget { class VendorEditDetails extends StatefulWidget {
@ -28,6 +29,7 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
final _custom1Controller = TextEditingController(); final _custom1Controller = TextEditingController();
final _custom2Controller = TextEditingController(); final _custom2Controller = TextEditingController();
final _debouncer = Debouncer();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
@override @override
@ -71,18 +73,20 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final vendor = viewModel.vendor.rebuild((b) => b final viewModel = widget.viewModel;
..name = _nameController.text.trim() final vendor = viewModel.vendor.rebuild((b) => b
..idNumber = _idNumberController.text.trim() ..name = _nameController.text.trim()
..vatNumber = _vatNumberController.text.trim() ..idNumber = _idNumberController.text.trim()
..website = _websiteController.text.trim() ..vatNumber = _vatNumberController.text.trim()
..workPhone = _phoneController.text.trim() ..website = _websiteController.text.trim()
..customValue1 = _custom1Controller.text.trim() ..workPhone = _phoneController.text.trim()
..customValue2 = _custom2Controller.text.trim()); ..customValue1 = _custom1Controller.text.trim()
if (vendor != viewModel.vendor) { ..customValue2 = _custom2Controller.text.trim());
viewModel.onChanged(vendor); if (vendor != viewModel.vendor) {
} viewModel.onChanged(vendor);
}
});
} }
@override @override

View File

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart'; import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/vendor/edit/vendor_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
@ -24,6 +25,7 @@ class VendorEditNotesState extends State<VendorEditNotes> {
final _privateNotesController = TextEditingController(); final _privateNotesController = TextEditingController();
final List<TextEditingController> _controllers = []; final List<TextEditingController> _controllers = [];
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -56,13 +58,15 @@ class VendorEditNotesState extends State<VendorEditNotes> {
} }
void _onChanged() { void _onChanged() {
final viewModel = widget.viewModel; _debouncer.run(() {
final vendor = viewModel.vendor.rebuild((b) => b final viewModel = widget.viewModel;
//..publicNotes = _publicNotesController.text final vendor = viewModel.vendor.rebuild((b) => b
..privateNotes = _privateNotesController.text); //..publicNotes = _publicNotesController.text
if (vendor != viewModel.vendor) { ..privateNotes = _privateNotesController.text);
viewModel.onChanged(vendor); if (vendor != viewModel.vendor) {
} viewModel.onChanged(vendor);
}
});
} }
@override @override

View File

@ -2,6 +2,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:redux_logging/redux_logging.dart'; import 'package:redux_logging/redux_logging.dart';
@ -193,6 +194,7 @@ class ClientPage extends StatefulWidget {
class _ClientPageState extends State<ClientPage> { class _ClientPageState extends State<ClientPage> {
final _nameController = new TextEditingController(); final _nameController = new TextEditingController();
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -211,11 +213,13 @@ class _ClientPageState extends State<ClientPage> {
} }
void _onChanged() { void _onChanged() {
final name = _nameController.text.trim(); _debouncer.run(() {
final store = StoreProvider.of<AppState>(context); final name = _nameController.text.trim();
if (name != store.state.client.name) { final store = StoreProvider.of<AppState>(context);
store.dispatch(UpdateClient(name)); if (name != store.state.client.name) {
} store.dispatch(UpdateClient(name));
}
});
} }
@override @override
@ -277,6 +281,7 @@ class ContactForm extends StatefulWidget {
class _ContactFormState extends State<ContactForm> { class _ContactFormState extends State<ContactForm> {
final _emailController = new TextEditingController(); final _emailController = new TextEditingController();
final _debouncer = Debouncer();
@override @override
void didChangeDependencies() { void didChangeDependencies() {
@ -294,11 +299,13 @@ class _ContactFormState extends State<ContactForm> {
} }
void _onChanged() { void _onChanged() {
final store = StoreProvider.of<AppState>(context); _debouncer.run(() {
final email = _emailController.text.trim(); final store = StoreProvider.of<AppState>(context);
if (email != widget.contact.email) { final email = _emailController.text.trim();
store.dispatch(UpdateContact(email: email, index: widget.index)); if (email != widget.contact.email) {
} store.dispatch(UpdateContact(email: email, index: widget.index));
}
});
} }
@override @override

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/stub/edit/stub_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/action_icon_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/action_icon_button.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
class StubEdit extends StatefulWidget { class StubEdit extends StatefulWidget {
const StubEdit({ const StubEdit({
@ -20,7 +21,7 @@ class StubEdit extends StatefulWidget {
class _StubEditState extends State<StubEdit> { class _StubEditState extends State<StubEdit> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _debouncer = Debouncer(); final _debouncer = Debouncer();
// STARTER: controllers - do not remove comment // STARTER: controllers - do not remove comment
@ -54,12 +55,15 @@ final _debouncer = Debouncer();
} }
void _onChanged() { void _onChanged() {
_debouncer.run(() {
final stub = widget.viewModel.stub.rebuild((b) => b final stub = widget.viewModel.stub.rebuild((b) => b
// STARTER: set value - do not remove comment // STARTER: set value - do not remove comment
); );
if (stub != widget.viewModel.stub) { if (stub != widget.viewModel.stub) {
widget.viewModel.onChanged(stub); widget.viewModel.onChanged(stub);
} }
});
} }
@override @override