Skip to content

Commit 9f42f88

Browse files
committed
chore: activate loader only after typing
1 parent 0c6b217 commit 9f42f88

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

app/lib/ui/components/form_input/phone_number/phone_number_input_demo_screen.dart

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,16 @@ class _PhoneNumberInputDemo extends StatefulWidget {
121121
class _PhoneNumberInputDemoState extends State<_PhoneNumberInputDemo> {
122122
late final TextEditingController controller;
123123
late final FocusNode textInputFocus;
124+
bool _isTyping = false;
124125
Country? selectedCountry;
125126

126127
@override
127128
void initState() {
128129
super.initState();
129130
controller = TextEditingController();
130131
textInputFocus = FocusNode();
132+
133+
controller.addListener(_handleTextChanged);
131134
}
132135

133136
void onCountryChanged(Country country) {
@@ -147,9 +150,29 @@ class _PhoneNumberInputDemoState extends State<_PhoneNumberInputDemo> {
147150
void dispose() {
148151
controller.dispose();
149152
textInputFocus.dispose();
153+
controller.removeListener(_handleTextChanged);
150154
super.dispose();
151155
}
152156

157+
void _handleTextChanged() {
158+
// Get the current text from the controller
159+
final text = controller.text ?? '';
160+
161+
// Trigger a rebuild only when the "typing" state actually changes
162+
// (prevents unnecessary rebuilds on every keystroke)
163+
final typing = text.isNotEmpty;
164+
if (typing != _isTyping) {
165+
setState(() {
166+
_isTyping = typing;
167+
});
168+
}
169+
170+
final customizationState = FormFieldsCustomization.of(context);
171+
if (customizationState != null) {
172+
customizationState.isTyping = typing;
173+
}
174+
}
175+
153176
@override
154177
Widget build(BuildContext context) {
155178
final customizationState = FormFieldsCustomization.of(context)!; // safe to use !
@@ -353,7 +376,7 @@ class _CustomizationContentState extends State<_CustomizationContent> {
353376
CustomizableSwitch(
354377
title: context.l10n.app_components_common_loader_label,
355378
value: customizationState.hasLoader,
356-
onChanged: customizationState.isLoaderWhenError || customizationState.isLoaderWhenEnabled || customizationState.isEnabledWhenPlaceHolderIsNotEmpty
379+
onChanged: customizationState.isLoaderWhenError || !customizationState.isTyping || customizationState.isLoaderWhenEnabled || customizationState.isEnabledWhenPlaceHolderIsNotEmpty
357380
? null
358381
: (value) {
359382
customizationState.hasLoader = value;

ouds_core/lib/components/form_input/ouds_phone_number_input.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
141141
final bool _isHovered = false;
142142
bool _isFocused = false;
143143
FocusNode? _internalFocusNode;
144+
bool _isTyping = false;
144145

145146
/// init countryselector
146147
Country countrySelected = Country.empty();
@@ -153,6 +154,13 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
153154
@override
154155
void initState() {
155156
super.initState();
157+
158+
// Listen to the external controller if provided
159+
// This allows us to detect text changes in real time.
160+
if (widget.controller != null) {
161+
widget.controller!.addListener(_handleTextChanged);
162+
}
163+
156164
if (widget.focusNode == null) {
157165
_internalFocusNode = FocusNode();
158166
_internalFocusNode!.addListener(_handleFocusChange);
@@ -161,6 +169,29 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
161169
}
162170
}
163171

172+
void _handleTextChanged() {
173+
// Get the current text from the controller
174+
final text = widget.controller?.text ?? '';
175+
176+
// Trigger a rebuild only when the "typing" state actually changes
177+
// (prevents unnecessary rebuilds on every keystroke)
178+
final typing = text.isNotEmpty;
179+
if (typing != _isTyping) {
180+
setState(() {
181+
_isTyping = typing;
182+
});
183+
}
184+
}
185+
186+
@override
187+
void didUpdateWidget(covariant OudsPhoneNumberInput oldWidget) {
188+
super.didUpdateWidget(oldWidget);
189+
if (oldWidget.controller != widget.controller) {
190+
oldWidget.controller?.removeListener(_handleTextChanged);
191+
widget.controller?.addListener(_handleTextChanged);
192+
}
193+
}
194+
164195
void _handleFocusChange() {
165196
setState(() {
166197
_isFocused = (widget.focusNode ?? _internalFocusNode)!.hasFocus;
@@ -169,6 +200,8 @@ class _OudsPhoneNumberInputState extends State<OudsPhoneNumberInput> {
169200

170201
@override
171202
void dispose() {
203+
widget.controller?.removeListener(_handleTextChanged);
204+
172205
if (_internalFocusNode != null) {
173206
_internalFocusNode!.removeListener(_handleFocusChange);
174207
_internalFocusNode!.dispose();

0 commit comments

Comments
 (0)