diff --git a/lib/ui/app/invoice/invoice_email_view.dart b/lib/ui/app/invoice/invoice_email_view.dart index 299bec51f..4f6e80d18 100644 --- a/lib/ui/app/invoice/invoice_email_view.dart +++ b/lib/ui/app/invoice/invoice_email_view.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.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/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/templates.dart'; @@ -29,6 +30,7 @@ class _InvoiceEmailViewState extends State { String emailSubject; String emailBody; + final _debouncer = Debouncer(); final _subjectController = TextEditingController(); final _bodyController = TextEditingController(); @@ -59,10 +61,12 @@ class _InvoiceEmailViewState extends State { } void _onChanged() { - setState(() { - emailSubject = _subjectController.text; - emailBody = _bodyController.text; - updateTemplate(); + _debouncer.run(() { + setState(() { + emailSubject = _subjectController.text; + emailBody = _bodyController.text; + updateTemplate(); + }); }); } diff --git a/lib/ui/auth/login_view.dart b/lib/ui/auth/login_view.dart index e6497086a..b9b59052d 100644 --- a/lib/ui/auth/login_view.dart +++ b/lib/ui/auth/login_view.dart @@ -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/loading_indicator.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/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -31,7 +30,6 @@ class LoginView extends StatefulWidget { class _LoginState extends State { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); final _firstNameController = TextEditingController(); final _lastNameController = TextEditingController(); diff --git a/lib/ui/client/edit/client_edit.dart b/lib/ui/client/edit/client_edit.dart index de1168e11..318d8cf6b 100644 --- a/lib/ui/client/edit/client_edit.dart +++ b/lib/ui/client/edit/client_edit.dart @@ -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_shipping_address.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/ui/app/buttons/action_icon_button.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; @@ -28,7 +27,6 @@ class _ClientEditState extends State with SingleTickerProviderStateMixin { TabController _controller; static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); @override void initState() { diff --git a/lib/ui/client/edit/client_edit_billing_address.dart b/lib/ui/client/edit/client_edit_billing_address.dart index c780ae67a..60c557a3c 100644 --- a/lib/ui/client/edit/client_edit_billing_address.dart +++ b/lib/ui/client/edit/client_edit_billing_address.dart @@ -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/form_card.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/redux/static/static_selectors.dart'; @@ -28,6 +29,7 @@ class ClientEditBillingAddressState extends State { final _postalCodeController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -66,15 +68,17 @@ class ClientEditBillingAddressState extends State { } void _onChanged() { - final client = widget.viewModel.client.rebuild((b) => b - ..address1 = _address1Controller.text.trim() - ..address2 = _address2Controller.text.trim() - ..city = _cityController.text.trim() - ..state = _stateController.text.trim() - ..postalCode = _postalCodeController.text.trim()); - if (client != widget.viewModel.client) { - widget.viewModel.onChanged(client); - } + _debouncer.run(() { + final client = widget.viewModel.client.rebuild((b) => b + ..address1 = _address1Controller.text.trim() + ..address2 = _address2Controller.text.trim() + ..city = _cityController.text.trim() + ..state = _stateController.text.trim() + ..postalCode = _postalCodeController.text.trim()); + if (client != widget.viewModel.client) { + widget.viewModel.onChanged(client); + } + }); } @override diff --git a/lib/ui/client/edit/client_edit_contacts.dart b/lib/ui/client/edit/client_edit_contacts.dart index c0032497b..05e82d3af 100644 --- a/lib/ui/client/edit/client_edit_contacts.dart +++ b/lib/ui/client/edit/client_edit_contacts.dart @@ -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/responsive_padding.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'; class ClientEditContacts extends StatefulWidget { @@ -160,6 +161,7 @@ class ContactEditDetailsState extends State { final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); + final _debouncer = Debouncer(); List _controllers = []; @override @@ -206,17 +208,19 @@ class ContactEditDetailsState extends State { } void _onChanged() { - final contact = widget.contact.rebuild((b) => b - ..firstName = _firstNameController.text.trim() - ..lastName = _lastNameController.text.trim() - ..email = _emailController.text.trim() - ..password = _passwordController.text.trim() - ..phone = _phoneController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (contact != widget.contact) { - widget.viewModel.onChangedContact(contact, widget.index); - } + _debouncer.run(() { + final contact = widget.contact.rebuild((b) => b + ..firstName = _firstNameController.text.trim() + ..lastName = _lastNameController.text.trim() + ..email = _emailController.text.trim() + ..password = _passwordController.text.trim() + ..phone = _phoneController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (contact != widget.contact) { + widget.viewModel.onChangedContact(contact, widget.index); + } + }); } @override diff --git a/lib/ui/client/edit/client_edit_details.dart b/lib/ui/client/edit/client_edit_details.dart index 070d0303b..57d2c7937 100644 --- a/lib/ui/client/edit/client_edit_details.dart +++ b/lib/ui/client/edit/client_edit_details.dart @@ -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/decorated_form_field.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/ui/app/form_card.dart'; @@ -30,6 +31,7 @@ class ClientEditDetailsState extends State { final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); + final _debouncer = Debouncer(); final List _controllers = []; @override @@ -73,18 +75,20 @@ class ClientEditDetailsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final client = viewModel.client.rebuild((b) => b - ..name = _nameController.text.trim() - ..idNumber = _idNumberController.text.trim() - ..vatNumber = _vatNumberController.text.trim() - ..website = _websiteController.text.trim() - ..phone = _phoneController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (client != viewModel.client) { - viewModel.onChanged(client); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final client = viewModel.client.rebuild((b) => b + ..name = _nameController.text.trim() + ..idNumber = _idNumberController.text.trim() + ..vatNumber = _vatNumberController.text.trim() + ..website = _websiteController.text.trim() + ..phone = _phoneController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (client != viewModel.client) { + viewModel.onChanged(client); + } + }); } @override diff --git a/lib/ui/client/edit/client_edit_notes.dart b/lib/ui/client/edit/client_edit_notes.dart index 3f957fee6..4e834302b 100644 --- a/lib/ui/client/edit/client_edit_notes.dart +++ b/lib/ui/client/edit/client_edit_notes.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:invoiceninja_flutter/data/models/entities.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/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; @@ -24,6 +25,7 @@ class ClientEditNotesState extends State { final _privateNotesController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -56,13 +58,15 @@ class ClientEditNotesState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final client = viewModel.client.rebuild((b) => b - ..publicNotes = _publicNotesController.text - ..privateNotes = _privateNotesController.text); - if (client != viewModel.client) { - viewModel.onChanged(client); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final client = viewModel.client.rebuild((b) => b + ..publicNotes = _publicNotesController.text + ..privateNotes = _privateNotesController.text); + if (client != viewModel.client) { + viewModel.onChanged(client); + } + }); } @override diff --git a/lib/ui/client/edit/client_edit_settings.dart b/lib/ui/client/edit/client_edit_settings.dart index 8a584a0a2..0d6fb962c 100644 --- a/lib/ui/client/edit/client_edit_settings.dart +++ b/lib/ui/client/edit/client_edit_settings.dart @@ -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/ui/app/entity_dropdown.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/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -27,6 +28,7 @@ class ClientEditSettingsState extends State { final _paymentTermsController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -62,12 +64,14 @@ class ClientEditSettingsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final client = viewModel.client.rebuild((b) => - b..settings.defaultTaskRate = parseDouble(_taskRateController.text)); - if (client != viewModel.client) { - viewModel.onChanged(client); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final client = viewModel.client.rebuild((b) => + b..settings.defaultTaskRate = parseDouble(_taskRateController.text)); + if (client != viewModel.client) { + viewModel.onChanged(client); + } + }); } @override diff --git a/lib/ui/client/edit/client_edit_shipping_address.dart b/lib/ui/client/edit/client_edit_shipping_address.dart index a1e53e619..ce18578c0 100644 --- a/lib/ui/client/edit/client_edit_shipping_address.dart +++ b/lib/ui/client/edit/client_edit_shipping_address.dart @@ -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/entity_dropdown.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/redux/static/static_selectors.dart'; @@ -29,6 +30,7 @@ class ClientEditShippingAddressState extends State { final _shippingPostalCodeController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -67,15 +69,17 @@ class ClientEditShippingAddressState extends State { } void _onChanged() { - final client = widget.viewModel.client.rebuild((b) => b - ..shippingAddress1 = _shippingAddress1Controller.text.trim() - ..shippingAddress2 = _shippingAddress2Controller.text.trim() - ..shippingCity = _shippingCityController.text.trim() - ..shippingState = _shippingStateController.text.trim() - ..shippingPostalCode = _shippingPostalCodeController.text.trim()); - if (client != widget.viewModel.client) { - widget.viewModel.onChanged(client); - } + _debouncer.run(() { + final client = widget.viewModel.client.rebuild((b) => b + ..shippingAddress1 = _shippingAddress1Controller.text.trim() + ..shippingAddress2 = _shippingAddress2Controller.text.trim() + ..shippingCity = _shippingCityController.text.trim() + ..shippingState = _shippingStateController.text.trim() + ..shippingPostalCode = _shippingPostalCodeController.text.trim()); + if (client != widget.viewModel.client) { + widget.viewModel.onChanged(client); + } + }); } @override diff --git a/lib/ui/company_gateway/edit/company_gateway_edit.dart b/lib/ui/company_gateway/edit/company_gateway_edit.dart index 72f51e2d2..46bc3db9e 100644 --- a/lib/ui/company_gateway/edit/company_gateway_edit.dart +++ b/lib/ui/company_gateway/edit/company_gateway_edit.dart @@ -32,7 +32,6 @@ class CompanyGatewayEdit extends StatefulWidget { class _CompanyGatewayEditState extends State with SingleTickerProviderStateMixin { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); final FocusScopeNode _focusNode = FocusScopeNode(); TabController _controller; @@ -322,6 +321,7 @@ class GatewayConfigField extends StatefulWidget { class _GatewayConfigFieldState extends State { bool autoValidate = false; TextEditingController _textController; + final _debouncer = Debouncer(); @override void initState() { @@ -347,7 +347,9 @@ class _GatewayConfigFieldState extends State { } void _onChanged() { - widget.onChanged(_textController.text.trim()); + _debouncer.run(() { + widget.onChanged(_textController.text.trim()); + }); } bool _obscureText(String field) { @@ -432,6 +434,8 @@ class LimitEditor extends StatefulWidget { } class _LimitEditorState extends State { + final _debouncer = Debouncer(); + bool _enableMin = false; bool _enableMax = false; @@ -481,16 +485,19 @@ class _LimitEditorState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final companyGateway = viewModel.companyGateway; + _debouncer.run(() { + final viewModel = widget.viewModel; + final companyGateway = viewModel.companyGateway; - final updatedGateway = companyGateway.rebuild((b) => b - ..minLimit = _enableMin ? parseDouble(_minController.text.trim()) : null - ..maxLimit = _enableMax ? parseDouble(_maxController.text.trim()) : null); + final updatedGateway = companyGateway.rebuild((b) => b + ..minLimit = _enableMin ? parseDouble(_minController.text.trim()) : null + ..maxLimit = + _enableMax ? parseDouble(_maxController.text.trim()) : null); - if (companyGateway != updatedGateway) { - viewModel.onChanged(updatedGateway); - } + if (companyGateway != updatedGateway) { + viewModel.onChanged(updatedGateway); + } + }); } @override @@ -600,6 +607,7 @@ class _FeesEditorState extends State { final _capController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void dispose() { @@ -638,22 +646,24 @@ class _FeesEditorState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final companyGateway = viewModel.companyGateway; + _debouncer.run(() { + final viewModel = widget.viewModel; + final companyGateway = viewModel.companyGateway; - final amount = parseDouble(_amountController.text.trim()); - final percent = parseDouble(_percentController.text.trim()); - final cap = parseDouble(_capController.text.trim()); - final feesEnabled = amount != 0 || percent != 0; + final amount = parseDouble(_amountController.text.trim()); + final percent = parseDouble(_percentController.text.trim()); + final cap = parseDouble(_capController.text.trim()); + final feesEnabled = amount != 0 || percent != 0; - final updatedGateway = companyGateway.rebuild((b) => b - ..feeAmount = feesEnabled ? amount : null - ..feePercent = feesEnabled ? percent : null - ..feeCap = feesEnabled ? cap : null); + final updatedGateway = companyGateway.rebuild((b) => b + ..feeAmount = feesEnabled ? amount : null + ..feePercent = feesEnabled ? percent : null + ..feeCap = feesEnabled ? cap : null); - if (companyGateway != updatedGateway) { - viewModel.onChanged(updatedGateway); - } + if (companyGateway != updatedGateway) { + viewModel.onChanged(updatedGateway); + } + }); } @override diff --git a/lib/ui/document/edit/document_edit.dart b/lib/ui/document/edit/document_edit.dart index 761d25535..799d34873 100644 --- a/lib/ui/document/edit/document_edit.dart +++ b/lib/ui/document/edit/document_edit.dart @@ -54,12 +54,14 @@ class _DocumentEditState extends State { } void _onChanged() { - final document = widget.viewModel.document.rebuild((b) => b - // STARTER: set value - do not remove comment - ); - if (document != widget.viewModel.document) { - widget.viewModel.onChanged(document); - } + _debouncer.run(() { + final document = widget.viewModel.document.rebuild((b) => b + // STARTER: set value - do not remove comment + ); + if (document != widget.viewModel.document) { + widget.viewModel.onChanged(document); + } + }); } @override diff --git a/lib/ui/expense/edit/expense_edit_details.dart b/lib/ui/expense/edit/expense_edit_details.dart index e0934024f..4b430829a 100644 --- a/lib/ui/expense/edit/expense_edit_details.dart +++ b/lib/ui/expense/edit/expense_edit_details.dart @@ -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/date_picker.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/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -31,6 +32,7 @@ class ExpenseEditDetailsState extends State { final _custom2Controller = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -66,14 +68,16 @@ class ExpenseEditDetailsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final expense = viewModel.expense.rebuild((b) => b - ..amount = parseDouble(_amountController.text) - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (expense != viewModel.expense) { - viewModel.onChanged(expense); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final expense = viewModel.expense.rebuild((b) => b + ..amount = parseDouble(_amountController.text) + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (expense != viewModel.expense) { + viewModel.onChanged(expense); + } + }); } @override diff --git a/lib/ui/expense/edit/expense_edit_notes.dart b/lib/ui/expense/edit/expense_edit_notes.dart index 703363072..7e2d6ac58 100644 --- a/lib/ui/expense/edit/expense_edit_notes.dart +++ b/lib/ui/expense/edit/expense_edit_notes.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.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/ui/app/form_card.dart'; @@ -21,6 +22,7 @@ class ExpenseEditNotesState extends State { final _privateNotesController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -53,13 +55,15 @@ class ExpenseEditNotesState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final expense = viewModel.expense.rebuild((b) => b - ..publicNotes = _publicNotesController.text.trim() - ..privateNotes = _privateNotesController.text.trim()); - if (expense != viewModel.expense) { - viewModel.onChanged(expense); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final expense = viewModel.expense.rebuild((b) => b + ..publicNotes = _publicNotesController.text.trim() + ..privateNotes = _privateNotesController.text.trim()); + if (expense != viewModel.expense) { + viewModel.onChanged(expense); + } + }); } @override diff --git a/lib/ui/expense/edit/expense_edit_settings.dart b/lib/ui/expense/edit/expense_edit_settings.dart index 873ec6d3d..2db4a2aa6 100644 --- a/lib/ui/expense/edit/expense_edit_settings.dart +++ b/lib/ui/expense/edit/expense_edit_settings.dart @@ -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/invoice/tax_rate_dropdown.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/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -31,6 +32,7 @@ class ExpenseEditSettingsState extends State { final _exchangeRateController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -68,13 +70,15 @@ class ExpenseEditSettingsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final expense = viewModel.expense.rebuild((b) => b - ..transactionReference = _transactionReferenceController.text.trim() - ..exchangeRate = parseDouble(_exchangeRateController.text)); - if (expense != viewModel.expense) { - viewModel.onChanged(expense); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final expense = viewModel.expense.rebuild((b) => b + ..transactionReference = _transactionReferenceController.text.trim() + ..exchangeRate = parseDouble(_exchangeRateController.text)); + if (expense != viewModel.expense) { + viewModel.onChanged(expense); + } + }); } void _setCurrency(CurrencyEntity currency) { diff --git a/lib/ui/group/edit/group_edit.dart b/lib/ui/group/edit/group_edit.dart index 796d4b9b5..08fbff338 100644 --- a/lib/ui/group/edit/group_edit.dart +++ b/lib/ui/group/edit/group_edit.dart @@ -24,13 +24,13 @@ class GroupEdit extends StatefulWidget { class _GroupEditState extends State { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); final _nameController = TextEditingController(); final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -63,13 +63,15 @@ class _GroupEditState extends State { } void _onChanged() { - final group = widget.viewModel.group.rebuild((b) => b - ..name = _nameController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (group != widget.viewModel.group) { - widget.viewModel.onChanged(group); - } + _debouncer.run(() { + final group = widget.viewModel.group.rebuild((b) => b + ..name = _nameController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (group != widget.viewModel.group) { + widget.viewModel.onChanged(group); + } + }); } @override @@ -102,7 +104,8 @@ class _GroupEditState extends State { ActionIconButton( icon: Icons.cloud_upload, tooltip: localization.save, - isVisible: !(group.isDeleted ?? false), // TODO remove this + isVisible: !(group.isDeleted ?? false), + // TODO remove this isDirty: group.isNew || group != viewModel.origGroup, isSaving: viewModel.isSaving, onPressed: () { diff --git a/lib/ui/invoice/edit/invoice_edit_items.dart b/lib/ui/invoice/edit/invoice_edit_items.dart index bf67509d0..a2de1b7ec 100644 --- a/lib/ui/invoice/edit/invoice_edit_items.dart +++ b/lib/ui/invoice/edit/invoice_edit_items.dart @@ -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/responsive_padding.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:flutter/material.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; @@ -114,6 +115,7 @@ class ItemEditDetailsState extends State { TaxRateEntity _taxRate2; List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -160,25 +162,27 @@ class ItemEditDetailsState extends State { } void _onChanged() { - var invoiceItem = widget.invoiceItem.rebuild((b) => b - ..productKey = _productKeyController.text.trim() - ..notes = _notesController.text - ..cost = parseDouble(_costController.text) - ..quantity = parseDouble(_qtyController.text) - ..discount = parseDouble(_discountController.text) - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); + _debouncer.run(() { + var invoiceItem = widget.invoiceItem.rebuild((b) => b + ..productKey = _productKeyController.text.trim() + ..notes = _notesController.text + ..cost = parseDouble(_costController.text) + ..quantity = parseDouble(_qtyController.text) + ..discount = parseDouble(_discountController.text) + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); - if (_taxRate1 != null) { - invoiceItem = invoiceItem.applyTax(_taxRate1); - } - if (_taxRate2 != null) { - invoiceItem = invoiceItem.applyTax(_taxRate2, isSecond: true); - } + if (_taxRate1 != null) { + invoiceItem = invoiceItem.applyTax(_taxRate1); + } + if (_taxRate2 != null) { + invoiceItem = invoiceItem.applyTax(_taxRate2, isSecond: true); + } - if (invoiceItem != widget.invoiceItem) { - widget.viewModel.onChangedInvoiceItem(invoiceItem, widget.index); - } + if (invoiceItem != widget.invoiceItem) { + widget.viewModel.onChangedInvoiceItem(invoiceItem, widget.index); + } + }); } @override diff --git a/lib/ui/invoice/edit/invoice_edit_notes.dart b/lib/ui/invoice/edit/invoice_edit_notes.dart index 8fcb737c1..88687608a 100644 --- a/lib/ui/invoice/edit/invoice_edit_notes.dart +++ b/lib/ui/invoice/edit/invoice_edit_notes.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.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/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; class InvoiceEditNotes extends StatefulWidget { @@ -22,6 +23,7 @@ class InvoiceEditNotesState extends State { final _footerController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -58,14 +60,16 @@ class InvoiceEditNotesState extends State { } void _onChanged() { - final invoice = widget.viewModel.invoice.rebuild((b) => b - ..publicNotes = _publicNotesController.text.trim() - ..privateNotes = _privateNotesController.text.trim() - ..terms = _termsController.text.trim() - ..footer = _footerController.text.trim()); - if (invoice != widget.viewModel.invoice) { - widget.viewModel.onChanged(invoice); - } + _debouncer.run(() { + final invoice = widget.viewModel.invoice.rebuild((b) => b + ..publicNotes = _publicNotesController.text.trim() + ..privateNotes = _privateNotesController.text.trim() + ..terms = _termsController.text.trim() + ..footer = _footerController.text.trim()); + if (invoice != widget.viewModel.invoice) { + widget.viewModel.onChanged(invoice); + } + }); } @override diff --git a/lib/ui/payment/edit/payment_edit.dart b/lib/ui/payment/edit/payment_edit.dart index 3551b3e1f..ec47a2070 100644 --- a/lib/ui/payment/edit/payment_edit.dart +++ b/lib/ui/payment/edit/payment_edit.dart @@ -30,14 +30,13 @@ class PaymentEdit extends StatefulWidget { class _PaymentEditState extends State { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); final _amountController = TextEditingController(); final _transactionReferenceController = TextEditingController(); final _privateNotesController = TextEditingController(); List _controllers = []; - + final _debouncer = Debouncer(); bool autoValidate = false; @override @@ -72,13 +71,15 @@ class _PaymentEditState extends State { } void _onChanged() { - final payment = widget.viewModel.payment.rebuild((b) => b - ..amount = parseDouble(_amountController.text) - ..transactionReference = _transactionReferenceController.text.trim() - ..privateNotes = _privateNotesController.text.trim()); - if (payment != widget.viewModel.payment) { - widget.viewModel.onChanged(payment); - } + _debouncer.run(() { + final payment = widget.viewModel.payment.rebuild((b) => b + ..amount = parseDouble(_amountController.text) + ..transactionReference = _transactionReferenceController.text.trim() + ..privateNotes = _privateNotesController.text.trim()); + if (payment != widget.viewModel.payment) { + widget.viewModel.onChanged(payment); + } + }); } @override diff --git a/lib/ui/product/edit/product_edit.dart b/lib/ui/product/edit/product_edit.dart index c3240837a..d50eef558 100644 --- a/lib/ui/product/edit/product_edit.dart +++ b/lib/ui/product/edit/product_edit.dart @@ -40,6 +40,7 @@ class _ProductEditState extends State { final _custom2Controller = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -85,17 +86,19 @@ class _ProductEditState extends State { } void _onChanged() { - final product = widget.viewModel.product.rebuild((b) => b - ..productKey = _productKeyController.text.trim() - ..notes = _notesController.text.trim() - ..price = parseDouble(_priceController.text) - ..quantity = parseDouble(_quantityController.text) - ..cost = parseDouble(_costController.text) - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } + _debouncer.run(() { + final product = widget.viewModel.product.rebuild((b) => b + ..productKey = _productKeyController.text.trim() + ..notes = _notesController.text.trim() + ..price = parseDouble(_priceController.text) + ..quantity = parseDouble(_quantityController.text) + ..cost = parseDouble(_costController.text) + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (product != widget.viewModel.product) { + widget.viewModel.onChanged(product); + } + }); } @override diff --git a/lib/ui/project/edit/project_edit.dart b/lib/ui/project/edit/project_edit.dart index 523e4f34b..ab1cb642e 100644 --- a/lib/ui/project/edit/project_edit.dart +++ b/lib/ui/project/edit/project_edit.dart @@ -83,16 +83,18 @@ class _ProjectEditState extends State { } void _onChanged() { - final project = widget.viewModel.project.rebuild((b) => b - ..name = _nameController.text.trim() - ..budgetedHours = parseDouble(_hoursController.text) - ..taskRate = parseDouble(_taskRateController.text) - ..privateNotes = _privateNotesController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (project != widget.viewModel.project) { - widget.viewModel.onChanged(project); - } + _debouncer.run(() { + final project = widget.viewModel.project.rebuild((b) => b + ..name = _nameController.text.trim() + ..budgetedHours = parseDouble(_hoursController.text) + ..taskRate = parseDouble(_taskRateController.text) + ..privateNotes = _privateNotesController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (project != widget.viewModel.project) { + widget.viewModel.onChanged(project); + } + }); } @override diff --git a/lib/ui/settings/buy_now_buttons.dart b/lib/ui/settings/buy_now_buttons.dart index 320dc6b39..5119402f3 100644 --- a/lib/ui/settings/buy_now_buttons.dart +++ b/lib/ui/settings/buy_now_buttons.dart @@ -56,15 +56,7 @@ class _BuyNowButtonsState extends State { super.didChangeDependencies(); } - void _onChanged() { - /* - final product = widget.viewModel.product.rebuild((b) => b - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } - */ - } + void _onChanged() {} @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/client_portal.dart b/lib/ui/settings/client_portal.dart index 9e6fbb1fe..ad7140da6 100644 --- a/lib/ui/settings/client_portal.dart +++ b/lib/ui/settings/client_portal.dart @@ -83,15 +83,7 @@ class _ClientPortalState extends State super.didChangeDependencies(); } - void _onChanged() { - /* - final product = widget.viewModel.product.rebuild((b) => b - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } - */ - } + void _onChanged() {} @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/credit_cards_and_banks.dart b/lib/ui/settings/credit_cards_and_banks.dart index 192c0ac97..c48b0d654 100644 --- a/lib/ui/settings/credit_cards_and_banks.dart +++ b/lib/ui/settings/credit_cards_and_banks.dart @@ -64,15 +64,7 @@ class _CreditCardsAndBanksState extends State super.didChangeDependencies(); } - void _onChanged() { - /* - final product = widget.viewModel.product.rebuild((b) => b - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } - */ - } + void _onChanged() {} @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/custom_fields.dart b/lib/ui/settings/custom_fields.dart index 8bf381876..cb25e23b5 100644 --- a/lib/ui/settings/custom_fields.dart +++ b/lib/ui/settings/custom_fields.dart @@ -138,6 +138,7 @@ class _CustomFieldsSettingsState extends State { final _customField4Controller = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void dispose() { @@ -174,21 +175,23 @@ class _CustomFieldsSettingsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final fieldType = widget.fieldType; - final company = widget.viewModel.company; - final origFields = company.customFields; + _debouncer.run(() { + final viewModel = widget.viewModel; + final fieldType = widget.fieldType; + final company = widget.viewModel.company; + final origFields = company.customFields; - final updatedFields = origFields.rebuild((b) => b - ..addAll({'${fieldType}1': _customField1Controller.text.trim()}) - ..addAll({'${fieldType}2': _customField2Controller.text.trim()}) - ..addAll({'${fieldType}3': _customField3Controller.text.trim()}) - ..addAll({'${fieldType}4': _customField4Controller.text.trim()})); + final updatedFields = origFields.rebuild((b) => b + ..addAll({'${fieldType}1': _customField1Controller.text.trim()}) + ..addAll({'${fieldType}2': _customField2Controller.text.trim()}) + ..addAll({'${fieldType}3': _customField3Controller.text.trim()}) + ..addAll({'${fieldType}4': _customField4Controller.text.trim()})); - if (viewModel.company.customFields != updatedFields) { - viewModel.onCompanyChanged( - company.rebuild((b) => b..customFields.replace(updatedFields))); - } + if (viewModel.company.customFields != updatedFields) { + viewModel.onCompanyChanged( + company.rebuild((b) => b..customFields.replace(updatedFields))); + } + }); } @override diff --git a/lib/ui/settings/generated_numbers.dart b/lib/ui/settings/generated_numbers.dart index 8b87b0321..100468d91 100644 --- a/lib/ui/settings/generated_numbers.dart +++ b/lib/ui/settings/generated_numbers.dart @@ -27,7 +27,6 @@ class GeneratedNumbers extends StatefulWidget { class _GeneratedNumbersState extends State with SingleTickerProviderStateMixin { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); FocusScopeNode _focusNode; TabController _controller; @@ -37,6 +36,7 @@ class _GeneratedNumbersState extends State final _recurringPrefixController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void initState() { @@ -75,12 +75,15 @@ class _GeneratedNumbersState extends State } void _onChanged() { - final settings = widget.viewModel.settings.rebuild((b) => b - ..recurringInvoiceNumberPrefix = _recurringPrefixController.text.trim()); + _debouncer.run(() { + final settings = widget.viewModel.settings.rebuild((b) => b + ..recurringInvoiceNumberPrefix = + _recurringPrefixController.text.trim()); - if (settings != widget.viewModel.settings) { - widget.viewModel.onSettingsChanged(settings); - } + if (settings != widget.viewModel.settings) { + widget.viewModel.onSettingsChanged(settings); + } + }); } @override @@ -260,6 +263,7 @@ class _EntityNumberSettingsState extends State { final _patternController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void dispose() { @@ -290,12 +294,14 @@ class _EntityNumberSettingsState extends State { } void _onChanged() { - final int counter = parseDouble(_counterController.text.trim()).toInt(); - final String pattern = _patternController.text.trim(); + _debouncer.run(() { + final int counter = parseDouble(_counterController.text.trim()).toInt(); + final String pattern = _patternController.text.trim(); - if (counter != widget.counterValue || pattern != widget.patternValue) { - widget.onChanged(counter, pattern); - } + if (counter != widget.counterValue || pattern != widget.patternValue) { + widget.onChanged(counter, pattern); + } + }); } @override diff --git a/lib/ui/settings/invoice_design.dart b/lib/ui/settings/invoice_design.dart index 6939a59e4..9a8d1116e 100644 --- a/lib/ui/settings/invoice_design.dart +++ b/lib/ui/settings/invoice_design.dart @@ -31,15 +31,10 @@ class InvoiceDesign extends StatefulWidget { class _InvoiceDesignState extends State with SingleTickerProviderStateMixin { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); TabController _controller; FocusScopeNode _focusNode; - //final _fontSizeController = TextEditingController(); - - List _controllers = []; - @override void initState() { super.initState(); @@ -51,39 +46,9 @@ class _InvoiceDesignState extends State void dispose() { _controller.dispose(); _focusNode.dispose(); - _controllers.forEach((dynamic controller) { - controller.removeListener(_onChanged); - controller.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 Widget build(BuildContext context) { final localization = AppLocalization.of(context); diff --git a/lib/ui/settings/localization_settings.dart b/lib/ui/settings/localization_settings.dart index 7a2b1f346..92994951d 100644 --- a/lib/ui/settings/localization_settings.dart +++ b/lib/ui/settings/localization_settings.dart @@ -63,15 +63,7 @@ class _LocalizationSettingsState extends State { super.didChangeDependencies(); } - void _onChanged() { - /* - final product = widget.viewModel.product.rebuild((b) => b - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } - */ - } + void _onChanged() {} @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/online_payments.dart b/lib/ui/settings/online_payments.dart index 05f00c676..e81346ff9 100644 --- a/lib/ui/settings/online_payments.dart +++ b/lib/ui/settings/online_payments.dart @@ -61,15 +61,7 @@ class _OnlinePaymentsState extends State super.didChangeDependencies(); } - void _onChanged() { - /* - final product = widget.viewModel.product.rebuild((b) => b - ..customValue2 = _custom2Controller.text.trim()); - if (product != widget.viewModel.product) { - widget.viewModel.onChanged(product); - } - */ - } + void _onChanged() {} @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/user_details.dart b/lib/ui/settings/user_details.dart index 357c8d016..4bed95813 100644 --- a/lib/ui/settings/user_details.dart +++ b/lib/ui/settings/user_details.dart @@ -22,7 +22,6 @@ class UserDetails extends StatefulWidget { class _UserDetailsState extends State { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); bool autoValidate = false; @@ -32,6 +31,7 @@ class _UserDetailsState extends State { final _emailController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void dispose() { @@ -67,14 +67,16 @@ class _UserDetailsState extends State { } void _onChanged() { - final user = widget.viewModel.user.rebuild((b) => b - ..firstName = _firstNameController.text.trim() - ..lastName = _lastNameController.text.trim() - ..email = _emailController.text.trim() - ..firstName = _firstNameController.text.trim()); - if (user != widget.viewModel.user) { - widget.viewModel.onChanged(user); - } + _debouncer.run(() { + final user = widget.viewModel.user.rebuild((b) => b + ..firstName = _firstNameController.text.trim() + ..lastName = _lastNameController.text.trim() + ..email = _emailController.text.trim() + ..firstName = _firstNameController.text.trim()); + if (user != widget.viewModel.user) { + widget.viewModel.onChanged(user); + } + }); } @override diff --git a/lib/ui/task/edit/task_edit_details.dart b/lib/ui/task/edit/task_edit_details.dart index 5c2b551d6..bff58020d 100644 --- a/lib/ui/task/edit/task_edit_details.dart +++ b/lib/ui/task/edit/task_edit_details.dart @@ -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/forms/custom_field.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/redux/client/client_selectors.dart'; import 'package:invoiceninja_flutter/redux/project/project_selectors.dart'; @@ -26,6 +27,7 @@ class _TaskEditDetailsState extends State { final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); + final _debouncer = Debouncer(); List _controllers = []; @override @@ -59,13 +61,15 @@ class _TaskEditDetailsState extends State { } void _onChanged() { - final task = widget.viewModel.task.rebuild((b) => b - ..description = _descriptionController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (task != widget.viewModel.task) { - widget.viewModel.onChanged(task); - } + _debouncer.run(() { + final task = widget.viewModel.task.rebuild((b) => b + ..description = _descriptionController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (task != widget.viewModel.task) { + widget.viewModel.onChanged(task); + } + }); } @override diff --git a/lib/ui/tax_rate/edit/tax_rate_edit.dart b/lib/ui/tax_rate/edit/tax_rate_edit.dart index 7dc693054..2ff8a5133 100644 --- a/lib/ui/tax_rate/edit/tax_rate_edit.dart +++ b/lib/ui/tax_rate/edit/tax_rate_edit.dart @@ -23,7 +23,6 @@ class TaxRateEdit extends StatefulWidget { class _TaxRateEditState extends State { static final GlobalKey _formKey = GlobalKey(); - final _debouncer = Debouncer(); bool autoValidate = false; @@ -31,6 +30,7 @@ class _TaxRateEditState extends State { final _rateController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -62,12 +62,14 @@ class _TaxRateEditState extends State { } void _onChanged() { - final taxRate = widget.viewModel.taxRate.rebuild((b) => b - ..name = _nameController.text.trim() - ..rate = parseDouble(_rateController.text)); - if (taxRate != widget.viewModel.taxRate) { - widget.viewModel.onChanged(taxRate); - } + _debouncer.run(() { + final taxRate = widget.viewModel.taxRate.rebuild((b) => b + ..name = _nameController.text.trim() + ..rate = parseDouble(_rateController.text)); + if (taxRate != widget.viewModel.taxRate) { + widget.viewModel.onChanged(taxRate); + } + }); } @override diff --git a/lib/ui/user/edit/user_edit.dart b/lib/ui/user/edit/user_edit.dart index 0b5f67c40..427aeaa70 100644 --- a/lib/ui/user/edit/user_edit.dart +++ b/lib/ui/user/edit/user_edit.dart @@ -67,14 +67,16 @@ class _UserEditState extends State { } void _onChanged() { - final user = widget.viewModel.user.rebuild((b) => b - ..firstName = _firstNameController.text.trim() - ..lastName = _lastNameController.text.trim() - ..email = _emailController.text.trim() - ..phone = _phoneController.text.trim()); - if (user != widget.viewModel.user) { - widget.viewModel.onChanged(user); - } + _debouncer.run(() { + final user = widget.viewModel.user.rebuild((b) => b + ..firstName = _firstNameController.text.trim() + ..lastName = _lastNameController.text.trim() + ..email = _emailController.text.trim() + ..phone = _phoneController.text.trim()); + if (user != widget.viewModel.user) { + widget.viewModel.onChanged(user); + } + }); } @override diff --git a/lib/ui/vendor/edit/vendor_edit_address.dart b/lib/ui/vendor/edit/vendor_edit_address.dart index cd852a5b7..8beb962fc 100644 --- a/lib/ui/vendor/edit/vendor_edit_address.dart +++ b/lib/ui/vendor/edit/vendor_edit_address.dart @@ -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/form_card.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/redux/static/static_selectors.dart'; @@ -26,6 +27,7 @@ class VendorEditAddressState extends State { final _postalCodeController = TextEditingController(); List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -64,15 +66,17 @@ class VendorEditAddressState extends State { } void _onChanged() { - final vendor = widget.viewModel.vendor.rebuild((b) => b - ..address1 = _address1Controller.text.trim() - ..address2 = _address2Controller.text.trim() - ..city = _cityController.text.trim() - ..state = _stateController.text.trim() - ..postalCode = _postalCodeController.text.trim()); - if (vendor != widget.viewModel.vendor) { - widget.viewModel.onChanged(vendor); - } + _debouncer.run(() { + final vendor = widget.viewModel.vendor.rebuild((b) => b + ..address1 = _address1Controller.text.trim() + ..address2 = _address2Controller.text.trim() + ..city = _cityController.text.trim() + ..state = _stateController.text.trim() + ..postalCode = _postalCodeController.text.trim()); + if (vendor != widget.viewModel.vendor) { + widget.viewModel.onChanged(vendor); + } + }); } @override diff --git a/lib/ui/vendor/edit/vendor_edit_contacts.dart b/lib/ui/vendor/edit/vendor_edit_contacts.dart index 5e7e5c59a..c3e1a9bf4 100644 --- a/lib/ui/vendor/edit/vendor_edit_contacts.dart +++ b/lib/ui/vendor/edit/vendor_edit_contacts.dart @@ -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/forms/custom_field.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'; class VendorEditContacts extends StatefulWidget { @@ -157,6 +158,7 @@ class ContactEditDetailsState extends State { final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); + final _debouncer = Debouncer(); List _controllers = []; @override @@ -201,14 +203,16 @@ class ContactEditDetailsState extends State { } void _onChanged() { - final contact = widget.contact.rebuild((b) => b - ..firstName = _firstNameController.text.trim() - ..lastName = _lastNameController.text.trim() - ..email = _emailController.text.trim() - ..phone = _phoneController.text.trim()); - if (contact != widget.contact) { - widget.viewModel.onChangedContact(contact, widget.index); - } + _debouncer.run(() { + final contact = widget.contact.rebuild((b) => b + ..firstName = _firstNameController.text.trim() + ..lastName = _lastNameController.text.trim() + ..email = _emailController.text.trim() + ..phone = _phoneController.text.trim()); + if (contact != widget.contact) { + widget.viewModel.onChangedContact(contact, widget.index); + } + }); } @override diff --git a/lib/ui/vendor/edit/vendor_edit_details.dart b/lib/ui/vendor/edit/vendor_edit_details.dart index e39afb6e8..cd320d684 100644 --- a/lib/ui/vendor/edit/vendor_edit_details.dart +++ b/lib/ui/vendor/edit/vendor_edit_details.dart @@ -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/decorated_form_field.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'; class VendorEditDetails extends StatefulWidget { @@ -28,6 +29,7 @@ class VendorEditDetailsState extends State { final _custom1Controller = TextEditingController(); final _custom2Controller = TextEditingController(); + final _debouncer = Debouncer(); final List _controllers = []; @override @@ -71,18 +73,20 @@ class VendorEditDetailsState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final vendor = viewModel.vendor.rebuild((b) => b - ..name = _nameController.text.trim() - ..idNumber = _idNumberController.text.trim() - ..vatNumber = _vatNumberController.text.trim() - ..website = _websiteController.text.trim() - ..workPhone = _phoneController.text.trim() - ..customValue1 = _custom1Controller.text.trim() - ..customValue2 = _custom2Controller.text.trim()); - if (vendor != viewModel.vendor) { - viewModel.onChanged(vendor); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final vendor = viewModel.vendor.rebuild((b) => b + ..name = _nameController.text.trim() + ..idNumber = _idNumberController.text.trim() + ..vatNumber = _vatNumberController.text.trim() + ..website = _websiteController.text.trim() + ..workPhone = _phoneController.text.trim() + ..customValue1 = _custom1Controller.text.trim() + ..customValue2 = _custom2Controller.text.trim()); + if (vendor != viewModel.vendor) { + viewModel.onChanged(vendor); + } + }); } @override diff --git a/lib/ui/vendor/edit/vendor_edit_notes.dart b/lib/ui/vendor/edit/vendor_edit_notes.dart index 0d2449d72..855a9e654 100644 --- a/lib/ui/vendor/edit/vendor_edit_notes.dart +++ b/lib/ui/vendor/edit/vendor_edit_notes.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:invoiceninja_flutter/data/models/entities.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/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/redux/static/static_selectors.dart'; @@ -24,6 +25,7 @@ class VendorEditNotesState extends State { final _privateNotesController = TextEditingController(); final List _controllers = []; + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -56,13 +58,15 @@ class VendorEditNotesState extends State { } void _onChanged() { - final viewModel = widget.viewModel; - final vendor = viewModel.vendor.rebuild((b) => b - //..publicNotes = _publicNotesController.text - ..privateNotes = _privateNotesController.text); - if (vendor != viewModel.vendor) { - viewModel.onChanged(vendor); - } + _debouncer.run(() { + final viewModel = widget.viewModel; + final vendor = viewModel.vendor.rebuild((b) => b + //..publicNotes = _publicNotesController.text + ..privateNotes = _privateNotesController.text); + if (vendor != viewModel.vendor) { + viewModel.onChanged(vendor); + } + }); } @override diff --git a/samples/form_redux.dart b/samples/form_redux.dart index 26b871a98..b456f8da4 100644 --- a/samples/form_redux.dart +++ b/samples/form_redux.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/utils/completers.dart'; import 'package:redux/redux.dart'; import 'package:redux_logging/redux_logging.dart'; @@ -193,6 +194,7 @@ class ClientPage extends StatefulWidget { class _ClientPageState extends State { final _nameController = new TextEditingController(); + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -211,11 +213,13 @@ class _ClientPageState extends State { } void _onChanged() { - final name = _nameController.text.trim(); - final store = StoreProvider.of(context); - if (name != store.state.client.name) { - store.dispatch(UpdateClient(name)); - } + _debouncer.run(() { + final name = _nameController.text.trim(); + final store = StoreProvider.of(context); + if (name != store.state.client.name) { + store.dispatch(UpdateClient(name)); + } + }); } @override @@ -277,6 +281,7 @@ class ContactForm extends StatefulWidget { class _ContactFormState extends State { final _emailController = new TextEditingController(); + final _debouncer = Debouncer(); @override void didChangeDependencies() { @@ -294,11 +299,13 @@ class _ContactFormState extends State { } void _onChanged() { - final store = StoreProvider.of(context); - final email = _emailController.text.trim(); - if (email != widget.contact.email) { - store.dispatch(UpdateContact(email: email, index: widget.index)); - } + _debouncer.run(() { + final store = StoreProvider.of(context); + final email = _emailController.text.trim(); + if (email != widget.contact.email) { + store.dispatch(UpdateContact(email: email, index: widget.index)); + } + }); } @override diff --git a/stubs/ui/stub/edit/stub_edit b/stubs/ui/stub/edit/stub_edit index 723f51358..fd2fac943 100644 --- a/stubs/ui/stub/edit/stub_edit +++ b/stubs/ui/stub/edit/stub_edit @@ -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/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; +import 'package:invoiceninja_flutter/utils/completers.dart'; class StubEdit extends StatefulWidget { const StubEdit({ @@ -20,7 +21,7 @@ class StubEdit extends StatefulWidget { class _StubEditState extends State { static final GlobalKey _formKey = GlobalKey(); -final _debouncer = Debouncer(); + final _debouncer = Debouncer(); // STARTER: controllers - do not remove comment @@ -54,12 +55,15 @@ final _debouncer = Debouncer(); } void _onChanged() { + _debouncer.run(() { + final stub = widget.viewModel.stub.rebuild((b) => b // STARTER: set value - do not remove comment ); if (stub != widget.viewModel.stub) { - widget.viewModel.onChanged(stub); + widget.viewModel.onChanged(stub); } + }); } @override