feat(app): finalize ad gated flows and weather
- add AppLogger and replace scattered print logging\n- implement ad-gated recommendation flow with reminder handling and calendar link\n- complete Bluetooth share pipeline with ad gate and merge\n- integrate KMA weather API with caching and dart-define decoding\n- add NaverUrlProcessor refactor and restore restaurant repository tests
This commit is contained in:
@@ -1,7 +1,28 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
const double _defaultLatitude = 37.5666805;
|
||||
const double _defaultLongitude = 126.9784147;
|
||||
|
||||
/// 위치 정보를 사용할 수 없을 때 활용하는 기본 좌표(서울 시청).
|
||||
Position defaultPosition() {
|
||||
return Position(
|
||||
latitude: _defaultLatitude,
|
||||
longitude: _defaultLongitude,
|
||||
timestamp: DateTime.now(),
|
||||
accuracy: 0,
|
||||
altitude: 0,
|
||||
altitudeAccuracy: 0,
|
||||
heading: 0,
|
||||
headingAccuracy: 0,
|
||||
speed: 0,
|
||||
speedAccuracy: 0,
|
||||
isMocked: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// 위치 권한 상태 Provider
|
||||
final locationPermissionProvider = FutureProvider<PermissionStatus>((
|
||||
ref,
|
||||
@@ -18,14 +39,16 @@ final currentLocationProvider = FutureProvider<Position?>((ref) async {
|
||||
// 권한이 없으면 요청
|
||||
final result = await Permission.location.request();
|
||||
if (!result.isGranted) {
|
||||
return null;
|
||||
AppLogger.debug('위치 권한 거부됨, 기본 좌표(서울 시청) 사용');
|
||||
return defaultPosition();
|
||||
}
|
||||
}
|
||||
|
||||
// 위치 서비스 활성화 확인
|
||||
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
throw Exception('위치 서비스가 비활성화되어 있습니다');
|
||||
AppLogger.debug('위치 서비스 비활성화, 기본 좌표(서울 시청) 사용');
|
||||
return defaultPosition();
|
||||
}
|
||||
|
||||
// 현재 위치 가져오기
|
||||
@@ -36,7 +59,12 @@ final currentLocationProvider = FutureProvider<Position?>((ref) async {
|
||||
);
|
||||
} catch (e) {
|
||||
// 타임아웃이나 오류 발생 시 마지막 알려진 위치 반환
|
||||
return await Geolocator.getLastKnownPosition();
|
||||
final lastPosition = await Geolocator.getLastKnownPosition();
|
||||
if (lastPosition != null) {
|
||||
return lastPosition;
|
||||
}
|
||||
AppLogger.debug('현재 위치를 가져오지 못해 기본 좌표(서울 시청)를 반환');
|
||||
return defaultPosition();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -83,7 +111,8 @@ class LocationNotifier extends StateNotifier<AsyncValue<Position?>> {
|
||||
if (!permissionStatus.isGranted) {
|
||||
final granted = await requestLocationPermission();
|
||||
if (!granted) {
|
||||
state = const AsyncValue.data(null);
|
||||
AppLogger.debug('위치 권한 거부됨, 기본 좌표(서울 시청)로 대체');
|
||||
state = AsyncValue.data(defaultPosition());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +120,8 @@ class LocationNotifier extends StateNotifier<AsyncValue<Position?>> {
|
||||
// 위치 서비스 확인
|
||||
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
state = AsyncValue.error('위치 서비스가 비활성화되어 있습니다', StackTrace.current);
|
||||
AppLogger.debug('위치 서비스 비활성화, 기본 좌표(서울 시청)로 대체');
|
||||
state = AsyncValue.data(defaultPosition());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -102,13 +132,18 @@ class LocationNotifier extends StateNotifier<AsyncValue<Position?>> {
|
||||
);
|
||||
|
||||
state = AsyncValue.data(position);
|
||||
} catch (e, stack) {
|
||||
} catch (e) {
|
||||
// 오류 발생 시 마지막 알려진 위치 시도
|
||||
try {
|
||||
final lastPosition = await Geolocator.getLastKnownPosition();
|
||||
state = AsyncValue.data(lastPosition);
|
||||
if (lastPosition != null) {
|
||||
state = AsyncValue.data(lastPosition);
|
||||
} else {
|
||||
AppLogger.debug('마지막 위치도 없어 기본 좌표(서울 시청)로 대체');
|
||||
state = AsyncValue.data(defaultPosition());
|
||||
}
|
||||
} catch (_) {
|
||||
state = AsyncValue.error(e, stack);
|
||||
state = AsyncValue.data(defaultPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user