1차 보완(0.1.1+14) 내용 합치기
This commit is contained in:
@@ -12,6 +12,7 @@ import '../../core/ui/app_icons.dart';
|
||||
import '../auth/auth.dart';
|
||||
import '../auth/auth_repository.dart';
|
||||
import '../home/home_screen.dart' show formatPop;
|
||||
import '../quest/location_consent.dart';
|
||||
import 'my_data.dart';
|
||||
import 'notice_screens.dart';
|
||||
import 'payment_screens.dart';
|
||||
@@ -24,7 +25,7 @@ import '../../core/ui/bottom_inset.dart';
|
||||
/// 설정 — 화면 대조 원장 F6 · Figma `354:222008`.
|
||||
///
|
||||
/// 명세 `554:22634` — 계정 정보(닉네임 · 가입 이메일)
|
||||
/// 명세 `554:22797` — SNS 연동. *동일 이메일만 연동 가능*. 행의 「연결」에서 바로 제공자
|
||||
/// 명세 `554:22797` — SNS 연동. 행의 「연결」에서 바로 제공자
|
||||
/// 시트를 띄운다(시안 F6-05~07 · 대표 결정 — 별도 연동 화면을 거치지 않는다).
|
||||
/// 명세 `554:22831` — 푸시 알림 · 차단 · 언어
|
||||
/// 명세 `554:22857` — 공지사항 · 1:1 문의접수 · 앱 버전
|
||||
@@ -65,6 +66,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
Map<AuthProviderKind, String?> _linked = const {};
|
||||
({String current, bool latest})? _version;
|
||||
|
||||
/// 위치기반 서비스 약관 동의 상태(Q-E1 · R02). 못 읽었으면 null — 토글을 그리지 않는다.
|
||||
bool? _locationConsent;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -74,8 +78,15 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
Future<void> _load() async {
|
||||
final profile = await widget.repository.profile();
|
||||
final version = await widget.repository.appVersion();
|
||||
bool? location;
|
||||
try {
|
||||
location = await widget.repository.locationConsent.granted();
|
||||
} catch (_) {
|
||||
location = null;
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_locationConsent = location;
|
||||
_profile = profile;
|
||||
_linked = widget.linker.linkedAccounts;
|
||||
_version = version;
|
||||
@@ -166,6 +177,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
down: true,
|
||||
onTap: _pickLanguage,
|
||||
),
|
||||
if (_locationConsent case final on?)
|
||||
_SwitchRow(
|
||||
label: l10n.settingsLocationConsent,
|
||||
value: on,
|
||||
onChanged: _setLocationConsent,
|
||||
),
|
||||
],
|
||||
),
|
||||
MyGroup(
|
||||
@@ -254,7 +271,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
/// 설정 행에서 바로 연결 · 해제한다(시안 F6-05~07 — 설정 위에 OS 제공자 시트가 뜬다).
|
||||
///
|
||||
/// 연결은 제공자 시트로 곧장 가고, 해제는 확인 팝업(시안 `554:23257`)을 거친다.
|
||||
/// 이메일이 다르면(E-AUTH-08 · [sameAccountIdentity]) 시안 `554:23103` 안내 팝업.
|
||||
/// 그 소셜 계정이 다른 FANUZU 계정에 이미 붙어 있으면(E-AUTH-08) 시안 `554:23103` 안내 팝업.
|
||||
/// 명세의 「동일 이메일만 연동 가능」은 통합검토회신 v2.3 **Q-E8** 이 대체했다 — 이메일은 소유 확인이 아니다.
|
||||
Future<void> _toggleLink(AuthProviderKind provider) async {
|
||||
final connected = _linked.containsKey(provider);
|
||||
if (connected) {
|
||||
@@ -274,8 +292,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
// 로컬 값을 뒤집으면 서버가 거절한 연결이 붙은 것처럼 보인다.
|
||||
setState(() => _linked = widget.linker.linkedAccounts);
|
||||
switch (outcome) {
|
||||
case AuthFailed(code: 'E-AUTH-08'):
|
||||
await _notice(context.l10n.settingsSameEmailOnly);
|
||||
case AuthFailed(code: 'E-AUTH-08', :final message):
|
||||
await _notice(message);
|
||||
case AuthFailed(:final code, :final message):
|
||||
_toast('[$code] $message');
|
||||
case AuthNotConfigured():
|
||||
@@ -335,6 +353,24 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
await LocaleScope.maybeOf(context)?.select(picked);
|
||||
}
|
||||
|
||||
/// 위치기반 서비스 약관 동의 · 철회(Q-E1 · R02). 켜면 동의 창을 거쳐 기록하고, 끄면 철회 행을 남긴다.
|
||||
/// Figma 설정 시안에 없는 줄이다 — 동의를 철회할 수단이 있어야 해 언어 아래에 토글 하나를 둔다.
|
||||
Future<void> _setLocationConsent(bool on) async {
|
||||
final consent = widget.repository.locationConsent;
|
||||
var now = on;
|
||||
if (on) {
|
||||
now = await ensureLocationConsent(context, consent);
|
||||
} else {
|
||||
try {
|
||||
await consent.record(false);
|
||||
} catch (_) {
|
||||
now = true;
|
||||
if (mounted) _toast(context.l10n.commonRequestFailed);
|
||||
}
|
||||
}
|
||||
if (mounted) setState(() => _locationConsent = now);
|
||||
}
|
||||
|
||||
/// 서비스 탈퇴 — 명세 `554:24885` 「연동 상태값이 있을 경우 비정상 탈퇴 처리 · 게시물 보존 ·
|
||||
/// 탈퇴 처리 후 앱 종료」. 연동이 남아 있으면 비정상 탈퇴 안내(`554:24908` · `374:14699`)만 띄운다.
|
||||
/// 서버도 같은 조건을 다시 본다(E-AUTH-14).
|
||||
@@ -400,6 +436,41 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 켜고 끄는 줄 — 푸시 알림 설정 화면의 토글과 같은 모양.
|
||||
class _SwitchRow extends StatelessWidget {
|
||||
const _SwitchRow({
|
||||
required this.label,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final bool value;
|
||||
final ValueChanged<bool> onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SizedBox(
|
||||
height: 24,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(label, style: myText(16, FontWeight.w600, height: 1)),
|
||||
),
|
||||
Switch(
|
||||
value: value,
|
||||
activeThumbColor: AppColors.onCosmic,
|
||||
activeTrackColor: AppColors.cosmicAccent,
|
||||
inactiveThumbColor: const Color(0xFF3A3A3A),
|
||||
inactiveTrackColor: const Color(0xFF2C2C2C),
|
||||
trackOutlineColor: const WidgetStatePropertyAll(Colors.transparent),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 「닉네임 · BTS_Hong」 — 둘 다 16/600, 값은 #bbbbbb.
|
||||
class _ValueRow extends StatelessWidget {
|
||||
const _ValueRow({required this.label, required this.value});
|
||||
|
||||
Reference in New Issue
Block a user