diff --git a/lib/views/login/login_page.dart b/lib/views/login/login_page.dart index 0f94cfd..45f1e04 100644 --- a/lib/views/login/login_page.dart +++ b/lib/views/login/login_page.dart @@ -23,12 +23,16 @@ import 'package:google_sign_in/google_sign_in.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'dart:io' show Platform; +/* 애플 로그인 */ +import 'package:sign_in_with_apple/sign_in_with_apple.dart'; + /* 광고 */ import 'package:google_mobile_ads/google_mobile_ads.dart'; /* 메인 페이지 */ import '../room/main_page.dart'; + /* 설정 */ import '../../config/config.dart'; @@ -235,135 +239,78 @@ class _LoginPageState extends State { // ───────────────────────────────────────── - // (D4) 애플 로그인 (임시) + // (D4) 애플 로그인 // ───────────────────────────────────────── Future _appleLogin() async { setState(() => _isLoading = true); try { - // TODO: 애플 로그인 구현 - showResponseDialog(context, 'Notice', 'Apple login will be implemented soon.'); - } catch (e) { - showResponseDialog(context, 'Error', 'An error occurred during Apple login.\n$e'); - } finally { - setState(() => _isLoading = false); - } - } - - // ───────────────────────────────────────── - // (D3) 구글 회원가입 - // ───────────────────────────────────────── - Future _googleSignUp() async { - final agreed = await _showTermsModal(); - if (agreed != true) { - return; - } - - try { - // (2) 구글 계정 선택 - final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); - if (googleUser == null) { - // 사용자가 회원가입 창에서 취소 - return; - } - - // (3) 구글 인증 정보 - final GoogleSignInAuthentication googleAuth = await googleUser.authentication; - - // (4) FirebaseAuth Credential - final AuthCredential credential = GoogleAuthProvider.credential( - accessToken: googleAuth.accessToken, - idToken: googleAuth.idToken, + // 1) 애플 로그인 시도 + final appleCredential = await SignInWithApple.getAppleIDCredential( + scopes: [ + AppleIDAuthorizationScopes.email, + AppleIDAuthorizationScopes.fullName, + ], ); - // (5) FirebaseAuth로 "회원가입" 시도 - final UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(credential); + // 2) Firebase 용 credential 생성 + final oauthCredential = OAuthProvider('apple.com').credential( + idToken: appleCredential.identityToken, + accessToken: appleCredential.authorizationCode, + ); + + // 3) Firebase Auth로 로그인 + final UserCredential userCredential = + await FirebaseAuth.instance.signInWithCredential(oauthCredential); final User? user = userCredential.user; + if (user == null) { - showResponseDialog(context, 'Error' /* 오류 */, 'Google account authentication failed.' - /* 구글계정 인증에 실패했습니다. */); + showResponseDialog(context, 'Error' /* 오류 */, + 'Apple login error. Please contact the administrator.' + /* 애플 로그인 오류. 관리자에게 문의해주세요. */); return; } - // (6) idToken 추출 후, 서버에 회원가입 요청 + // 4) Firebase 토큰 가져오기 final idToken = await user.getIdToken(); + + // 5) 서버에 애플 로그인 정보 전송 final requestBody = { 'id_token': idToken, }; - final response = await Api.serverRequest(uri: '/user/google/signup', body: requestBody); + final response = await Api.serverRequest(uri: '/user/apple/login', body: requestBody); + if (response['result'] == 'OK') { final resp = response['response'] ?? {}; if (resp['result'] == 'OK') { - // 회원가입 성공 안내 - showResponseDialog(context, 'Sign-up Complete' /* 회원가입 완료 */, 'Google sign-up has been completed.' - /* 구글 회원가입이 완료되었습니다. */); + // 로그인 성공 시 정보 저장 + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('oauth_type', 'apple'); + await prefs.setBool('auto_login', true); + await prefs.setString('jwt_token', resp['auth']['token'].toString()); + await prefs.setInt('my_user_seq', resp['auth']['user_seq']); + + // 메인 페이지로 이동 + Navigator.pushReplacement(context, + MaterialPageRoute(builder: (_) => const MainPage())); } else { - // 실패 시 - final msgTitle = resp['response_info']?['msg_title'] ?? 'Error' /* 오류 */; - final msgContent = resp['response_info']?['msg_content'] ?? 'Failed to sign up.' - /* 회원가입에 실패했습니다. */; - showResponseDialog(context, msgTitle, msgContent); + showResponseDialog(context, + resp['response_info']['msg_title'], + resp['response_info']['msg_content']); } } else { - showResponseDialog(context, 'Error' /* 오류 */, 'Google sign-up request failed.' - /* 구글 회원가입 요청 실패 */); + showResponseDialog(context, 'Error' /* 오류 */, + 'Apple login request failed.' /* 애플 로그인 요청 실패 */); } } catch (e) { - showResponseDialog(context, 'Error' /* 오류 */, 'An error occurred during Google sign-up.\n$e' - /* 구글 회원가입 중 오류가 발생했습니다.\n$e */); + _showAlert('Error' /* 오류 */, + 'An error occurred during Apple login.\n$e' + /* 애플 로그인 중 오류가 발생했습니다.\n$e */); + } finally { + setState(() => _isLoading = false); } } - - // ───────────────────────────────────────── - // (E) 약관 모달 (개인정보 수집 동의) - // ───────────────────────────────────────── - Future _showTermsModal() async { - return showDialog( - context: context, - barrierDismissible: false, - builder: (ctx) { - return AlertDialog( - backgroundColor: Colors.white, - title: const Text( - 'Privacy Collection and Usage Agreement' - /* 개인정보 수집 및 이용 동의서 */, - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text( - Config.termsOfService, - style: const TextStyle(fontSize: 14), - ), - ], - ), - ), - actions: [ - TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.black, - foregroundColor: Colors.white, - ), - onPressed: () => Navigator.pop(ctx, false), - child: Text('Disagree' - /* 거부 */), - ), - TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.black, - foregroundColor: Colors.white, - ), - onPressed: () => Navigator.pop(ctx, true), - child: Text('Agree' - /* 동의 */), - ), - ], - ); - }, - ); - } + // ───────────────────────────────────────── // (F) 간단 Alert (간단 알림창)