diff --git a/android/app/build.gradle b/android/app/build.gradle index f9777e1..b5cea76 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -36,7 +36,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "org.zxconnect.mobile.le_kiosque_by_gcs" - minSdkVersion 16 + minSdkVersion 21 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/assets/images/2.0x/facebook_logo.png b/assets/images/2.0x/facebook_logo.png new file mode 100755 index 0000000..4bf7e36 Binary files /dev/null and b/assets/images/2.0x/facebook_logo.png differ diff --git a/assets/images/2.0x/google_logo.png b/assets/images/2.0x/google_logo.png new file mode 100644 index 0000000..725529a Binary files /dev/null and b/assets/images/2.0x/google_logo.png differ diff --git a/assets/images/3.0x/facebook_logo.png b/assets/images/3.0x/facebook_logo.png new file mode 100755 index 0000000..bd4075b Binary files /dev/null and b/assets/images/3.0x/facebook_logo.png differ diff --git a/assets/images/3.0x/google_logo.png b/assets/images/3.0x/google_logo.png new file mode 100644 index 0000000..2a568f1 Binary files /dev/null and b/assets/images/3.0x/google_logo.png differ diff --git a/assets/images/facebook_logo.png b/assets/images/facebook_logo.png new file mode 100755 index 0000000..d00e4ba Binary files /dev/null and b/assets/images/facebook_logo.png differ diff --git a/assets/images/google_logo.png b/assets/images/google_logo.png new file mode 100644 index 0000000..2658fe5 Binary files /dev/null and b/assets/images/google_logo.png differ diff --git a/assets/images/kiosque_logo.png b/assets/images/kiosque_logo.png new file mode 100644 index 0000000..bdba529 Binary files /dev/null and b/assets/images/kiosque_logo.png differ diff --git a/assets/images/login_back.png b/assets/images/login_back.png new file mode 100644 index 0000000..38ef637 Binary files /dev/null and b/assets/images/login_back.png differ diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index fcefcbf..33edf9b 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,56 +1,57 @@ - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - le_kiosque_by_gcs - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - CFBundleURLTypes - - - CFBundleURLSchemes - - fb894030758020771 - - - - FacebookAppID - 894030758020771 - FacebookDisplayName - Le Kiosque By GC&S - + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + le_kiosque_by_gcs + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CFBundleURLTypes + + + CFBundleURLSchemes + + fb894030758020771 + com.googleusercontent.apps.944092516126-hkrk2q9uqomp41t2sttm47hpu7av0t81 + + + + FacebookAppID + 894030758020771 + FacebookDisplayName + Le Kiosque By GC&S + diff --git a/lib/main.dart b/lib/main.dart index 0e5a1ac..6748065 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,11 @@ +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:le_kiosque_by_gcs/services/auth/main_auth.dart'; +import 'package:le_kiosque_by_gcs/ui/landing.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(); runApp(MyApp()); } @@ -8,12 +13,14 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - showSemanticsDebugger: false, + debugShowCheckedModeBanner: false, title: 'Le Kiosque By GC&S', theme: ThemeData( - primarySwatch: Colors.white, + primarySwatch: Colors.blue, + ), + home: LandingPageView( + auth: MainAuth(), ), - home: Container(), ); } } diff --git a/lib/services/auth/auth.dart b/lib/services/auth/auth.dart new file mode 100644 index 0000000..05c2a12 --- /dev/null +++ b/lib/services/auth/auth.dart @@ -0,0 +1,13 @@ + +import 'package:firebase_auth/firebase_auth.dart'; + +abstract class Auth { + Future signInWithGoogle(); + + Future signInWithFacebook(); + + Future signOut(); + + Stream authStateChanges(); +} + diff --git a/lib/services/auth/main_auth.dart b/lib/services/auth/main_auth.dart new file mode 100644 index 0000000..b22451a --- /dev/null +++ b/lib/services/auth/main_auth.dart @@ -0,0 +1,69 @@ + +import 'package:le_kiosque_by_gcs/services/auth/auth.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter_login_facebook/flutter_login_facebook.dart'; +import 'package:google_sign_in/google_sign_in.dart'; + +class MainAuth implements Auth { + + FirebaseAuth _auth = FirebaseAuth.instance; + + @override + Future signInWithGoogle() async { + final googleSignIn = GoogleSignIn(); + final googleUser = await googleSignIn.signIn(); + + if (googleUser != null) { + final userAuth = await googleUser.authentication; + if (userAuth.accessToken != null) { + final authCredential = GoogleAuthProvider.credential( + accessToken: userAuth.accessToken, idToken: userAuth.idToken); + final authResult = await _auth.signInWithCredential(authCredential); + return authResult.user; + } else { + throw FirebaseAuthException(message: "Auth Abord"); + } + } else { + throw FirebaseAuthException(message: "Auth Abord"); + } + } + + @override + Future signOut() async { + final googleSignIn = GoogleSignIn(); + final facebookAuth = FacebookLogin(); + + await facebookAuth.logOut(); + await googleSignIn.signOut(); + await _auth.signOut(); + } + + @override + Stream authStateChanges() => _auth.authStateChanges(); + + @override + Future signInWithFacebook() async { + final facebookAuth = FacebookLogin(); + final result = await facebookAuth.logIn(permissions: [ + FacebookPermission.publicProfile, + FacebookPermission.email + ]); + + switch (result.status) { + case FacebookLoginStatus.Success: + final accessToken = result.accessToken.token; + final credential = FacebookAuthProvider.credential(accessToken); + final authResult = await _auth.signInWithCredential(credential); + return authResult.user; + break; + case FacebookLoginStatus.Cancel: + throw FirebaseAuthException(message: "Auth Abord"); + break; + case FacebookLoginStatus.Error: + throw FirebaseAuthException(message: result.error.developerMessage); + break; + default: + throw UnimplementedError(); + } + } +} \ No newline at end of file diff --git a/lib/ui/auth.dart b/lib/ui/auth.dart index 783638b..0eb69c6 100644 --- a/lib/ui/auth.dart +++ b/lib/ui/auth.dart @@ -1,13 +1,107 @@ import 'package:flutter/material.dart'; +import 'package:le_kiosque_by_gcs/services/auth/auth.dart'; -class AuthView extends StatefulWidget { - @override - _AuthViewState createState() => _AuthViewState(); -} +import 'custom/custom_elevated_button.dart'; + +class AuthView extends StatelessWidget { + const AuthView({Key key, this.auth}) : super(key: key); + final Auth auth; + + Future _signWithGoogle() async { + try { + await auth.signInWithGoogle(); + } catch (e) { + print("Error $e"); + } + } + + Future _signInWithFacebook() async { + try { + await auth.signInWithFacebook(); + } catch (e) { + print("Error $e"); + } + } -class _AuthViewState extends State { @override Widget build(BuildContext context) { - return Container(); + return Scaffold( + resizeToAvoidBottomInset: false, + body: Column( + children: [ + Container( + height: 550, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/login_back.png"), + fit: BoxFit.cover, + ), + ), + ), + Expanded( + child: Transform.translate( + offset: Offset(0, -50), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), + child: Padding( + padding: const EdgeInsets.only( + top: 32, + left: 24, + right: 24, + bottom: 24, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "S'identifier", + style: TextStyle( + fontSize: 26, + fontWeight: FontWeight.bold, + color: Colors.black, + inherit: false), + ), + SizedBox(height: 32), + CustomElevatedButton( + imageAsset: "assets/images/google_logo.png", + color: Colors.white, + textColor: Colors.black, + onPressed: _signWithGoogle, + text: "Se connecter avec Google", + ), + SizedBox(height: 24), + CustomElevatedButton( + imageAsset: "assets/images/facebook_logo.png", + color: Color(0xFF334D92), + textColor: Colors.white, + onPressed: _signInWithFacebook, + text: "Se connecter avec Facebook", + ), + SizedBox( + height: 48, + ), + Text( + "En vous connectant, vous acceptez nos conditions et termes d'utilisation.", + style: TextStyle( + inherit: false, + color: Colors.black87, + ), + ) + ], + ), + ), + ), + ), + ) + ], + ), + ); } } diff --git a/lib/ui/custom/custom_elevated_button.dart b/lib/ui/custom/custom_elevated_button.dart new file mode 100644 index 0000000..9a37d79 --- /dev/null +++ b/lib/ui/custom/custom_elevated_button.dart @@ -0,0 +1,58 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class CustomElevatedButton extends StatelessWidget { + CustomElevatedButton({ + this.onPressed, + this.color, + this.height: 50, + this.textColor, + this.text, + this.imageAsset: "", + }); + + final VoidCallback onPressed; + final Color color; + final double height; + final Color textColor; + final String text; + final String imageAsset; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: height, + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(color), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(16), + ), + ), + ), + ), + onPressed: onPressed, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 20, + width: 20, + child: Image.asset(imageAsset), + ), + Text( + text, + style: TextStyle(fontSize: 15, color: textColor), + ), + Opacity( + child: Image.asset(imageAsset), + opacity: 0, + ), + ], + ), + ), + ); + } +} diff --git a/lib/ui/landing.dart b/lib/ui/landing.dart new file mode 100644 index 0000000..13ee921 --- /dev/null +++ b/lib/ui/landing.dart @@ -0,0 +1,34 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:le_kiosque_by_gcs/services/auth/auth.dart'; +import 'package:le_kiosque_by_gcs/ui/auth.dart'; +import 'package:le_kiosque_by_gcs/ui/main.dart'; + +class LandingPageView extends StatelessWidget { + final Auth auth; + + const LandingPageView({Key key, this.auth}) : super(key: key); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: auth.authStateChanges(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.active) { + if (snapshot.data == null) { + return AuthView(auth: auth); + } else { + return MainView(); + } + } + else { + return Scaffold( + body: Center( + child: CircularProgressIndicator(), + ), + ); + } + } + ); + } +} diff --git a/lib/ui/main.dart b/lib/ui/main.dart new file mode 100644 index 0000000..03f71e1 --- /dev/null +++ b/lib/ui/main.dart @@ -0,0 +1,104 @@ +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +class MainView extends StatefulWidget { + @override + _MainViewState createState() => _MainViewState(); +} + +class _MainViewState extends State { + int _selectedIndex = 0; + + void _onItemTapped(int index) { + setState(() { + _selectedIndex = index; + }); + } + + void _showSearchView(BuildContext context) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => Scaffold(), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + "Le Kiosque By GC&S", + style: TextStyle( + color: Colors.black, + ), + ), + leading: Builder( + builder: (BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 16), + child: Image.asset("assets/images/kiosque_logo.png"), + ); + }, + ), + elevation: 4, + actions: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Color(0xFFF1F1F1), + ), + child: TextButton( + onPressed: () => _showSearchView(context), + child: Icon( + Icons.search, + color: Colors.grey, + ), + ), + ), + ) + ], + backgroundColor: Colors.white, + ), + bottomNavigationBar: BottomNavigationBar( + currentIndex: _selectedIndex, + type: BottomNavigationBarType.fixed, + onTap: _onItemTapped, + selectedItemColor: Colors.grey, + items: [ + BottomNavigationBarItem( + icon: Icon( + Icons.home_rounded, + color: Colors.grey, + ), + label: 'Accueil', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.subscriptions_rounded, + color: Colors.grey, + ), + label: 'A la une', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.amp_stories_rounded, + color: Colors.grey, + ), + label: 'Abonnement', + ), + BottomNavigationBarItem( + icon: Icon( + Icons.people_rounded, + color: Colors.grey, + ), + label: 'Mon profil', + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 376591e..8354044 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -111,6 +111,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_auth_buttons: + dependency: "direct main" + description: + name: flutter_auth_buttons + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.0" flutter_login_facebook: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 874a627..50f6e1f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,6 +32,7 @@ dependencies: firebase_auth: 0.18.2 google_sign_in: ^4.5.6 flutter_login_facebook: 0.4.0+1 + flutter_auth_buttons: ^0.10.0 dev_dependencies: flutter_test: @@ -48,6 +49,9 @@ flutter: # the material Icons class. uses-material-design: true + assets: + - assets/images/ + # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg