구글 로그인 구현
This commit is contained in:
parent
fa65ed3d15
commit
0fdaa1f6dd
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
1313
.idea/caches/deviceStreaming.xml
generated
Normal file
1313
.idea/caches/deviceStreaming.xml
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
.idea/deviceManager.xml
generated
Normal file
13
.idea/deviceManager.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DeviceTable">
|
||||
<option name="columnSorters">
|
||||
<list>
|
||||
<ColumnSorterState>
|
||||
<option name="column" value="Name" />
|
||||
<option name="order" value="ASCENDING" />
|
||||
</ColumnSorterState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
5
.idea/misc.xml
generated
Normal file
5
.idea/misc.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/rup.iml" filepath="$PROJECT_DIR$/.idea/rup.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
13
.idea/rup.iml
generated
Normal file
13
.idea/rup.iml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/app/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/app/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -3,6 +3,7 @@ plugins {
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
id("com.google.gms.google-services")
|
||||
}
|
||||
|
||||
android {
|
||||
@ -21,7 +22,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.app"
|
||||
applicationId = "com.example.rup"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
|
||||
47
app/android/app/google-services.json
Normal file
47
app/android/app/google-services.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "379988243470",
|
||||
"project_id": "rup-project-9d4c4",
|
||||
"storage_bucket": "rup-project-9d4c4.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:379988243470:android:b4a4761b906eb44a1cb85f",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.rup"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "379988243470-jd0c59ci9ksr36er7sjkrkc4rtgmll1a.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "com.example.rup",
|
||||
"certificate_hash": "7bda16a71840f93ab7c41fecc24da2bde3702424"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "379988243470-g6490l8gucc3ljras93i28c3l4qlroi4.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAql00w1JB6n5wb4StXi9eyixVyIuT3-Hg"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "379988243470-g6490l8gucc3ljras93i28c3l4qlroi4.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:label="app"
|
||||
android:name="${applicationName}"
|
||||
|
||||
@ -1,3 +1,13 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.google.gms:google-services:4.3.15")
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
|
||||
@ -1,7 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'screens/splash_screen.dart';
|
||||
import 'dart:developer';
|
||||
|
||||
void main() {
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
try {
|
||||
await Firebase.initializeApp();
|
||||
} catch (e) {
|
||||
log('Firebase initialization failed: $e');
|
||||
}
|
||||
runApp(RupApp());
|
||||
}
|
||||
|
||||
|
||||
@ -1,119 +1,176 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import '../services/auth_service.dart';
|
||||
import 'home_screen.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LoginScreen> createState() => _LoginScreenState();
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
bool _isLoading = false;
|
||||
|
||||
Future<void> _handleGoogleLogin() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final authService = AuthService();
|
||||
final user = await authService.signInWithGoogle();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
if (user != null) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const HomeScreen()),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('로그인이 취소되었습니다.')));
|
||||
}
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('로그인 실패: $e')));
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.black, size: 20),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: const Text(
|
||||
'로그인',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 240),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset('assets/img/foot.png', width: 30),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
'로그인',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
return Stack(
|
||||
children: [
|
||||
Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
'RUP에 어서오세요!\n지금 로그인하고 다양한 서비스를 이용해보세요.',
|
||||
title: const Text(
|
||||
'로그인',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Spacer(),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Image.asset('assets/img/cat.png', height: 150),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 240),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset('assets/img/foot.png', width: 30),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
'로그인',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
'RUP에 어서오세요!\n지금 로그인하고 다양한 서비스를 이용해보세요.',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Spacer(),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Image.asset('assets/img/cat.png', height: 150),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
bottomSheet: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 40),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Naver Login Button
|
||||
_SocialLoginButton(
|
||||
text: '네이버 로그인',
|
||||
textColor: Colors.white,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFF00D03F),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/navericon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Kakao Login Button
|
||||
_SocialLoginButton(
|
||||
text: '카카오 로그인',
|
||||
textColor: const Color(0xFF212121),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFFFAE100),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/kakaoicon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Google Login Button
|
||||
_SocialLoginButton(
|
||||
text: '구글 로그인',
|
||||
textColor: const Color(0xFF17191A),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Colors.white,
|
||||
onPressed: _handleGoogleLogin,
|
||||
iconPath: 'assets/icons/googleicon.svg',
|
||||
isBordered: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomSheet: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 40),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Naver Login Button
|
||||
_SocialLoginButton(
|
||||
text: '네이버 로그인',
|
||||
textColor: Colors.white,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFF00D03F),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/navericon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Kakao Login Button
|
||||
_SocialLoginButton(
|
||||
text: '카카오 로그인',
|
||||
textColor: const Color(0xFF212121),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFFFAE100),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/kakaoicon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Google Login Button
|
||||
_SocialLoginButton(
|
||||
text: '구글 로그인',
|
||||
textColor: const Color(0xFF17191A),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Colors.white,
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/googleicon.svg',
|
||||
isBordered: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_isLoading)
|
||||
Container(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,119 +1,176 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import '../services/auth_service.dart';
|
||||
import 'home_screen.dart';
|
||||
|
||||
class SignupScreen extends StatelessWidget {
|
||||
class SignupScreen extends StatefulWidget {
|
||||
const SignupScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SignupScreen> createState() => _SignupScreenState();
|
||||
}
|
||||
|
||||
class _SignupScreenState extends State<SignupScreen> {
|
||||
bool _isLoading = false;
|
||||
|
||||
Future<void> _handleGoogleLogin() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final authService = AuthService();
|
||||
final user = await authService.signInWithGoogle();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
if (user != null) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const HomeScreen()),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('로그인이 취소되었습니다.')));
|
||||
}
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('로그인 실패: $e')));
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios, color: Colors.black, size: 20),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Text(
|
||||
'회원가입',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 240),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset('assets/img/foot.png', width: 30),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
'서비스 이용 약관',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
return Stack(
|
||||
children: [
|
||||
Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
'똑똑한 반려생활을 위한 첫걸음,\nRUP에 오신것을 환영해요!',
|
||||
title: const Text(
|
||||
'회원가입',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Spacer(),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Image.asset('assets/img/cat.png', height: 150),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 240),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset('assets/img/foot.png', width: 30),
|
||||
const SizedBox(width: 10),
|
||||
const Text(
|
||||
'서비스 이용 약관',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const Text(
|
||||
'똑똑한 반려생활을 위한 첫걸음,\nRUP에 오신것을 환영해요!',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
const Spacer(),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Image.asset('assets/img/cat.png', height: 150),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
bottomSheet: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 40),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Naver Login Button
|
||||
_SocialLoginButton(
|
||||
text: '네이버 로그인',
|
||||
textColor: Colors.white,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFF00D03F),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/navericon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Kakao Login Button
|
||||
_SocialLoginButton(
|
||||
text: '카카오로 3초만에 시작하기',
|
||||
textColor: const Color(0xFF212121),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: const Color(0xFFFAE100),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/kakaoicon.svg',
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
// Google Login Button
|
||||
_SocialLoginButton(
|
||||
text: '구글 로그인',
|
||||
textColor: const Color(0xFF17191A),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Colors.white,
|
||||
onPressed: _handleGoogleLogin,
|
||||
iconPath: 'assets/icons/googleicon.svg',
|
||||
isBordered: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomSheet: Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.fromLTRB(20, 20, 20, 40),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Naver Login Button
|
||||
_SocialLoginButton(
|
||||
text: '네이버 로그인',
|
||||
textColor: Colors.white,
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Color(0xFF00D03F),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/navericon.svg',
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
// Kakao Login Button
|
||||
_SocialLoginButton(
|
||||
text: '카카오로 3초만에 시작하기',
|
||||
textColor: Color(0xFF212121),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Color(0xFFFAE100),
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/kakaoicon.svg',
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
// Google Login Button
|
||||
_SocialLoginButton(
|
||||
text: '구글 로그인',
|
||||
textColor: Color(0xFF17191A),
|
||||
fontFamily: 'SCDream',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
backgroundColor: Colors.white,
|
||||
onPressed: () {},
|
||||
iconPath: 'assets/icons/googleicon.svg',
|
||||
isBordered: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_isLoading)
|
||||
Container(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFFF7500), // Original Brand Color
|
||||
backgroundColor: const Color(0xFFFF7500),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
51
app/lib/services/auth_service.dart
Normal file
51
app/lib/services/auth_service.dart
Normal file
@ -0,0 +1,51 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
|
||||
class AuthService {
|
||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||
final GoogleSignIn _googleSignIn = GoogleSignIn();
|
||||
|
||||
// 구글 로그인
|
||||
Future<UserCredential?> signInWithGoogle() async {
|
||||
// 1. 구글 로그인 흐름 시작
|
||||
print('[DEBUG] Google Sign-In: Starting signIn()');
|
||||
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
|
||||
print(
|
||||
'[DEBUG] Google Sign-In: signIn() completed, user: ${googleUser?.email}',
|
||||
);
|
||||
|
||||
if (googleUser == null) {
|
||||
// 사용자가 로그인 창을 닫음
|
||||
print('[DEBUG] Google Sign-In: User canceled');
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 인증 세부 정보 요청
|
||||
print('[DEBUG] Google Sign-In: Getting authentication...');
|
||||
final GoogleSignInAuthentication googleAuth =
|
||||
await googleUser.authentication;
|
||||
print(
|
||||
'[DEBUG] Google Sign-In: Authentication received. AccessToken: ${googleAuth.accessToken != null}, IDToken: ${googleAuth.idToken != null}',
|
||||
);
|
||||
|
||||
// 3. 자격 증명 생성
|
||||
final OAuthCredential credential = GoogleAuthProvider.credential(
|
||||
accessToken: googleAuth.accessToken,
|
||||
idToken: googleAuth.idToken,
|
||||
);
|
||||
|
||||
// 4. Firebase에 로그인
|
||||
print('[DEBUG] Google Sign-In: Signing in with credential to Firebase...');
|
||||
final userCredential = await _auth.signInWithCredential(credential);
|
||||
print(
|
||||
'[DEBUG] Google Sign-In: Firebase sign-in completed. User: ${userCredential.user?.uid}',
|
||||
);
|
||||
return userCredential;
|
||||
}
|
||||
|
||||
// 로그아웃
|
||||
Future<void> signOut() async {
|
||||
await _googleSignIn.signOut();
|
||||
await _auth.signOut();
|
||||
}
|
||||
}
|
||||
@ -5,8 +5,14 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import firebase_auth
|
||||
import firebase_core
|
||||
import google_sign_in_ios
|
||||
import video_player_avfoundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
|
||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||
}
|
||||
|
||||
104
app/pubspec.lock
104
app/pubspec.lock
@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_flutterfire_internals:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _flutterfire_internals
|
||||
sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.59"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -73,6 +81,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
firebase_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_auth
|
||||
sha256: "0fed2133bee1369ee1118c1fef27b2ce0d84c54b7819a2b17dada5cfec3b03ff"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.7.0"
|
||||
firebase_auth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_platform_interface
|
||||
sha256: "871c9df4ec9a754d1a793f7eb42fa3b94249d464cfb19152ba93e14a5966b386"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.7.3"
|
||||
firebase_auth_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_web
|
||||
sha256: d9ada769c43261fd1b18decf113186e915c921a811bd5014f5ea08f4cf4bc57e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.15.3"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.15.2"
|
||||
firebase_core_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_platform_interface
|
||||
sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
firebase_core_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_web
|
||||
sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.24.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -104,6 +160,54 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
google_identity_services_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_identity_services_web
|
||||
sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+1"
|
||||
google_sign_in:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: google_sign_in
|
||||
sha256: d0a2c3bcb06e607bb11e4daca48bd4b6120f0bbc4015ccebbe757d24ea60ed2a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
google_sign_in_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_android
|
||||
sha256: d5e23c56a4b84b6427552f1cf3f98f716db3b1d1a647f16b96dbb5b93afa2805
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
google_sign_in_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_ios
|
||||
sha256: "102005f498ce18442e7158f6791033bbc15ad2dcc0afa4cf4752e2722a516c96"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.9.0"
|
||||
google_sign_in_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_platform_interface
|
||||
sha256: "5f6f79cf139c197261adb6ac024577518ae48fdff8e53205c5373b5f6430a8aa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
google_sign_in_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_web
|
||||
sha256: "460547beb4962b7623ac0fb8122d6b8268c951cf0b646dd150d60498430e4ded"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.4+4"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -36,6 +36,9 @@ dependencies:
|
||||
cupertino_icons: ^1.0.8
|
||||
flutter_svg: ^2.0.10
|
||||
video_player: ^2.8.2
|
||||
firebase_core: ^3.0.0 # 파이어베이스 기본 (Updated)
|
||||
firebase_auth: ^5.0.0 # 인증 기능 (Updated)
|
||||
google_sign_in: ^6.2.1 # 구글 로그인 UI/기능 (Updated)
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@ -6,6 +6,12 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <firebase_auth/firebase_auth_plugin_c_api.h>
|
||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FirebaseAuthPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi"));
|
||||
FirebaseCorePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
firebase_auth
|
||||
firebase_core
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user