import 'package:flutter/material.dart'; import 'package:friendly_map/modules/app/app.dart'; import 'package:friendly_map/modules/platform/platform.dart'; import 'package:friendly_map/modules/storage/storage.dart'; import 'package:friendly_map/modules/visibility/visibility.dart'; import '../app_scope.dart'; import '../theme.dart'; import '../widgets/async_view.dart'; import '../widgets/common.dart'; import '../widgets/radar_view.dart'; class _LocData { const _LocData(this.on, this.mine, this.friends, this.recipients); final bool on; final GeoPoint? mine; final List friends; final Map recipients; } /// 위치: 켜면 공개 범위 표에서 허용한 친구에게만 내 위치를 보내고, 친구들이 보내 준 위치를 레이더로 본다. class LocationScreen extends StatefulWidget { const LocationScreen({super.key}); @override State createState() => _LocationScreenState(); } class _LocationScreenState extends State { bool _busy = false; Future<_LocData> _load(FriendlyApp app) async => _LocData(await app.location.sharingOn(), await app.location.mine(), await app.location.friends(), await app.location.recipients()); Future _share() async { final app = AppScope.of(context).app; setState(() => _busy = true); final n = await app.location.shareNow(); if (!mounted) return; setState(() => _busy = false); showNote(context, n == 0 ? '보낼 수 있는 친구가 없거나 위치를 얻지 못했어요.' : '친구 $n명에게 위치를 보냈어요.'); } @override Widget build(BuildContext context) { final app = AppScope.of(context).app; return Scaffold( appBar: AppBar(title: const Text('위치')), body: AsyncView<_LocData>( load: _load, builder: (context, d) { final dots = [ if (d.mine != null) for (final f in d.friends) RadarDot(f.person.name, bearingDegrees(d.mine!, f.point), distanceMeters(d.mine!, f.point)), ]; return ListView(padding: const EdgeInsets.only(bottom: 32), children: [ Panel( child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ ToggleRow( title: '내 위치 공유', subtitle: app.location.available ? '꺼져 있으면 아무에게도 보내지 않아요' : '이 기기에서는 위치를 쓸 수 없어요', value: d.on, onChanged: (v) => app.location.setSharing(app.location.available && v), ), if (d.on) ...[ Text( d.recipients.isEmpty ? '받을 수 있는 친구가 없어요. 내 정보의 공개 범위 표에서 "실시간 위치"를 열어 주세요.' : '받는 친구: ${d.recipients.entries.map((e) => '${e.key.name}${e.value == VLevel.partial ? '(대략)' : ''}').join(', ')}', style: const TextStyle(fontSize: 12, color: Pal.muted, height: 1.5), ), const SizedBox(height: 8), FilledButton.tonal(onPressed: _busy ? null : _share, child: const Text('지금 보내기')), ], ]), ), const SectionHeader('친구 위치'), if (d.mine == null) const EmptyNote('내 위치를 얻지 못했어요. 위치 권한과 GPS 를 확인해 주세요.'), Center(child: RadarView(dots: dots)), if (d.friends.isEmpty) const EmptyNote('친구가 보내 준 위치가 아직 없어요.'), for (final f in d.friends) ListTile( leading: Avatar(f.person.name, size: 40), title: Text(f.person.name), subtitle: Text( d.mine == null ? '${f.point.lat.toStringAsFixed(3)}, ${f.point.lng.toStringAsFixed(3)}' : '${distanceLabel(distanceMeters(d.mine!, f.point))} · ${shortTime(f.at)}', style: const TextStyle(fontSize: 12, color: Pal.muted), ), ), ]); }, ), ); } }