feat(app): stabilize recommendation flow
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
@@ -69,13 +70,31 @@ final currentLocationProvider = FutureProvider<Position?>((ref) async {
|
||||
});
|
||||
|
||||
/// 위치 스트림 Provider
|
||||
final locationStreamProvider = StreamProvider<Position>((ref) {
|
||||
return Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 10, // 10미터 이상 이동 시 업데이트
|
||||
),
|
||||
);
|
||||
final locationStreamProvider = StreamProvider<Position>((ref) async* {
|
||||
if (kIsWeb) {
|
||||
AppLogger.debug('[location] web detected, emit fallback immediately');
|
||||
yield defaultPosition();
|
||||
return;
|
||||
}
|
||||
|
||||
final status = await Permission.location.status;
|
||||
if (!status.isGranted) {
|
||||
AppLogger.debug('[location] permission not granted, emit fallback');
|
||||
yield defaultPosition();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
yield* Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 10, // 10미터 이상 이동 시 업데이트
|
||||
),
|
||||
);
|
||||
} catch (_) {
|
||||
AppLogger.error('[location] position stream failed, emit fallback');
|
||||
yield defaultPosition();
|
||||
}
|
||||
});
|
||||
|
||||
/// 초기 3초 내 위치를 가져오지 못하면 기본 좌표를 우선 반환하고,
|
||||
@@ -83,20 +102,30 @@ final locationStreamProvider = StreamProvider<Position>((ref) {
|
||||
final currentLocationWithFallbackProvider = StreamProvider<Position>((
|
||||
ref,
|
||||
) async* {
|
||||
final initial = await Future.any([
|
||||
ref
|
||||
.watch(currentLocationProvider.future)
|
||||
.then((pos) => pos ?? defaultPosition()),
|
||||
Future<Position>.delayed(
|
||||
const Duration(seconds: 3),
|
||||
() => defaultPosition(),
|
||||
),
|
||||
]).catchError((_) => defaultPosition());
|
||||
AppLogger.debug('[location] emit fallback immediately (safe start)');
|
||||
// 웹/권한 거부 상황에서는 즉시 기본 좌표를 먼저 흘려보내 리스트 로딩을 막는다.
|
||||
final fallback = defaultPosition();
|
||||
yield fallback;
|
||||
|
||||
yield initial;
|
||||
final initial = await Future.any([
|
||||
ref.watch(currentLocationProvider.future).then((pos) => pos ?? fallback),
|
||||
Future<Position>.delayed(const Duration(seconds: 3), () => fallback),
|
||||
]).catchError((_) => fallback);
|
||||
|
||||
if (initial.latitude != fallback.latitude ||
|
||||
initial.longitude != fallback.longitude) {
|
||||
AppLogger.debug(
|
||||
'[location] resolved initial position: '
|
||||
'${initial.latitude}, ${initial.longitude}',
|
||||
);
|
||||
yield initial;
|
||||
} else {
|
||||
AppLogger.debug('[location] initial resolved to fallback');
|
||||
}
|
||||
|
||||
yield* ref.watch(locationStreamProvider.stream).handleError((_) {
|
||||
// 스트림 오류는 무시하고 마지막 위치를 유지
|
||||
AppLogger.error('[location] stream error, keeping last position');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user