execute method
Authenticate device and get tokens
Flow:
- Get device feedback code
- If device not found: a. Report feedback in native (Android only) b. Retry API call c. If still fails, retry 10 times with 10 second intervals d. If all attempts fail, show device not enrolled screen
- Login with code to get tokens
Implementation
Future<AuthTokens> execute(DeviceInfo deviceInfo, {required String app}) async {
DebugLogger.log('[AuthenticateUseCase] === execute() called ===');
DebugLogger.log('[AuthenticateUseCase] Device ID: ${deviceInfo.deviceId}');
DebugLogger.log('[AuthenticateUseCase] Platform Type: ${deviceInfo.platformType}');
String platformType;
switch (deviceInfo.platformType) {
case PlatformType.android:
platformType = 'android';
break;
case PlatformType.ios:
platformType = 'ios';
break;
case PlatformType.macOS:
platformType = 'macos';
break;
case PlatformType.windows:
platformType = 'windows';
break;
case PlatformType.linux:
platformType = 'linux';
break;
}
// First attempt to get device feedback
var feedbackResponse = await repository.getDeviceFeedback(
deviceInfo.deviceId,
platformType: platformType,
app: app,
);
// If device not found, report feedback and retry (Android only)
if (feedbackResponse.isDeviceNotFound) {
DebugLogger.log('[AuthenticateUseCase] ❌ Device not found');
// Report feedback in native Android (iOS doesn't have this)
if (deviceInfo.platformType == PlatformType.android) {
DebugLogger.log('[AuthenticateUseCase] Reporting feedback in native Android');
try {
final reported = await HaloAuthPlatform.instance.reportFeedback(
deviceInfo.deviceId,
);
DebugLogger.log('[AuthenticateUseCase] Feedback reported: $reported');
} catch (e) {
DebugLogger.log('[AuthenticateUseCase] ⚠️ Failed to report feedback: $e');
}
}
// Retry API call after reporting feedback
DebugLogger.log('[AuthenticateUseCase] Retrying device feedback after reporting');
feedbackResponse = await repository.getDeviceFeedback(
deviceInfo.deviceId,
platformType: platformType,
app: app,
);
// If still not found, retry 10 times with 10 second intervals
if (feedbackResponse.isDeviceNotFound) {
DebugLogger.log(
'[AuthenticateUseCase] ❌ Device still not found - starting retry loop (10 attempts, 10 sec intervals)',
);
bool success = false;
for (int attempt = 1; attempt <= 10; attempt++) {
DebugLogger.log('[AuthenticateUseCase] Retry attempt $attempt/10');
// Wait 10 seconds before retry (except for first retry which already happened)
if (attempt > 1) {
DebugLogger.log(
'[AuthenticateUseCase] Waiting 10 seconds before next attempt...',
);
await Future.delayed(const Duration(seconds: 10));
}
feedbackResponse = await repository.getDeviceFeedback(
deviceInfo.deviceId,
platformType: platformType,
app: app,
);
if (feedbackResponse.isSuccess && feedbackResponse.data != null) {
DebugLogger.log(
'[AuthenticateUseCase] ✅ Device feedback received on attempt $attempt',
);
success = true;
break;
}
DebugLogger.log(
'[AuthenticateUseCase] Attempt $attempt failed: ${feedbackResponse.error}',
);
}
// If all attempts failed, show device not enrolled screen
if (!success) {
DebugLogger.log(
'[AuthenticateUseCase] ❌ All retry attempts failed - showing device not enrolled screen',
);
await _navigateToDeviceNotEnrolled(deviceInfo.deviceId);
// Throw exception after showing screen
throw Exception('Device not found after all retry attempts');
}
}
}
// Check if we have a valid code
if (!feedbackResponse.isSuccess || feedbackResponse.data == null) {
DebugLogger.log('[AuthenticateUseCase] ❌ Failed to get device feedback code');
throw Exception(
'Failed to get device feedback code: ${feedbackResponse.error ?? "Unknown error"}',
);
}
// Login with the code
DebugLogger.log(
'[AuthenticateUseCase] ✅ Device feedback code received, logging in...',
);
final tokens = await repository.loginWithCode(
feedbackResponse.data!,
deviceId: deviceInfo.deviceId,
);
DebugLogger.log('[AuthenticateUseCase] ✅ Authentication successful');
DebugLogger.log('[AuthenticateUseCase] Device ID: ${tokens.deviceId}');
return tokens;
}