From df32443b49cdee777332ce3fa0e77049ca99483a Mon Sep 17 00:00:00 2001 From: Yellowtoast Date: Fri, 27 Oct 2023 18:33:36 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/api_exceptions.dart | 0 .../data/auth_repository.dart | 33 +-- .../data/auth_repository.g.dart | 2 +- .../data_sources/local_auth_data_source.dart | 2 +- .../local_auth_data_source.g.dart | 0 .../apple_auth_data_source_impl.dart | 19 ++ .../google_auth_data_source_impl.dart | 60 +++++ .../kakao_auth_data_source_impl.dart | 79 ++++++ .../sns_auth_data_source.dart | 23 ++ .../data/phone_auth_repository.dart | 5 +- .../domain/auth_status.dart | 2 +- .../domain/auth_status.freezed.dart | 0 .../domain/sns_oauth_info.dart | 0 .../domain/sns_oauth_info.freezed.dart | 0 .../auth/presentation/login/login_view.dart | 110 ++++++++ .../login/login_view_controller.dart | 4 +- .../login/login_view_controller.g.dart | 0 .../login/widgets/sns_button_widget.dart | 6 +- .../data_sources/sns_auth_data_source.dart | 171 ------------- .../domain/registration_info.dart | 27 -- .../domain/registration_info.freezed.dart | 240 ------------------ .../domain/registration_info.g.dart | 31 --- .../presentation/login/login_view.dart | 81 ------ .../signup/auth_verify_notifier_provider.dart | 60 ----- .../presentation/signup/phone_auth_view.dart | 154 ----------- .../signup/phone_auth_view_controller.dart | 25 -- .../signup/phone_auth_view_controller.g.dart | 27 -- .../signup/send_code_button_provider.dart | 3 - 28 files changed, 309 insertions(+), 855 deletions(-) rename lib/src/features/{authentication => auth}/data/api_exceptions.dart (100%) rename lib/src/features/{authentication => auth}/data/auth_repository.dart (80%) rename lib/src/features/{authentication => auth}/data/auth_repository.g.dart (98%) rename lib/src/features/{authentication => auth}/data/data_sources/local_auth_data_source.dart (90%) rename lib/src/features/{authentication => auth}/data/data_sources/local_auth_data_source.g.dart (100%) create mode 100644 lib/src/features/auth/data/data_sources/sns_data_sources/apple_auth_data_source_impl.dart create mode 100644 lib/src/features/auth/data/data_sources/sns_data_sources/google_auth_data_source_impl.dart create mode 100644 lib/src/features/auth/data/data_sources/sns_data_sources/kakao_auth_data_source_impl.dart create mode 100644 lib/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart rename lib/src/features/{authentication => auth}/data/phone_auth_repository.dart (93%) rename lib/src/features/{authentication => auth}/domain/auth_status.dart (87%) rename lib/src/features/{authentication => auth}/domain/auth_status.freezed.dart (100%) rename lib/src/features/{authentication => auth}/domain/sns_oauth_info.dart (100%) rename lib/src/features/{authentication => auth}/domain/sns_oauth_info.freezed.dart (100%) create mode 100644 lib/src/features/auth/presentation/login/login_view.dart rename lib/src/features/{authentication => auth}/presentation/login/login_view_controller.dart (83%) rename lib/src/features/{authentication => auth}/presentation/login/login_view_controller.g.dart (100%) rename lib/src/features/{authentication => auth}/presentation/login/widgets/sns_button_widget.dart (86%) delete mode 100644 lib/src/features/authentication/data/data_sources/sns_auth_data_source.dart delete mode 100644 lib/src/features/authentication/domain/registration_info.dart delete mode 100644 lib/src/features/authentication/domain/registration_info.freezed.dart delete mode 100644 lib/src/features/authentication/domain/registration_info.g.dart delete mode 100644 lib/src/features/authentication/presentation/login/login_view.dart delete mode 100644 lib/src/features/authentication/presentation/signup/auth_verify_notifier_provider.dart delete mode 100644 lib/src/features/authentication/presentation/signup/phone_auth_view.dart delete mode 100644 lib/src/features/authentication/presentation/signup/phone_auth_view_controller.dart delete mode 100644 lib/src/features/authentication/presentation/signup/phone_auth_view_controller.g.dart delete mode 100644 lib/src/features/authentication/presentation/signup/send_code_button_provider.dart diff --git a/lib/src/features/authentication/data/api_exceptions.dart b/lib/src/features/auth/data/api_exceptions.dart similarity index 100% rename from lib/src/features/authentication/data/api_exceptions.dart rename to lib/src/features/auth/data/api_exceptions.dart diff --git a/lib/src/features/authentication/data/auth_repository.dart b/lib/src/features/auth/data/auth_repository.dart similarity index 80% rename from lib/src/features/authentication/data/auth_repository.dart rename to lib/src/features/auth/data/auth_repository.dart index ec218c2..2697705 100644 --- a/lib/src/features/authentication/data/auth_repository.dart +++ b/lib/src/features/auth/data/auth_repository.dart @@ -3,10 +3,13 @@ import 'dart:async'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; import 'package:pets_next_door_flutter/src/constants/enums.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/data/data_sources/local_auth_data_source.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/data/data_sources/sns_auth_data_source.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/domain/auth_status.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/domain/sns_oauth_info.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/local_auth_data_source.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/apple_auth_data_source_impl.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/google_auth_data_source_impl.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/kakao_auth_data_source_impl.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/auth_status.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'auth_repository.g.dart'; @@ -85,26 +88,6 @@ class AuthRepositoryImpl implements AuthRepository { return localAuthDataSource.getCurrentAuthStatus(); } - // @override - // Future logout({required AuthStatus authStatus}) async { - // final currentLoginProviderType = authStatus.maybeWhen( - // loggedOut: (latelyLoggedInProviderType) => latelyLoggedInProviderType, - // signUpInProgress: (providerType) => providerType, - // loggedIn: (providerType) => providerType, - // orElse: () => null, - // ); - - // if (currentLoginProviderType == null) return false; - - // return firebaseAuthDataSource.signOut().then( - // (_) => _updateAuthStatus( - // authStatus: AuthStatus.loggedOut( - // latestLogInProviderType: currentLoginProviderType, - // ), - // ), - // ); - // } - Future _updateAuthStatus({required AuthStatus authStatus}) async { await localAuthDataSource.updateAuthStatus(authStatus: authStatus); return true; @@ -152,7 +135,7 @@ final localAuthServiceProvider = Provider((ref) { return LocalAuthServiceImpl(); }); -@riverpod +@Riverpod(keepAlive: false) Future authSignInOrRegister( AuthSignInOrRegisterRef ref, SnsProviderType providerType, diff --git a/lib/src/features/authentication/data/auth_repository.g.dart b/lib/src/features/auth/data/auth_repository.g.dart similarity index 98% rename from lib/src/features/authentication/data/auth_repository.g.dart rename to lib/src/features/auth/data/auth_repository.g.dart index 1c3b143..c0b2cd3 100644 --- a/lib/src/features/authentication/data/auth_repository.g.dart +++ b/lib/src/features/auth/data/auth_repository.g.dart @@ -7,7 +7,7 @@ part of 'auth_repository.dart'; // ************************************************************************** String _$authSignInOrRegisterHash() => - r'3b0a6708fcfd650fe5b91e18a88f6e2c0368b89c'; + r'affe886cb38677d633a1a8cbbbaed4e577ca8679'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/src/features/authentication/data/data_sources/local_auth_data_source.dart b/lib/src/features/auth/data/data_sources/local_auth_data_source.dart similarity index 90% rename from lib/src/features/authentication/data/data_sources/local_auth_data_source.dart rename to lib/src/features/auth/data/data_sources/local_auth_data_source.dart index fe30ef3..b46631a 100644 --- a/lib/src/features/authentication/data/data_sources/local_auth_data_source.dart +++ b/lib/src/features/auth/data/data_sources/local_auth_data_source.dart @@ -1,4 +1,4 @@ -import 'package:pets_next_door_flutter/src/features/authentication/domain/auth_status.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/auth_status.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'local_auth_data_source.g.dart'; diff --git a/lib/src/features/authentication/data/data_sources/local_auth_data_source.g.dart b/lib/src/features/auth/data/data_sources/local_auth_data_source.g.dart similarity index 100% rename from lib/src/features/authentication/data/data_sources/local_auth_data_source.g.dart rename to lib/src/features/auth/data/data_sources/local_auth_data_source.g.dart diff --git a/lib/src/features/auth/data/data_sources/sns_data_sources/apple_auth_data_source_impl.dart b/lib/src/features/auth/data/data_sources/sns_data_sources/apple_auth_data_source_impl.dart new file mode 100644 index 0000000..1cef1fa --- /dev/null +++ b/lib/src/features/auth/data/data_sources/sns_data_sources/apple_auth_data_source_impl.dart @@ -0,0 +1,19 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart'; + +final appleAuthServiceProvider = + Provider.autoDispose((ref) => AppleAuthDataSourceImpl()); + +class AppleAuthDataSourceImpl implements SnsAuthDataSource { + @override + snsLogin() { + // TODO: implement snsLogin + throw UnimplementedError(); + } + + @override + Future validateLoginStatus() { + // TODO: implement validateLoginStatus + throw UnimplementedError(); + } +} diff --git a/lib/src/features/auth/data/data_sources/sns_data_sources/google_auth_data_source_impl.dart b/lib/src/features/auth/data/data_sources/sns_data_sources/google_auth_data_source_impl.dart new file mode 100644 index 0000000..a1619b5 --- /dev/null +++ b/lib/src/features/auth/data/data_sources/sns_data_sources/google_auth_data_source_impl.dart @@ -0,0 +1,60 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:pets_next_door_flutter/src/constants/enums.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; + +final googleAuthServiceProvider = Provider.autoDispose( + (ref) => GoogleAuthDataSourceImpl()); + +class GoogleAuthDataSourceImpl implements SnsAuthDataSource { + @override + Future snsLogin() async { + final signInResult = await _signInWithGoogle(); + + // Once signed in, return the UserCredential + // return FirebaseAuth.instance.signInWithCredential(oAuthCredential); + return SnsOAuthInfo.credential( + providerType: SnsProviderType.google, + authCredential: signInResult.oAuthCredential, + email: signInResult.email, + ); + } + + Future _signInWithGoogle() async { + final googleSignIn = GoogleSignIn(); + final isSignedIn = await googleSignIn.isSignedIn(); + final GoogleSignInAuthentication? googleAuth; + final String? userEmail; + + if (isSignedIn && googleSignIn.currentUser != null) { + final currentUser = googleSignIn.currentUser; + + googleAuth = await currentUser?.authentication; + userEmail = currentUser?.email; + } else { + // Trigger the authentication flow + final googleUser = await googleSignIn.signIn(); + + // Obtain the auth details from the request + googleAuth = await googleUser?.authentication; + userEmail = googleUser?.email; + } + + // Create a new credential + return ( + oAuthCredential: GoogleAuthProvider.credential( + accessToken: googleAuth?.accessToken, + idToken: googleAuth?.idToken, + ), + email: userEmail ?? '' + ); + } + + @override + Future validateLoginStatus() { + // TODO: implement validateLoginStatus + throw UnimplementedError(); + } +} diff --git a/lib/src/features/auth/data/data_sources/sns_data_sources/kakao_auth_data_source_impl.dart b/lib/src/features/auth/data/data_sources/sns_data_sources/kakao_auth_data_source_impl.dart new file mode 100644 index 0000000..abf6ed9 --- /dev/null +++ b/lib/src/features/auth/data/data_sources/sns_data_sources/kakao_auth_data_source_impl.dart @@ -0,0 +1,79 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; +import 'package:pets_next_door_flutter/src/constants/enums.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; + +final kakaoAuthServiceProvider = + Provider.autoDispose((ref) => KakaoAuthDataSourceImpl()); + +class KakaoAuthDataSourceImpl implements SnsAuthDataSource { + @override + Future snsLogin() async { + final signInResult = await _signInWithKakao(); + + // TODO: 여기다가 우리 자체 API 태워서 customToken 가지고 오는 로직 넣어야 함 + + return SnsOAuthInfo.token( + authToken: signInResult!.oAuthToken, + email: signInResult.email, + providerType: SnsProviderType.kakao, + ); + } + + Future _signInWithKakao() async { +// 카카오 로그인 구현 예제 + +// 카카오톡 실행 가능 여부 확인 +// 카카오톡 실행이 가능하면 카카오톡으로 로그인, 아니면 카카오계정으로 로그인 + if (await isKakaoTalkInstalled()) { + try { + final oAuthToken = await UserApi.instance.loginWithKakaoTalk(); + final userEmail = await UserApi.instance + .me() + .then((value) => value.kakaoAccount?.email ?? ''); + + return (oAuthToken: oAuthToken, email: userEmail); + } catch (error) { + // 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우, + // 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기) + if (error is PlatformException && error.code == 'CANCELED') { + return null; + } + + // 카카오톡에 연결된 카카오계정이 없는 경우, 카카오계정으로 로그인 + try { + final oAuthToken = await UserApi.instance.loginWithKakaoAccount(); + final userEmail = await UserApi.instance + .me() + .then((value) => value.kakaoAccount?.email ?? ''); + + return (oAuthToken: oAuthToken, email: userEmail); + } catch (error) { + // print('카카오계정으로 로그인 실패 $error'); + return null; + } + } + } else { + try { + // print('카카오계정으로 로그인 성공'); + final oAuthToken = await UserApi.instance.loginWithKakaoAccount(); + final userEmail = await UserApi.instance + .me() + .then((value) => value.kakaoAccount?.email ?? ''); + + return (oAuthToken: oAuthToken, email: userEmail); + } catch (error) { + // print('카카오계정으로 로그인 실패 $error'); + return null; + } + } + } + + @override + Future validateLoginStatus() { + // TODO: implement validateLoginStatus + throw UnimplementedError(); + } +} diff --git a/lib/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart b/lib/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart new file mode 100644 index 0000000..084ad23 --- /dev/null +++ b/lib/src/features/auth/data/data_sources/sns_data_sources/sns_auth_data_source.dart @@ -0,0 +1,23 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; + +typedef Valid = bool; + +typedef SignInResultOAuthCredential = ({ + OAuthCredential oAuthCredential, + String email +}); + +typedef SignInResultOAuthToken = ({ + OAuthToken oAuthToken, + String email, +}); + +abstract class SnsAuthDataSource { + /// 플랫폼 별로 sns로그인을 한 뒤 OAuth정보를 리턴하는 함수 + Future snsLogin(); + + /// 플랫폼의 로그인 상태가 유효한지 리턴하는 함수 + Future validateLoginStatus(); +} diff --git a/lib/src/features/authentication/data/phone_auth_repository.dart b/lib/src/features/auth/data/phone_auth_repository.dart similarity index 93% rename from lib/src/features/authentication/data/phone_auth_repository.dart rename to lib/src/features/auth/data/phone_auth_repository.dart index 0bc88c6..ebf76df 100644 --- a/lib/src/features/authentication/data/phone_auth_repository.dart +++ b/lib/src/features/auth/data/phone_auth_repository.dart @@ -1,10 +1,9 @@ -import 'dart:convert'; import 'dart:io'; + import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; - import 'package:pets_next_door_flutter/src/api/auth_api.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/data/api_exceptions.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/api_exceptions.dart'; import 'package:pets_next_door_flutter/src/utils/dio_provider.dart'; /// Weather Repository using the http client. Calls API methods and parses responses. diff --git a/lib/src/features/authentication/domain/auth_status.dart b/lib/src/features/auth/domain/auth_status.dart similarity index 87% rename from lib/src/features/authentication/domain/auth_status.dart rename to lib/src/features/auth/domain/auth_status.dart index 8f19195..f4e01ef 100644 --- a/lib/src/features/authentication/domain/auth_status.dart +++ b/lib/src/features/auth/domain/auth_status.dart @@ -1,6 +1,6 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/domain/sns_oauth_info.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; part 'auth_status.freezed.dart'; diff --git a/lib/src/features/authentication/domain/auth_status.freezed.dart b/lib/src/features/auth/domain/auth_status.freezed.dart similarity index 100% rename from lib/src/features/authentication/domain/auth_status.freezed.dart rename to lib/src/features/auth/domain/auth_status.freezed.dart diff --git a/lib/src/features/authentication/domain/sns_oauth_info.dart b/lib/src/features/auth/domain/sns_oauth_info.dart similarity index 100% rename from lib/src/features/authentication/domain/sns_oauth_info.dart rename to lib/src/features/auth/domain/sns_oauth_info.dart diff --git a/lib/src/features/authentication/domain/sns_oauth_info.freezed.dart b/lib/src/features/auth/domain/sns_oauth_info.freezed.dart similarity index 100% rename from lib/src/features/authentication/domain/sns_oauth_info.freezed.dart rename to lib/src/features/auth/domain/sns_oauth_info.freezed.dart diff --git a/lib/src/features/auth/presentation/login/login_view.dart b/lib/src/features/auth/presentation/login/login_view.dart new file mode 100644 index 0000000..988b1d5 --- /dev/null +++ b/lib/src/features/auth/presentation/login/login_view.dart @@ -0,0 +1,110 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:go_router/go_router.dart'; +import 'package:pets_next_door_flutter/src/constants/enums.dart'; +import 'package:pets_next_door_flutter/src/constants/sizes.dart'; +import 'package:pets_next_door_flutter/src/constants/strings.dart'; +import 'package:pets_next_door_flutter/src/constants/svgs.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; +import 'package:pets_next_door_flutter/src/features/auth/presentation/login/login_view_controller.dart'; +import 'package:pets_next_door_flutter/src/features/auth/presentation/login/widgets/sns_button_widget.dart'; +import 'package:pets_next_door_flutter/src/features/user/domain/user_profile_view_state.dart'; +import 'package:pets_next_door_flutter/src/routing/app_router.dart'; + +class LoginView extends StatelessWidget { + const LoginView({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: Consumer( + builder: (BuildContext context, WidgetRef ref, Widget? child) { + final loginViewController = + ref.watch(loginViewControllerProvider.notifier); + + final providerList = (Platform.isIOS) + ? SnsProviderType.values.toList() + : SnsProviderType.getAndroidProviderList(); + + return SafeArea( + child: Column( + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SvgPicture.asset(PNDSvgs.mainIcon), + gapH20, + SvgPicture.asset(PNDSvgs.mainTitleIcon), + ], + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * (155 / 844), + ), + Expanded( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: providerList.map((provider) { + final index = + SnsProviderType.values.indexOf(provider); + final isLastIndex = + SnsProviderType.values.length - 1 == index; + + return Padding( + padding: EdgeInsets.only( + right: isLastIndex ? 0 : PNDSizes.p24, + ), + child: SnsButtonWidget( + snsType: provider, + onTap: (provider) { + loginViewController.signIn( + selectedProvider: provider, + onRegisterUser: (registerInfo) => + _routeToRegister(context, registerInfo), + onExistingUser: () => _routeToHome(context), + ); + }, + ), + ); + }).toList(), + ), + gapH32, + const Text( + PNDStrings.problemWhenLogin, + style: TextStyle( + color: Color(0xff9E9E9E), shadows: [BoxShadow()]), + ), + ], + ), + ), + ], + ), + ); + }, + ), + ); + } + + void _routeToRegister( + BuildContext context, + SnsOAuthInfo snsOAuthInfo, + ) { + // ref.read(registrationInfoStateProvider(snsOAuthInfo).notifier); + + context.pushNamed( + AppRoute.profile.name, + extra: UserProfileViewState.edit(userId: 1), + ); + } + + void _routeToHome(BuildContext context) { + context.goNamed(AppRoute.home.name); + } +} diff --git a/lib/src/features/authentication/presentation/login/login_view_controller.dart b/lib/src/features/auth/presentation/login/login_view_controller.dart similarity index 83% rename from lib/src/features/authentication/presentation/login/login_view_controller.dart rename to lib/src/features/auth/presentation/login/login_view_controller.dart index db8cf95..2b81102 100644 --- a/lib/src/features/authentication/presentation/login/login_view_controller.dart +++ b/lib/src/features/auth/presentation/login/login_view_controller.dart @@ -1,6 +1,6 @@ import 'package:pets_next_door_flutter/src/constants/enums.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/data/auth_repository.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/domain/sns_oauth_info.dart'; +import 'package:pets_next_door_flutter/src/features/auth/data/auth_repository.dart'; +import 'package:pets_next_door_flutter/src/features/auth/domain/sns_oauth_info.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'login_view_controller.g.dart'; diff --git a/lib/src/features/authentication/presentation/login/login_view_controller.g.dart b/lib/src/features/auth/presentation/login/login_view_controller.g.dart similarity index 100% rename from lib/src/features/authentication/presentation/login/login_view_controller.g.dart rename to lib/src/features/auth/presentation/login/login_view_controller.g.dart diff --git a/lib/src/features/authentication/presentation/login/widgets/sns_button_widget.dart b/lib/src/features/auth/presentation/login/widgets/sns_button_widget.dart similarity index 86% rename from lib/src/features/authentication/presentation/login/widgets/sns_button_widget.dart rename to lib/src/features/auth/presentation/login/widgets/sns_button_widget.dart index bdfdcdb..9ebd9f3 100644 --- a/lib/src/features/authentication/presentation/login/widgets/sns_button_widget.dart +++ b/lib/src/features/auth/presentation/login/widgets/sns_button_widget.dart @@ -20,9 +20,9 @@ class SnsButtonWidget extends StatelessWidget { @override Widget build(BuildContext context) { final svgAssetUrl = switch (snsType) { - SnsProviderType.apple => Svgs.apple, - SnsProviderType.google => Svgs.google, - SnsProviderType.kakao => Svgs.kakao, + SnsProviderType.apple => PNDSvgs.apple, + SnsProviderType.google => PNDSvgs.google, + SnsProviderType.kakao => PNDSvgs.kakao, }; return GestureDetector( diff --git a/lib/src/features/authentication/data/data_sources/sns_auth_data_source.dart b/lib/src/features/authentication/data/data_sources/sns_auth_data_source.dart deleted file mode 100644 index c1b4160..0000000 --- a/lib/src/features/authentication/data/data_sources/sns_auth_data_source.dart +++ /dev/null @@ -1,171 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/services.dart'; -import 'package:google_sign_in/google_sign_in.dart'; -import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; -import 'package:pets_next_door_flutter/src/constants/enums.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/domain/sns_oauth_info.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -typedef Valid = bool; - -typedef SignInResultOAuthCredential = ({ - OAuthCredential oAuthCredential, - String email -}); - -typedef SignInResultOAuthToken = ({ - OAuthToken oAuthToken, - String email, -}); - -final kakaoAuthServiceProvider = - Provider((ref) => KakaoAuthDataSource()); - -final googleAuthServiceProvider = - Provider((ref) => GoogleAuthDataSource()); - -final appleAuthServiceProvider = - Provider((ref) => AppleAuthDataSource()); - -abstract class SnsAuthDataSource { - /// 플랫폼 별로 sns로그인을 한 뒤 OAuth정보를 리턴하는 함수 - Future snsLogin(); - - /// 플랫폼의 로그인 상태가 유효한지 리턴하는 함수 - Future validateLoginStatus(); -} - -class KakaoAuthDataSource implements SnsAuthDataSource { - @override - Future snsLogin() async { - final signInResult = await _signInWithKakao(); - - // TODO: 여기다가 우리 자체 API 태워서 customToken 가지고 오는 로직 넣어야 함 - - return SnsOAuthInfo.token( - authToken: signInResult!.oAuthToken, - email: signInResult.email, - providerType: SnsProviderType.kakao, - ); - } - - Future _signInWithKakao() async { -// 카카오 로그인 구현 예제 - -// 카카오톡 실행 가능 여부 확인 -// 카카오톡 실행이 가능하면 카카오톡으로 로그인, 아니면 카카오계정으로 로그인 - if (await isKakaoTalkInstalled()) { - try { - final oAuthToken = await UserApi.instance.loginWithKakaoTalk(); - final userEmail = await UserApi.instance - .me() - .then((value) => value.kakaoAccount?.email ?? ''); - - return (oAuthToken: oAuthToken, email: userEmail); - } catch (error) { - // 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우, - // 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기) - if (error is PlatformException && error.code == 'CANCELED') { - return null; - } - - // 카카오톡에 연결된 카카오계정이 없는 경우, 카카오계정으로 로그인 - try { - final oAuthToken = await UserApi.instance.loginWithKakaoAccount(); - final userEmail = await UserApi.instance - .me() - .then((value) => value.kakaoAccount?.email ?? ''); - - return (oAuthToken: oAuthToken, email: userEmail); - } catch (error) { - // print('카카오계정으로 로그인 실패 $error'); - return null; - } - } - } else { - try { - // print('카카오계정으로 로그인 성공'); - final oAuthToken = await UserApi.instance.loginWithKakaoAccount(); - final userEmail = await UserApi.instance - .me() - .then((value) => value.kakaoAccount?.email ?? ''); - - return (oAuthToken: oAuthToken, email: userEmail); - } catch (error) { - // print('카카오계정으로 로그인 실패 $error'); - return null; - } - } - } - - @override - Future validateLoginStatus() { - // TODO: implement validateLoginStatus - throw UnimplementedError(); - } -} - -class GoogleAuthDataSource implements SnsAuthDataSource { - @override - Future snsLogin() async { - final signInResult = await _signInWithGoogle(); - - // Once signed in, return the UserCredential - // return FirebaseAuth.instance.signInWithCredential(oAuthCredential); - return SnsOAuthInfo.credential( - providerType: SnsProviderType.google, - authCredential: signInResult.oAuthCredential, - email: signInResult.email, - ); - } - - Future _signInWithGoogle() async { - final googleSignIn = GoogleSignIn(); - final isSignedIn = await googleSignIn.isSignedIn(); - final GoogleSignInAuthentication? googleAuth; - final String? userEmail; - - if (isSignedIn && googleSignIn.currentUser != null) { - final currentUser = googleSignIn.currentUser; - - googleAuth = await currentUser?.authentication; - userEmail = currentUser?.email; - } else { - // Trigger the authentication flow - final googleUser = await googleSignIn.signIn(); - - // Obtain the auth details from the request - googleAuth = await googleUser?.authentication; - userEmail = googleUser?.email; - } - - // Create a new credential - return ( - oAuthCredential: GoogleAuthProvider.credential( - accessToken: googleAuth?.accessToken, - idToken: googleAuth?.idToken, - ), - email: userEmail ?? '' - ); - } - - @override - Future validateLoginStatus() { - // TODO: implement validateLoginStatus - throw UnimplementedError(); - } -} - -class AppleAuthDataSource implements SnsAuthDataSource { - @override - snsLogin() { - // TODO: implement snsLogin - throw UnimplementedError(); - } - - @override - Future validateLoginStatus() { - // TODO: implement validateLoginStatus - throw UnimplementedError(); - } -} diff --git a/lib/src/features/authentication/domain/registration_info.dart b/lib/src/features/authentication/domain/registration_info.dart deleted file mode 100644 index 1e9eea2..0000000 --- a/lib/src/features/authentication/domain/registration_info.dart +++ /dev/null @@ -1,27 +0,0 @@ -// library forecast; - -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:pets_next_door_flutter/src/constants/enums.dart'; - -part 'registration_info.g.dart'; -part 'registration_info.freezed.dart'; - -/// 회원가입을 위해 DB에 등록하는데 필요한 데이터 목록 -/// - [email] : 유저의 이메일 -/// - [providerType] : 회원가입에 사용한 sns provider 타입 -/// - [firebaseUid] : firebase로그인 후 발급받은 firebas uid -/// - [fullname] : 유저의 실제 이름 -/// - [nickname] : 유저가 설정한 닉네임 -@freezed -class RegistrationInfo with _$RegistrationInfo { - factory RegistrationInfo({ - required String email, - required SnsProviderType providerType, - required String firebaseUid, - required String fullname, - required String nickname, - }) = _RegistrationInfo; - - factory RegistrationInfo.fromJson(Map json) => - _$RegistrationInfoFromJson(json); -} diff --git a/lib/src/features/authentication/domain/registration_info.freezed.dart b/lib/src/features/authentication/domain/registration_info.freezed.dart deleted file mode 100644 index 385a77e..0000000 --- a/lib/src/features/authentication/domain/registration_info.freezed.dart +++ /dev/null @@ -1,240 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'registration_info.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); - -RegistrationInfo _$RegistrationInfoFromJson(Map json) { - return _RegistrationInfo.fromJson(json); -} - -/// @nodoc -mixin _$RegistrationInfo { - String get email => throw _privateConstructorUsedError; - SnsProviderType get providerType => throw _privateConstructorUsedError; - String get firebaseUid => throw _privateConstructorUsedError; - String get fullname => throw _privateConstructorUsedError; - String get nickname => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $RegistrationInfoCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $RegistrationInfoCopyWith<$Res> { - factory $RegistrationInfoCopyWith( - RegistrationInfo value, $Res Function(RegistrationInfo) then) = - _$RegistrationInfoCopyWithImpl<$Res, RegistrationInfo>; - @useResult - $Res call( - {String email, - SnsProviderType providerType, - String firebaseUid, - String fullname, - String nickname}); -} - -/// @nodoc -class _$RegistrationInfoCopyWithImpl<$Res, $Val extends RegistrationInfo> - implements $RegistrationInfoCopyWith<$Res> { - _$RegistrationInfoCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? email = null, - Object? providerType = null, - Object? firebaseUid = null, - Object? fullname = null, - Object? nickname = null, - }) { - return _then(_value.copyWith( - email: null == email - ? _value.email - : email // ignore: cast_nullable_to_non_nullable - as String, - providerType: null == providerType - ? _value.providerType - : providerType // ignore: cast_nullable_to_non_nullable - as SnsProviderType, - firebaseUid: null == firebaseUid - ? _value.firebaseUid - : firebaseUid // ignore: cast_nullable_to_non_nullable - as String, - fullname: null == fullname - ? _value.fullname - : fullname // ignore: cast_nullable_to_non_nullable - as String, - nickname: null == nickname - ? _value.nickname - : nickname // ignore: cast_nullable_to_non_nullable - as String, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$_RegistrationInfoCopyWith<$Res> - implements $RegistrationInfoCopyWith<$Res> { - factory _$$_RegistrationInfoCopyWith( - _$_RegistrationInfo value, $Res Function(_$_RegistrationInfo) then) = - __$$_RegistrationInfoCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {String email, - SnsProviderType providerType, - String firebaseUid, - String fullname, - String nickname}); -} - -/// @nodoc -class __$$_RegistrationInfoCopyWithImpl<$Res> - extends _$RegistrationInfoCopyWithImpl<$Res, _$_RegistrationInfo> - implements _$$_RegistrationInfoCopyWith<$Res> { - __$$_RegistrationInfoCopyWithImpl( - _$_RegistrationInfo _value, $Res Function(_$_RegistrationInfo) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? email = null, - Object? providerType = null, - Object? firebaseUid = null, - Object? fullname = null, - Object? nickname = null, - }) { - return _then(_$_RegistrationInfo( - email: null == email - ? _value.email - : email // ignore: cast_nullable_to_non_nullable - as String, - providerType: null == providerType - ? _value.providerType - : providerType // ignore: cast_nullable_to_non_nullable - as SnsProviderType, - firebaseUid: null == firebaseUid - ? _value.firebaseUid - : firebaseUid // ignore: cast_nullable_to_non_nullable - as String, - fullname: null == fullname - ? _value.fullname - : fullname // ignore: cast_nullable_to_non_nullable - as String, - nickname: null == nickname - ? _value.nickname - : nickname // ignore: cast_nullable_to_non_nullable - as String, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_RegistrationInfo implements _RegistrationInfo { - _$_RegistrationInfo( - {required this.email, - required this.providerType, - required this.firebaseUid, - required this.fullname, - required this.nickname}); - - factory _$_RegistrationInfo.fromJson(Map json) => - _$$_RegistrationInfoFromJson(json); - - @override - final String email; - @override - final SnsProviderType providerType; - @override - final String firebaseUid; - @override - final String fullname; - @override - final String nickname; - - @override - String toString() { - return 'RegistrationInfo(email: $email, providerType: $providerType, firebaseUid: $firebaseUid, fullname: $fullname, nickname: $nickname)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_RegistrationInfo && - (identical(other.email, email) || other.email == email) && - (identical(other.providerType, providerType) || - other.providerType == providerType) && - (identical(other.firebaseUid, firebaseUid) || - other.firebaseUid == firebaseUid) && - (identical(other.fullname, fullname) || - other.fullname == fullname) && - (identical(other.nickname, nickname) || - other.nickname == nickname)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, email, providerType, firebaseUid, fullname, nickname); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_RegistrationInfoCopyWith<_$_RegistrationInfo> get copyWith => - __$$_RegistrationInfoCopyWithImpl<_$_RegistrationInfo>(this, _$identity); - - @override - Map toJson() { - return _$$_RegistrationInfoToJson( - this, - ); - } -} - -abstract class _RegistrationInfo implements RegistrationInfo { - factory _RegistrationInfo( - {required final String email, - required final SnsProviderType providerType, - required final String firebaseUid, - required final String fullname, - required final String nickname}) = _$_RegistrationInfo; - - factory _RegistrationInfo.fromJson(Map json) = - _$_RegistrationInfo.fromJson; - - @override - String get email; - @override - SnsProviderType get providerType; - @override - String get firebaseUid; - @override - String get fullname; - @override - String get nickname; - @override - @JsonKey(ignore: true) - _$$_RegistrationInfoCopyWith<_$_RegistrationInfo> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/src/features/authentication/domain/registration_info.g.dart b/lib/src/features/authentication/domain/registration_info.g.dart deleted file mode 100644 index 1cfe1f5..0000000 --- a/lib/src/features/authentication/domain/registration_info.g.dart +++ /dev/null @@ -1,31 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'registration_info.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_$_RegistrationInfo _$$_RegistrationInfoFromJson(Map json) => - _$_RegistrationInfo( - email: json['email'] as String, - providerType: $enumDecode(_$SnsProviderTypeEnumMap, json['providerType']), - firebaseUid: json['firebaseUid'] as String, - fullname: json['fullname'] as String, - nickname: json['nickname'] as String, - ); - -Map _$$_RegistrationInfoToJson(_$_RegistrationInfo instance) => - { - 'email': instance.email, - 'providerType': _$SnsProviderTypeEnumMap[instance.providerType]!, - 'firebaseUid': instance.firebaseUid, - 'fullname': instance.fullname, - 'nickname': instance.nickname, - }; - -const _$SnsProviderTypeEnumMap = { - SnsProviderType.kakao: 'kakao', - SnsProviderType.google: 'google', - SnsProviderType.apple: 'apple', -}; diff --git a/lib/src/features/authentication/presentation/login/login_view.dart b/lib/src/features/authentication/presentation/login/login_view.dart deleted file mode 100644 index 4fd20ff..0000000 --- a/lib/src/features/authentication/presentation/login/login_view.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:go_router/go_router.dart'; -import 'package:pets_next_door_flutter/src/constants/app_sizes.dart'; -import 'package:pets_next_door_flutter/src/constants/enums.dart'; -import 'package:pets_next_door_flutter/src/constants/strings.dart'; -import 'package:pets_next_door_flutter/src/constants/svgs.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/presentation/login/login_view_controller.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/presentation/login/widgets/sns_button_widget.dart'; -import 'package:pets_next_door_flutter/src/routing/app_router.dart'; - -class LoginView extends StatelessWidget { - const LoginView({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Consumer( - builder: (BuildContext context, WidgetRef ref, Widget? child) { - final loginViewController = - ref.watch(loginViewControllerProvider.notifier); - return SafeArea( - child: Column( - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SvgPicture.asset(Svgs.mainIcon), - gapH20, - SvgPicture.asset(Svgs.mainTitleIcon), - ], - ), - ), - SizedBox( - height: MediaQuery.of(context).size.height * (155 / 844), - ), - Expanded( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SnsButtonWidget( - onTap: (provider) async { - final authStatus = - await loginViewController.signIn(provider); - if (context.mounted) { - context.pushNamed(AppRoute.phoneAuth.name); - } - }, - snsType: SnsProviderType.google, - ), - gapW24, - SnsButtonWidget( - onTap: loginViewController.signIn, - snsType: SnsProviderType.kakao, - ), - gapW24, - SnsButtonWidget( - onTap: (value) => - context.goNamed(AppRoute.breedSearch.name), - snsType: SnsProviderType.apple, - ), - ], - ), - gapH32, - const Text(Strings.problemWhenLogin) - ], - ), - ), - ], - ), - ); - }, - ), - ); - } -} diff --git a/lib/src/features/authentication/presentation/signup/auth_verify_notifier_provider.dart b/lib/src/features/authentication/presentation/signup/auth_verify_notifier_provider.dart deleted file mode 100644 index aa7ada7..0000000 --- a/lib/src/features/authentication/presentation/signup/auth_verify_notifier_provider.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/presentation/signup/send_code_button_provider.dart'; -import 'package:pets_next_door_flutter/src/utils/timer_notifier_provider.dart'; - -final authVerifyNotifierProvider = NotifierProvider( - AuthVerifyNotifier.new, -); - -final sendAuthCodeStateProvider = Provider((ref) { - final timerState = ref.watch(timerNotifierProvider); - - if (timerState.isTimerTicking) { - return SendAuthCodeState.codeSent; - } - - if (timerState.timeLeft > Duration.zero) { - return SendAuthCodeState.initial; - } else { - return SendAuthCodeState.resendable; - } -}); - -enum SendAuthCodeState { - initial, - codeSent, - resendable, -} - -class AuthVerifyNotifier extends Notifier { - String _authCode = ''; - - @override - bool build() { - return false; - } - - void sendAuthCode() { - ref.watch(timerNotifierProvider.notifier).start(); - return; - } - - void _verifyAuthCode() { - // TODO: 여기서 필요한 통신 해야함 - final sendAuthCodeState = ref.watch(sendAuthCodeStateProvider); - if (sendAuthCodeState != SendAuthCodeState.codeSent) { - state = false; - } else { - if (_authCode == '12345') { - state = true; - } else { - state = false; - } - } - } - - void onAuthCodeChanged(String newCode) { - _authCode = newCode; - _verifyAuthCode(); - } -} diff --git a/lib/src/features/authentication/presentation/signup/phone_auth_view.dart b/lib/src/features/authentication/presentation/signup/phone_auth_view.dart deleted file mode 100644 index 4770a57..0000000 --- a/lib/src/features/authentication/presentation/signup/phone_auth_view.dart +++ /dev/null @@ -1,154 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:pets_next_door_flutter/src/constants/app_sizes.dart'; -import 'package:pets_next_door_flutter/src/features/authentication/presentation/signup/auth_verify_notifier_provider.dart'; -import 'package:pets_next_door_flutter/src/routing/app_router.dart'; -import 'package:pets_next_door_flutter/src/utils/timer_notifier_provider.dart'; -import 'package:pets_next_door_flutter/src/widgets/button/basic_activate_button.dart'; - -class PhoneAuthView extends StatelessWidget { - const PhoneAuthView({super.key}); - - @override - Widget build(BuildContext context) { - // final phoneAuthController = ref. - return Scaffold( - appBar: AppBar( - centerTitle: false, - leading: InkWell( - borderRadius: BorderRadius.circular(100), - radius: 18, - onTap: () => context.pop(), - child: Icon(Icons.arrow_back_ios_rounded), - ), - titleSpacing: 0, - title: const Text( - '휴대폰 번호 인증하기', - style: TextStyle(fontSize: 18), - ), - ), - body: GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - children: [ - Stack( - alignment: AlignmentDirectional.centerEnd, - children: [ - TextFormField( - decoration: const InputDecoration(hintText: '휴대폰 번호'), - ), - const Positioned( - child: PhoneAuthCodeSendButton(), - ), - ], - ), - gapH16, - const PhoneAuthCodeInputField(), - ], - ), - const PhoneAuthNextButton(), - ], - ), - ), - ), - ); - } -} - -class PhoneAuthCodeInputField extends StatelessWidget { - const PhoneAuthCodeInputField({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, WidgetRef ref, Widget? child) { - final timerProvider = ref.watch(timerNotifierProvider); - final authVerifyProvider = - ref.watch(authVerifyNotifierProvider.notifier); - return Stack( - alignment: AlignmentDirectional.centerEnd, - children: [ - TextFormField( - decoration: const InputDecoration(hintText: '인증번호 6자리'), - onChanged: authVerifyProvider.onAuthCodeChanged, - ), - Positioned( - child: Text( - timerProvider.timeLeftString, - ), - ), - ], - ); - }, - ); - } -} - -class PhoneAuthNextButton extends StatelessWidget { - const PhoneAuthNextButton({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, WidgetRef ref, Widget? child) { - final isAuthVerified = ref.watch(authVerifyNotifierProvider); - - return PNDBasicActivateButton( - isActive: isAuthVerified, - text: '다음으로', - onTap: () => context.pushNamed(AppRoute.profile.name), - ); - }, - ); - } -} - -class PhoneAuthCodeSendButton extends StatelessWidget { - const PhoneAuthCodeSendButton({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, WidgetRef ref, Widget? child) { - final authVerifyProvider = - ref.watch(authVerifyNotifierProvider.notifier); - final authVerified = ref.watch(authVerifyNotifierProvider); - final sendCodeButtonState = ref.watch(sendAuthCodeStateProvider); - - return GestureDetector( - onTap: () => (sendCodeButtonState != SendAuthCodeState.codeSent) - ? authVerifyProvider.sendAuthCode() - : null, - child: Container( - constraints: const BoxConstraints(maxWidth: 70, maxHeight: 32), - padding: const EdgeInsets.symmetric( - horizontal: 12, - ), - alignment: Alignment.center, - decoration: BoxDecoration( - color: authVerified ? Colors.grey : Colors.black, - borderRadius: BorderRadius.circular(100), - ), - child: const Text( - '인증하기', - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white, fontSize: 13, height: 1), - ), - ), - ); - }, - ); - } -} diff --git a/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.dart b/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.dart deleted file mode 100644 index 62bf76a..0000000 --- a/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pets_next_door_flutter/src/utils/timer_notifier_provider.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'phone_auth_view_controller.g.dart'; - -@riverpod -class PhoneAuthViewController extends _$PhoneAuthViewController { - @override - FutureOr build() { - // ok to leave this empty if the return type is FutureOr - } - - Future sendAuthCode() async { - ref.watch(timerNotifierProvider.notifier).start(); - } - - Future verifyAuthCode(String int) async {} -} - -final nextButtonStateProvider = Provider((ref) { - return null; -}); diff --git a/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.g.dart b/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.g.dart deleted file mode 100644 index 0a24b90..0000000 --- a/lib/src/features/authentication/presentation/signup/phone_auth_view_controller.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'phone_auth_view_controller.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$phoneAuthViewControllerHash() => - r'93c850f20cfd09f6362a32e091eee463643775b5'; - -/// See also [PhoneAuthViewController]. -@ProviderFor(PhoneAuthViewController) -final phoneAuthViewControllerProvider = - AutoDisposeAsyncNotifierProvider.internal( - PhoneAuthViewController.new, - name: r'phoneAuthViewControllerProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$phoneAuthViewControllerHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$PhoneAuthViewController = AutoDisposeAsyncNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member diff --git a/lib/src/features/authentication/presentation/signup/send_code_button_provider.dart b/lib/src/features/authentication/presentation/signup/send_code_button_provider.dart deleted file mode 100644 index 30d7c61..0000000 --- a/lib/src/features/authentication/presentation/signup/send_code_button_provider.dart +++ /dev/null @@ -1,3 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pets_next_door_flutter/src/utils/timer_notifier_provider.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart';