signInWithGoogle method
Main YouTube authentication method following working implementation flow
Implementation
Future<bool> signInWithGoogle(String username, BuildContext context, [String? customClientId]) async {
try {
debugPrint('🚀 Starting YouTube native authentication for: $username');
// Check if we have a valid client ID (not the demo one)
if (customClientId == null || customClientId == '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com') {
debugPrint('⚠️ No custom Google client ID provided - YouTube integration unavailable');
_showSetupRequiredDialog(context);
return false;
}
// STEP 1: Initialize SDK with custom client ID
final GoogleSignIn googleSignIn = _initializeGoogleSignIn(customClientId);
// STEP 2: Check if already signed in (silent sign-in)
GoogleSignInAccount? account = await googleSignIn.signInSilently();
// STEP 3: If not signed in, prompt for sign-in
if (account == null) {
debugPrint('📱 Prompting user for Google Sign-In');
account = await googleSignIn.signIn();
}
if (account == null) {
debugPrint('❌ User cancelled Google Sign-In');
_showErrorSnackBar(context, 'Sign-in was cancelled');
return false;
}
debugPrint('✅ Google Sign-In successful: ${account.email}');
// STEP 4: Get authentication tokens
final GoogleSignInAuthentication auth = await account.authentication;
// STEP 5: CRITICAL - Check for server auth code (refresh token)
final String? serverAuthCode = account.serverAuthCode;
if (serverAuthCode == null) {
debugPrint('⚠️ No server auth code available - refresh may fail');
_showErrorSnackBar(context, 'Authentication incomplete. Please try again.');
return false;
}
debugPrint('🔑 Got tokens with refresh capability');
// STEP 6: Fetch YouTube channel info
String channelName = 'Unknown Channel';
String? channelId;
try {
final channelResponse = await http.get(
Uri.parse('https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true'),
headers: {
'Authorization': 'Bearer ${auth.accessToken}',
'Accept': 'application/json',
},
);
if (channelResponse.statusCode == 200) {
final channelData = json.decode(channelResponse.body);
if (channelData['items'] != null && channelData['items'].isNotEmpty) {
channelName = channelData['items'][0]['snippet']['title'];
channelId = channelData['items'][0]['id'];
debugPrint('📺 Found YouTube channel: $channelName');
}
}
} catch (e) {
debugPrint('⚠️ Could not fetch channel info: $e');
// Continue anyway - channel info is not critical
}
// STEP 7: Send to backend using native-auth endpoint (matching working implementation)
final success = await _sendNativeAuthToBackend(
username,
account,
auth,
serverAuthCode,
channelName,
channelId
);
if (success) {
_showSuccessSnackBar(context, 'Successfully connected to YouTube!');
return true;
} else {
_showErrorSnackBar(context, 'Failed to connect to YouTube. Please try again.');
return false;
}
} catch (e) {
debugPrint('❌ Error during YouTube authentication: $e');
// Handle specific Google Sign-In error codes
String errorMessage = 'YouTube connection error';
if (e.toString().contains('sign_in_canceled')) {
errorMessage = 'Sign-in was cancelled';
} else if (e.toString().contains('sign_in_failed')) {
errorMessage = 'Sign-in failed. Please try again.';
} else if (e.toString().contains('network_error')) {
errorMessage = 'Network error. Please check your internet connection.';
} else if (e.toString().contains('sign_in_required')) {
errorMessage = 'Please sign in to your Google account';
}
_showErrorSnackBar(context, errorMessage);
return false;
}
}