Skip to content

Commit

Permalink
Implement apple login (#70)
Browse files Browse the repository at this point in the history
* Implement apple login for iOS

* Implement apple login for iOS

* Implement apple login for iOS

* Reformat files

* Clean up

* Clean up
  • Loading branch information
cp-sneha-s authored Mar 11, 2024
1 parent 1969123 commit 8e8b80b
Show file tree
Hide file tree
Showing 27 changed files with 607 additions and 200 deletions.
24 changes: 13 additions & 11 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
id "com.google.gms.google-services"
id "com.google.firebase.crashlytics"
}


def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
Expand All @@ -6,10 +15,6 @@ if (localPropertiesFile.exists()) {
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
Expand All @@ -21,14 +26,11 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'



android {
compileSdkVersion 33//flutter.compileSdkVersion
compileSdkVersion 34//flutter.compileSdkVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand Down Expand Up @@ -100,5 +102,5 @@ flutter {
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0"
}
14 changes: 0 additions & 14 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
buildscript {
ext.kotlin_version = '1.8.21'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
}
}

allprojects {
repositories {
Expand Down
33 changes: 25 additions & 8 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.0.4" apply false
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
id "com.google.gms.google-services" version "4.3.10" apply false
id "com.google.firebase.crashlytics" version "2.9.9" apply false

}

include ":app"
5 changes: 5 additions & 0 deletions assets/images/apple_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/images/google_logo.png
Binary file not shown.
8 changes: 8 additions & 0 deletions assets/images/google_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
</plist>
7 changes: 6 additions & 1 deletion ios/Runner/RunnerDebug.entitlements
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
</plist>
5 changes: 2 additions & 3 deletions lib/data/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

"sign_in_description_text": "Help you to manage your office leaves and employees easily with unity.",
"sign_in_title_text": "Effortless Leave\nManagement with Unity",
"login_button_text": "Sign in with Google",
"company_name": "Canopas Software",
"company_subtitle": "www.canopas.com",
"google_login_button_text": "Sign in with Google",
"apple_login_button_text": "Sign in with Apple",

"settings_tag": "Settings",
"members_tag": "Members",
Expand Down
29 changes: 24 additions & 5 deletions lib/data/services/auth_service.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:flutter/foundation.dart';
Expand Down Expand Up @@ -46,7 +48,7 @@ class AuthService {
idToken: googleSignInAuthentication.idToken,
);

user = await _signInWithCredentials(credential);
user = await signInWithCredentials(credential);
await googleSignIn.signOut();
}
} catch (e) {
Expand All @@ -63,7 +65,7 @@ class AuthService {
idToken: credentials.idToken,
accessToken: credentials.accessToken);

user = await _signInWithCredentials(authCredential);
user = await signInWithCredentials(authCredential);

await _desktopAuthManager.signOutFromGoogle(credentials.accessToken);
} on Exception {
Expand All @@ -73,8 +75,9 @@ class AuthService {
return user;
}

Future<firebase_auth.User?> _signInWithCredentials(
firebase_auth.AuthCredential authCredential) async {
Future<firebase_auth.User?> signInWithCredentials(
firebase_auth.AuthCredential authCredential,
) async {
firebase_auth.User? user;
try {
final firebase_auth.UserCredential userCredential =
Expand All @@ -86,7 +89,23 @@ class AuthService {
return user;
}

Future<bool> signOutWithGoogle() async {
Future<firebase_auth.User?> signInWithApple() async {
final firebase_auth.UserCredential? credential;

firebase_auth.AppleAuthProvider appleProvider =
firebase_auth.AppleAuthProvider();
if (kIsWeb) {
credential = await firebase_auth.FirebaseAuth.instance
.signInWithPopup(appleProvider);
} else {
credential = await firebase_auth.FirebaseAuth.instance
.signInWithProvider(appleProvider);
}

return credential.user;
}

Future<bool> signOut() async {
try {
await firebaseAuth.signOut();
return true;
Expand Down
9 changes: 6 additions & 3 deletions lib/gen/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions lib/style/other/smart_scroll_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// A scrollview that supports Spacer to fill the remaining space
import 'package:flutter/cupertino.dart';

class SmartScrollView extends StatelessWidget {
final Widget child;
final EdgeInsetsGeometry? padding;
final ScrollController? controller;

const SmartScrollView({
super.key,
required this.child,
this.padding,
this.controller,
});

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
controller: controller,
padding: padding,
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - (padding?.vertical ?? 0),
),
child: IntrinsicHeight(
child: child,
),
),
);
},
);
}
}
2 changes: 1 addition & 1 deletion lib/ui/admin/members/list/member_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class HeaderDelegate extends SliverPersistentHeaderDelegate {
}

@override
double get maxExtent => 100;
double get maxExtent => 80;

@override
double get minExtent => 60;
Expand Down
36 changes: 29 additions & 7 deletions lib/ui/sign_in/bloc/sign_in_view_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
Expand All @@ -19,23 +20,44 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
this._userStateNotifier,
this._authService,
this._accountService,
) : super(SignInInitialState()) {
on<SignInEvent>(_signIn);
) : super(const SignInState()) {
on<GoogleSignInEvent>(_googleSignIn);
on<AppleSignInEvent>(_appleSignIn);
}

Future<void> _signIn(SignInEvent event, Emitter<SignInState> emit) async {
emit(SignInLoadingState());
Future<void> _googleSignIn(
SignInEvent event, Emitter<SignInState> emit) async {
try {
emit(state.copyWith(googleSignInLoading: true));
firebase_auth.User? authUser = await _authService.signInWithGoogle();
if (authUser != null) {
final Account user = await _accountService.getUser(authUser);
await _userStateNotifier.setUser(user);
emit(SignInSuccessState());
emit(state.copyWith(googleSignInLoading: false, signInSuccess: true));
} else {
emit(SignInInitialState());
emit(state.copyWith(googleSignInLoading: false));
}
} on Exception {
emit(SignInFailureState(error: firesbaseAuthError));
emit(state.copyWith(
googleSignInLoading: false, error: firesbaseAuthError));
}
}

Future<void> _appleSignIn(
AppleSignInEvent event, Emitter<SignInState> emit) async {
try {
emit(state.copyWith(appleSignInLoading: true));
firebase_auth.User? authUser = await _authService.signInWithApple();
if (authUser != null) {
final Account user = await _accountService.getUser(authUser);
await _userStateNotifier.setUser(user);
emit(state.copyWith(appleSignInLoading: false, signInSuccess: true));
} else {
emit(state.copyWith(appleSignInLoading: false));
}
} on Exception {
emit(state.copyWith(
appleSignInLoading: false, error: somethingWentWrongError));
}
}
}
9 changes: 4 additions & 5 deletions lib/ui/sign_in/bloc/sign_in_view_event.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:equatable/equatable.dart';
abstract class SignInEvent {}

class SignInEvent extends Equatable {
@override
List<Object?> get props => [];
}
class GoogleSignInEvent extends SignInEvent {}

class AppleSignInEvent extends SignInEvent {}
38 changes: 12 additions & 26 deletions lib/ui/sign_in/bloc/sign_in_view_state.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
import 'package:equatable/equatable.dart';

abstract class SignInState extends Equatable {}

class SignInInitialState extends SignInState {
@override
List<Object?> get props => [];
}

class SignInLoadingState extends SignInState {
@override
List<Object?> get props => [];
}

class SignInFailureState extends SignInState {
final String error;

SignInFailureState({required this.error});

@override
List<Object?> get props => [error];
}

class SignInSuccessState extends SignInState {
@override
List<Object?> get props => [];
import 'package:freezed_annotation/freezed_annotation.dart';

part "sign_in_view_state.freezed.dart";

@freezed
class SignInState with _$SignInState {
const factory SignInState(
{@Default(false) appleSignInAvailable,
@Default(false) googleSignInLoading,
@Default(false) appleSignInLoading,
@Default(false) signInSuccess,
String? error}) = _SignInState;
}
Loading

0 comments on commit 8e8b80b

Please sign in to comment.