From 0f2a3b5324eb9c28891ea0f1eb1ee65e4fa00542 Mon Sep 17 00:00:00 2001 From: alexdivadi Date: Sat, 14 Feb 2026 19:47:22 -0600 Subject: [PATCH] fix: address widget --- .../inputs/any_step_address_field.dart | 71 +++++++++++++++---- .../event_detail/event_detail_form.dart | 5 ++ .../presentation/profile/profile_form.dart | 5 ++ 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/lib/core/common/widgets/inputs/any_step_address_field.dart b/lib/core/common/widgets/inputs/any_step_address_field.dart index 4e75395..9cee5f7 100644 --- a/lib/core/common/widgets/inputs/any_step_address_field.dart +++ b/lib/core/common/widgets/inputs/any_step_address_field.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:anystep/core/common/constants/spacing.dart'; import 'package:anystep/core/common/utils/log_utils.dart'; import 'package:anystep/core/common/widgets/inputs/any_step_text_field.dart'; +import 'package:anystep/core/config/theme/colors.dart'; import 'package:anystep/core/features/location/data/address_repository.dart'; import 'package:anystep/core/features/location/data/places_api_client.dart'; import 'package:anystep/core/features/location/domain/address_model.dart'; @@ -90,6 +91,8 @@ class _AnyStepAddressFieldState extends ConsumerState { bool _isLoading = false; bool _isSearchDisabled = false; bool _isApplyingSelection = false; + bool _isSelectingFromList = false; + bool _searchActive = false; bool _isSaving = false; List _dbResults = []; List _predictions = []; @@ -136,10 +139,15 @@ class _AnyStepAddressFieldState extends ConsumerState { void _handleFocusChange() { if (!_streetFocusNode.hasFocus) { - setState(() { - _dbResults = []; - _predictions = []; - _error = null; + _searchActive = false; + if (_isSelectingFromList) return; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted || _isSelectingFromList) return; + setState(() { + _dbResults = []; + _predictions = []; + _error = null; + }); }); } } @@ -168,10 +176,12 @@ class _AnyStepAddressFieldState extends ConsumerState { } void _onStreetChanged(String? value) { + if (_isApplyingSelection) return; _clearPlaceFieldsIfManualEdit(); _debounce?.cancel(); final query = value?.trim() ?? ''; if (query.isEmpty) { + _searchActive = false; setState(() { _dbResults = []; _predictions = []; @@ -179,6 +189,7 @@ class _AnyStepAddressFieldState extends ConsumerState { }); return; } + _searchActive = true; _debounce = Timer(const Duration(milliseconds: 300), () async { setState(() { _isLoading = true; @@ -230,14 +241,21 @@ class _AnyStepAddressFieldState extends ConsumerState { _latitude = address.latitude; _longitude = address.longitude; _addressId = address.id; - form.fields[widget.addressIdFieldName]?.didChange(address.id); - widget.onAddressSaved?.call(address.id); + if (address.id != null) { + form.fields[widget.addressIdFieldName]?.didChange(address.id); + form.save(); + widget.onAddressSaved?.call(address.id); + } else { + Log.w('Selected address missing id', address.toJson()); + } _streetController.text = address.street; _streetController.selection = TextSelection.fromPosition( TextPosition(offset: _streetController.text.length), ); _streetFocusNode.unfocus(); _isApplyingSelection = false; + _searchActive = false; + _isSelectingFromList = false; setState(() { _dbResults = []; _predictions = []; @@ -270,6 +288,8 @@ class _AnyStepAddressFieldState extends ConsumerState { ); _streetFocusNode.unfocus(); _isApplyingSelection = false; + _searchActive = false; + _isSelectingFromList = false; setState(() { _dbResults = []; _predictions = []; @@ -349,6 +369,18 @@ class _AnyStepAddressFieldState extends ConsumerState { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row( + children: [ + Icon(Icons.warning_amber_rounded, color: AnyStepColors.warning, size: 16), + Expanded( + child: Text( + "An improved address input is coming soon.", + style: Theme.of(context).textTheme.bodySmall, + ), + ), + ], + ), + const SizedBox(height: AnyStepSpacing.sm8), AnyStepTextField( name: 'street', labelText: widget.streetLabelText ?? loc.streetAddress, @@ -378,7 +410,8 @@ class _AnyStepAddressFieldState extends ConsumerState { padding: const EdgeInsets.only(bottom: AnyStepSpacing.sm4), child: Text(loc.noMatchesFound), ), - if (_dbResults.isNotEmpty || (!_isSearchDisabled && _predictions.isNotEmpty)) + if (_searchActive && + (_dbResults.isNotEmpty || (!_isSearchDisabled && _predictions.isNotEmpty))) Card( margin: const EdgeInsets.only(bottom: AnyStepSpacing.sm8), child: ListView.separated( @@ -391,19 +424,27 @@ class _AnyStepAddressFieldState extends ConsumerState { final address = _dbResults[index]; final title = address.name ?? address.formattedAddress; final subtitle = address.name != null ? address.formattedAddress : null; - return ListTile( - title: Text(title), - subtitle: subtitle != null ? Text(subtitle) : null, + return InkWell( + onTapDown: (_) => _isSelectingFromList = true, + onTapCancel: () => _isSelectingFromList = false, onTap: () => _selectAddress(address), + child: ListTile( + title: Text(title), + subtitle: subtitle != null ? Text(subtitle) : null, + ), ); } final prediction = _predictions[index - _dbResults.length]; - return ListTile( - title: Text(prediction.mainText ?? prediction.description), - subtitle: prediction.secondaryText != null - ? Text(prediction.secondaryText!) - : null, + return InkWell( + onTapDown: (_) => _isSelectingFromList = true, + onTapCancel: () => _isSelectingFromList = false, onTap: () => _selectPrediction(prediction), + child: ListTile( + title: Text(prediction.mainText ?? prediction.description), + subtitle: prediction.secondaryText != null + ? Text(prediction.secondaryText!) + : null, + ), ); }, ), diff --git a/lib/core/features/events/presentation/event_detail/event_detail_form.dart b/lib/core/features/events/presentation/event_detail/event_detail_form.dart index b145a7f..5ba0d0e 100644 --- a/lib/core/features/events/presentation/event_detail/event_detail_form.dart +++ b/lib/core/features/events/presentation/event_detail/event_detail_form.dart @@ -135,6 +135,11 @@ class _EventDetailFormState extends ConsumerState { ], ), + const SizedBox(height: AnyStepSpacing.sm4), + Align( + alignment: Alignment.centerLeft, + child: Text(loc.address, style: Theme.of(context).textTheme.titleMedium), + ), const SizedBox(height: AnyStepSpacing.sm4), AnyStepAddressField( formKey: formKey, diff --git a/lib/core/features/profile/presentation/profile/profile_form.dart b/lib/core/features/profile/presentation/profile/profile_form.dart index aaf4f63..cf1f820 100644 --- a/lib/core/features/profile/presentation/profile/profile_form.dart +++ b/lib/core/features/profile/presentation/profile/profile_form.dart @@ -79,6 +79,11 @@ class _ProfileFormState extends ConsumerState { validator: FormBuilderValidators.required(), ), const SizedBox(height: AnyStepSpacing.sm8), + Align( + alignment: Alignment.centerLeft, + child: Text(loc.address, style: Theme.of(context).textTheme.titleMedium), + ), + const SizedBox(height: AnyStepSpacing.sm4), AnyStepAddressField( formKey: _formKey, initialAddressId: widget.user.addressId ?? widget.user.address?.id,