feat(market): saved searches with in-app alerts (Wallapop-style)

Save the current market search (query + facets) and get notified when a
matching offer appears in your zone while the app is open, with a catch-up
scan on start. Adds a save affordance in the search bar, a saved-searches
list (apply/delete) with a per-search new-match badge, an AppBar entry
badged with the unseen total, and notification-tap routing to the list.
Alerts evaluate against the user's current area, dedup via seen keys, and
skip own/blocked/hidden/non-active offers. en+es strings.
This commit is contained in:
vjrj 2026-07-17 13:10:52 +02:00
parent c0cd299408
commit 93028c4933
9 changed files with 549 additions and 4 deletions

View file

@ -20,6 +20,8 @@ import 'services/plantare_service.dart';
import 'services/profile_cache.dart';
import 'services/profile_store.dart';
import 'services/saved_offers_store.dart';
import 'services/saved_search_alert_service.dart';
import 'services/saved_searches_store.dart';
import 'services/social_account_store.dart';
import 'services/social_connection.dart';
import 'services/social_service.dart';
@ -70,12 +72,16 @@ class _BootstrapState extends State<Bootstrap> {
getIt.isRegistered<SyncService>() ? getIt<SyncService>() : null;
final plantares =
getIt.isRegistered<PlantareService>() ? getIt<PlantareService>() : null;
// Subscribe the inbox + sync + plantaré listeners BEFORE the shared
// connection starts connecting, so the first session is caught; then bring
// the connection up.
final savedSearchAlerts = getIt.isRegistered<SavedSearchAlertService>()
? getIt<SavedSearchAlertService>()
: null;
// Subscribe the inbox + sync + plantaré + saved-search listeners BEFORE the
// shared connection starts connecting, so the first session is caught; then
// bring the connection up.
inbox?.start();
sync?.start();
plantares?.start();
savedSearchAlerts?.start();
connection?.start();
return TaneApp(
@ -92,6 +98,7 @@ class _BootstrapState extends State<Bootstrap> {
profileStore: getIt<ProfileStore>(),
profileCache: getIt<ProfileCache>(),
savedOffers: getIt<SavedOffersStore>(),
savedSearches: getIt<SavedSearchesStore>(),
socialAccounts: getIt<SocialAccountStore>(),
inbox: inbox,
notifications: notifications,