feat(block2): 'use my location' — set the sharing area without typing a code
Makes the coarse area human, per feedback that a typed code is jargon. - CoarseLocationProvider interface + geolocator-backed impl (BSD-3): low accuracy only, returns null on any denial/error (degrades quietly). Behind an interface so it's fakeable and the plugin stays at the composition root. - Config sheet: a 'Use my approximate location' button (shown only when a provider is wired) fills the area from the device position, reduced to a 5-char geohash via commons_core's Geohash — a precise fix never leaves the device. 'Couldn't get your location' on failure. - Threaded via TaneApp(location); main wires GeolocatorCoarseLocation. - Platform: ACCESS_COARSE_LOCATION (Android) + NSLocationWhenInUseUsageDescription (iOS), both scoped to the coarse-area use. - i18n en/es/pt. Widget test fills the area from a fake location. 8 tests green.
This commit is contained in:
parent
f8f73c4153
commit
492bc62025
15 changed files with 176 additions and 10 deletions
|
|
@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart';
|
|||
import 'data/species_repository.dart';
|
||||
import 'data/variety_repository.dart';
|
||||
import 'i18n/strings.g.dart';
|
||||
import 'services/coarse_location.dart';
|
||||
import 'services/onboarding_store.dart';
|
||||
import 'services/social_service.dart';
|
||||
import 'services/social_settings.dart';
|
||||
|
|
@ -31,6 +32,7 @@ class TaneApp extends StatelessWidget {
|
|||
required this.onboarding,
|
||||
this.social,
|
||||
this.socialSettings,
|
||||
this.location,
|
||||
this.showIntro = false,
|
||||
super.key,
|
||||
}) : _router = _buildRouter(
|
||||
|
|
@ -39,6 +41,7 @@ class TaneApp extends StatelessWidget {
|
|||
showIntro,
|
||||
social,
|
||||
socialSettings,
|
||||
location,
|
||||
);
|
||||
|
||||
final VarietyRepository repository;
|
||||
|
|
@ -49,6 +52,9 @@ class TaneApp extends StatelessWidget {
|
|||
/// null the market stays a "coming soon" card and `/market` is not routed.
|
||||
final SocialService? social;
|
||||
final SocialSettings? socialSettings;
|
||||
|
||||
/// Optional device-location source for the market's "use my location".
|
||||
final CoarseLocationProvider? location;
|
||||
final bool showIntro;
|
||||
final GoRouter _router;
|
||||
|
||||
|
|
@ -58,6 +64,7 @@ class TaneApp extends StatelessWidget {
|
|||
bool showIntro,
|
||||
SocialService? social,
|
||||
SocialSettings? socialSettings,
|
||||
CoarseLocationProvider? location,
|
||||
) {
|
||||
return GoRouter(
|
||||
initialLocation: showIntro ? '/intro' : '/',
|
||||
|
|
@ -70,8 +77,11 @@ class TaneApp extends StatelessWidget {
|
|||
if (social != null && socialSettings != null)
|
||||
GoRoute(
|
||||
path: '/market',
|
||||
builder: (context, state) =>
|
||||
MarketScreen(social: social, settings: socialSettings),
|
||||
builder: (context, state) => MarketScreen(
|
||||
social: social,
|
||||
settings: socialSettings,
|
||||
location: location,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/intro',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue