Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lulin/task/apple signin #55

Merged
merged 3 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 18 additions & 28 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ PODS:
- AppAuth/Core (1.7.5)
- AppAuth/ExternalUserAgent (1.7.5):
- AppAuth/Core
- device_info (0.0.1):
- device_info_plus (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_secure_storage (6.0.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- Toast
- google_sign_in_ios (0.0.1):
- AppAuth (>= 1.7.4)
- Flutter
Expand All @@ -35,35 +32,33 @@ PODS:
- GTMSessionFetcher/Core
- in_app_review (0.2.0):
- Flutter
- launch_review (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- share (0.0.1):
- share_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- Toast (4.1.0)
- sign_in_with_apple (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter

DEPENDENCIES:
- app_tracking_transparency (from `.symlinks/plugins/app_tracking_transparency/ios`)
- device_info (from `.symlinks/plugins/device_info/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- launch_review (from `.symlinks/plugins/launch_review/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- share (from `.symlinks/plugins/share/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)

SPEC REPOS:
Expand All @@ -72,56 +67,51 @@ SPEC REPOS:
- GoogleSignIn
- GTMAppAuth
- GTMSessionFetcher
- Toast

EXTERNAL SOURCES:
app_tracking_transparency:
:path: ".symlinks/plugins/app_tracking_transparency/ios"
device_info:
:path: ".symlinks/plugins/device_info/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
:path: Flutter
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
google_sign_in_ios:
:path: ".symlinks/plugins/google_sign_in_ios/darwin"
in_app_review:
:path: ".symlinks/plugins/in_app_review/ios"
launch_review:
:path: ".symlinks/plugins/launch_review/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
share:
:path: ".symlinks/plugins/share/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sign_in_with_apple:
:path: ".symlinks/plugins/sign_in_with_apple/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"

SPEC CHECKSUMS:
app_tracking_transparency: e169b653478da7bb15a6c61209015378ca73e375
AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
launch_review: 75d5a956ba8eaa493e9c9d4bf4c05e505e8d5ed0
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
Toast: ec33c32b8688982cecc6348adeae667c1b9938da
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe

PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
5 changes: 2 additions & 3 deletions ios/Runner/Runner.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<key>com.apple.developer.applesignin</key>
<array>
<string>applinks:compositesai.com</string>
<string>webcredentials:compositesai.com</string>
<string>Default</string>
</array>
</dict>
</plist>
66 changes: 66 additions & 0 deletions lib/presentation/settings/viewModels/login_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// lib/presentation/viewmodels/login_view_model.dart

import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:domain/usecases/auth_usecase.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:http/http.dart' as http;

class LoginViewModel extends ChangeNotifier {
final AuthUseCase authUseCase;
Expand Down Expand Up @@ -109,4 +113,66 @@ class LoginViewModel extends ChangeNotifier {
final accessToken = await authUseCase.syncUser(displayName, email, photoUrl);
return accessToken;
}

Future<void> signInWithApple() async {
try {
// Request credentials from Apple
final credential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
webAuthenticationOptions: WebAuthenticationOptions(
clientId: 'com.example.swiftcompsignin',
redirectUri: kIsWeb //This is where Apple sends the user back after they sign in.
? Uri.parse('https://compositesai.com/')
: Uri.parse(
'https://flutter-sign-in-with-apple-example.glitch.me/callbacks/sign_in_with_apple',
),
),
);

final identityToken = credential.identityToken;

if (identityToken == null) {
throw Exception('Identity token not available in Apple credentials');
}
// Send token to backend for validation
// This is where app sends token to backend to check if the the "identityToken" is real and safe to use.
final validateTokenEndpoint = Uri.parse('http://localhost:8080/api/auth/sign_in_with_apple');
final validationResponse = await http.Client().post(
validateTokenEndpoint,
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'identityToken': identityToken,
}),
);

if (validationResponse.statusCode != 200) {
print('Token validation failed: ${validationResponse.body}');
throw Exception('Failed to validate token with backend');
}
print('Token validated successfully: ${validationResponse.body}');

// Extract user information
final String? email = credential.email;
final String? givenName = credential.givenName;

if (email == null) {
throw Exception('Email not available in Apple credentials');
}

// Sync user with backend (you may modify syncUser based on backend response if needed)
await syncUser(givenName, email, null);

// Notify listeners for UI update
notifyListeners();
} catch (e) {
print('Sign in with Apple failed: $e');
rethrow; // Optionally rethrow for higher-level error handling
}
}

}
41 changes: 20 additions & 21 deletions lib/presentation/settings/viewModels/settings_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
// lib/presentation/viewmodels/settings_view_model.dart

import 'dart:io';
import 'package:device_info/device_info.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:domain/entities/user.dart';
import 'package:domain/usecases/auth_usecase.dart';
import 'package:domain/usecases/user_usercase.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:share_plus/share_plus.dart';
import 'package:swiftcomp/presentation/settings/providers/feature_flag_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:launch_review/launch_review.dart';
import 'package:share/share.dart';


class SettingsViewModel extends ChangeNotifier {
Expand Down Expand Up @@ -84,23 +82,33 @@ class SettingsViewModel extends ChangeNotifier {
Future<void> newLogout(BuildContext context) async {
try {
await authUseCase.logout();
Fluttertoast.showToast(
msg: "Logged out",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
backgroundColor: Colors.black,
textColor: Colors.white,
fontSize: 16.0,

// Display Snackbar for success message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Logged out"),
duration: Duration(seconds: 2),
backgroundColor: Colors.black,
),
);
isLoggedIn = false;
notifyListeners();
} catch (e) {
if (kDebugMode) {
print(e);
}
// Display Snackbar for error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Failed to log out. Please try again."),
duration: Duration(seconds: 2),
backgroundColor: Colors.red,
),
);
}
}


Future<void> openFeedback() async {
final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
String device;
Expand Down Expand Up @@ -158,16 +166,7 @@ class SettingsViewModel extends ChangeNotifier {
}

void rateApp() async {
try {
await LaunchReview.launch(
androidAppId: "com.banghuazhao.swiftcomp",
iOSAppId: "1297825946",
writeReview: true,
);
} catch (e) {
// Use fallback to open the app store directly if `LaunchReview` fails
openAppStore();
}
openAppStore();
}

Future<void> shareApp(BuildContext context) async {
Expand Down
33 changes: 23 additions & 10 deletions lib/presentation/settings/viewModels/user_profile_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:domain/usecases/user_usercase.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:domain/usecases/auth_usecase.dart';
import 'package:fluttertoast/fluttertoast.dart'; // Assuming your use cases are here
// Assuming your use cases are here

class UserProfileViewModel extends ChangeNotifier {
final AuthUseCase authUseCase;
Expand Down Expand Up @@ -48,27 +48,40 @@ class UserProfileViewModel extends ChangeNotifier {
}
}

Future<void> logoutUser() async {
Future<void> logoutUser(BuildContext context) async {
setLoading(true);
try {
await authUseCase.logout();
Fluttertoast.showToast(
msg: "Logged out",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
backgroundColor: Colors.black,
textColor: Colors.white,
fontSize: 16.0,

// Display a success Snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Logged out"),
duration: Duration(seconds: 2),
backgroundColor: Colors.black,
),
);

// Update state
isLoggedIn = false; // Explicitly set isLoggedIn to false
user = null; // Clear user data
notifyListeners();
} catch (e) {
// Log the error and display an error Snackbar
print("Logout failed: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Logout failed. Please try again."),
duration: Duration(seconds: 2),
backgroundColor: Colors.red,
),
);
} finally {
setLoading(false); // Ensure loading state is cleared
}
setLoading(false);
}


Future<void> deleteUser() async {
setLoading(true);
try {
Expand Down
Loading