games/packages/service_api/lib/services/session_notifier.dart
2025-11-14 18:03:50 +09:00

101 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'identity_service.dart';
import 'puzzle_service.dart';
class SessionNotifier with ChangeNotifier {
final IdentityService _identityService = IdentityService();
final PuzzleService _puzzleService = PuzzleService();
UserSession? _session;
UserSession? get session => _session;
bool get isLoading => _session == null;
bool get isGuest => _session?.isGuest ?? true;
// 🔽 [수정] 'GoogleSignIn()' 생성자 대신 '.instance' 싱글톤 사용
final GoogleSignIn _googleSignIn = GoogleSignIn.instance;
SessionNotifier() {
loadSession();
}
/// 앱 시작 시 저장된 세션 로드
Future<void> loadSession() async {
_session = await _identityService.getUserSession();
notifyListeners();
}
/// (백엔드 연동 후) 로그인/계정 연결
Future<void> login(String provider) async {
if (isLoading) return;
final guestUserId = _session!.userId; // 현재 게스트 ID
String? idToken;
String? email;
String? userName;
try {
if (provider == 'google') {
// 🔽 [수정] 'signIn()' 메서드 대신 'authenticate()' 사용
final GoogleSignInAccount? googleUser = await _googleSignIn.authenticate();
if (googleUser == null) return; // 유저가 취소
final GoogleSignInAuthentication googleAuth = googleUser.authentication;
idToken = googleAuth.idToken; // 👈 [핵심] 이 토큰을 백엔드로 전송
email = googleUser.email;
userName = googleUser.displayName;
} else if (provider == 'apple') {
final credential = await SignInWithApple.getAppleIDCredential(
scopes: [ AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName ],
);
idToken = credential.identityToken; // 👈 [핵심] 이 토큰을 백엔드로 전송
email = credential.email;
userName = "${credential.givenName ?? ''} ${credential.familyName ?? ''}".trim();
}
if (idToken == null) {
throw Exception("$provider 로그인에 실패했습니다.");
}
// [TODO] 백엔드에 'mergeAccount(guestUserId, idToken, provider)' API 호출
// 백엔드는 이 idToken을 검증하고, guestUserId의 데이터를
// 소셜 계정의 마스터 ID로 병합(merge)해야 합니다.
// --- 백엔드 응답 (임시 시뮬레이션) ---
// final backendResponse = await _puzzleService.mergeAccount(guestUserId, idToken, provider);
// _session = await _identityService.saveSocialLogin(
// newUserId: backendResponse.userId,
// newUserName: backendResponse.userName,
// newEmail: backendResponse.email,
// provider: provider
// );
// [임시] 백엔드 없으므로, 클라이언트 정보로 강제 저장 (테스트용)
_session = await _identityService.saveSocialLogin(
newUserId: "master-id-${email ?? provider}", // (임시)
newUserName: userName ?? "Social User",
newEmail: email ?? "No Email",
provider: provider
);
// --- 임시 시뮬레이션 끝 ---
notifyListeners();
} catch (e) {
debugPrint("$provider 로그인 오류: $e");
// [TODO] 유저에게 "로그인에 실패했습니다." 스낵바 표시
}
}
/// 로그아웃
Future<void> logout() async {
await _googleSignIn.signOut();
_session = await _identityService.logout();
notifyListeners();
}
}