diff --git a/app/src/main/java/app/gamenative/service/SteamAuthenticator.kt b/app/src/main/java/app/gamenative/service/SteamAuthenticator.kt new file mode 100644 index 0000000000..2adc566ddb --- /dev/null +++ b/app/src/main/java/app/gamenative/service/SteamAuthenticator.kt @@ -0,0 +1,86 @@ +package app.gamenative.service + +import app.gamenative.enums.LoginResult +import app.gamenative.enums.LoginScreen +import app.gamenative.ui.data.UserLoginState +import `in`.dragonbra.javasteam.steam.authentication.IAuthenticator +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import timber.log.Timber +import kotlinx.coroutines.channels.Channel +import java.util.concurrent.CompletableFuture + +class SteamAuthenticator(var loginState : MutableStateFlow, + var submitChannel : Channel, + var viewModelScope : CoroutineScope) : IAuthenticator { + + var useGuardTotp: Boolean = false + + override fun acceptDeviceConfirmation(): CompletableFuture { + Timber.tag("UserLoginViewModel").i("Two-Factor, device confirmation") + + if (useGuardTotp) { + useGuardTotp = false + return CompletableFuture.completedFuture(false) + } + + loginState.update { currentState -> + currentState.copy( + loginResult = LoginResult.DeviceConfirm, + loginScreen = LoginScreen.TWO_FACTOR, + isLoggingIn = false, + lastTwoFactorMethod = "steam_guard", + ) + } + + return CompletableFuture.completedFuture(true) + } + + override fun getDeviceCode(previousCodeWasIncorrect: Boolean): CompletableFuture { + Timber.tag("UserLoginViewModel").d("Two-Factor, device code") + + loginState.update { currentState -> + currentState.copy( + loginResult = LoginResult.DeviceAuth, + loginScreen = LoginScreen.TWO_FACTOR, + isLoggingIn = false, + previousCodeIncorrect = previousCodeWasIncorrect, + lastTwoFactorMethod = "authenticator_code", + ) + } + + return CompletableFuture().apply { + viewModelScope.launch { + val code = submitChannel.receive() + complete(code) + } + } + } + + override fun getEmailCode( + email: String?, + previousCodeWasIncorrect: Boolean, + ): CompletableFuture { + Timber.tag("UserLoginViewModel").d("Two-Factor, asking for email code") + + loginState.update { currentState -> + currentState.copy( + loginResult = LoginResult.EmailAuth, + loginScreen = LoginScreen.TWO_FACTOR, + isLoggingIn = false, + email = email, + previousCodeIncorrect = previousCodeWasIncorrect, + lastTwoFactorMethod = "email_code", + ) + } + + return CompletableFuture().apply { + viewModelScope.launch { + val code = submitChannel.receive() + complete(code) + } + } + } +} diff --git a/app/src/main/java/app/gamenative/ui/model/UserLoginViewModel.kt b/app/src/main/java/app/gamenative/ui/model/UserLoginViewModel.kt index 451ef1e891..96bf4d8795 100644 --- a/app/src/main/java/app/gamenative/ui/model/UserLoginViewModel.kt +++ b/app/src/main/java/app/gamenative/ui/model/UserLoginViewModel.kt @@ -8,12 +8,11 @@ import app.gamenative.enums.LoginResult import app.gamenative.enums.LoginScreen import app.gamenative.events.AndroidEvent import app.gamenative.events.SteamEvent +import app.gamenative.service.SteamAuthenticator import app.gamenative.service.SteamService import app.gamenative.ui.data.UserLoginState import app.gamenative.PrefManager import com.posthog.PostHog -import `in`.dragonbra.javasteam.steam.authentication.IAuthenticator -import java.util.concurrent.CompletableFuture import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -32,68 +31,7 @@ class UserLoginViewModel : ViewModel() { private val submitChannel = Channel() - private val authenticator = object : IAuthenticator { - override fun acceptDeviceConfirmation(): CompletableFuture { - Timber.tag("UserLoginViewModel").i("Two-Factor, device confirmation") - - _loginState.update { currentState -> - currentState.copy( - loginResult = LoginResult.DeviceConfirm, - loginScreen = LoginScreen.TWO_FACTOR, - isLoggingIn = false, - lastTwoFactorMethod = "steam_guard", - ) - } - - return CompletableFuture.completedFuture(true) - } - - override fun getDeviceCode(previousCodeWasIncorrect: Boolean): CompletableFuture { - Timber.tag("UserLoginViewModel").d("Two-Factor, device code") - - _loginState.update { currentState -> - currentState.copy( - loginResult = LoginResult.DeviceAuth, - loginScreen = LoginScreen.TWO_FACTOR, - isLoggingIn = false, - previousCodeIncorrect = previousCodeWasIncorrect, - lastTwoFactorMethod = "authenticator_code", - ) - } - - return CompletableFuture().apply { - viewModelScope.launch { - val code = submitChannel.receive() - complete(code) - } - } - } - - override fun getEmailCode( - email: String?, - previousCodeWasIncorrect: Boolean, - ): CompletableFuture { - Timber.tag("UserLoginViewModel").d("Two-Factor, asking for email code") - - _loginState.update { currentState -> - currentState.copy( - loginResult = LoginResult.EmailAuth, - loginScreen = LoginScreen.TWO_FACTOR, - isLoggingIn = false, - email = email, - previousCodeIncorrect = previousCodeWasIncorrect, - lastTwoFactorMethod = "email_code", - ) - } - - return CompletableFuture().apply { - viewModelScope.launch { - val code = submitChannel.receive() - complete(code) - } - } - } - } + private val authenticator = SteamAuthenticator(_loginState, submitChannel, viewModelScope) private val onSteamConnected: (SteamEvent.Connected) -> Unit = { Timber.i("Received is connected") @@ -321,6 +259,21 @@ class UserLoginViewModel : ViewModel() { } } + fun useGuardTotp() { + authenticator.useGuardTotp = true + + with(_loginState.value) { + viewModelScope.launch { + SteamService.startLoginWithCredentials( + username = username, + password = password, + rememberSession = rememberSession, + authenticator = authenticator, + ) + } + } + } + fun retryConnection(context: Context) { // Reset error/login state if needed _loginState.update { currentState -> diff --git a/app/src/main/java/app/gamenative/ui/screen/login/TwoFactorAuthScreen.kt b/app/src/main/java/app/gamenative/ui/screen/login/TwoFactorAuthScreen.kt index 05b8a650e1..00161b6733 100644 --- a/app/src/main/java/app/gamenative/ui/screen/login/TwoFactorAuthScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/login/TwoFactorAuthScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.material3.OutlinedTextFieldDefaults import app.gamenative.ui.component.NoExtractOutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -49,6 +50,7 @@ fun TwoFactorAuthScreenContent( userLoginState: UserLoginState, message: String, onSetTwoFactor: (String) -> Unit, + onUseGuardTotp: () -> Unit, onLogin: () -> Unit, ) { Column( @@ -69,6 +71,12 @@ fun TwoFactorAuthScreenContent( if (userLoginState.loginResult == LoginResult.DeviceConfirm) { LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.height(16.dp)) + TextButton( + onClick = onUseGuardTotp + ) { + Text(stringResource(R.string.steam_2fa_use_guard_totp)) + } } else if (userLoginState.loginResult == LoginResult.EmailAuth || userLoginState.loginResult == LoginResult.DeviceAuth ) { @@ -188,6 +196,9 @@ private fun Preview_TwoFactorAuthScreen( onSetTwoFactor = { value -> currentState = currentState.copy(twoFactorCode = value) }, + onUseGuardTotp = { + currentState = currentState.copy(twoFactorCode = "") + }, onLogin = { currentState = currentState.copy(twoFactorCode = "") }, diff --git a/app/src/main/java/app/gamenative/ui/screen/login/UserLoginScreen.kt b/app/src/main/java/app/gamenative/ui/screen/login/UserLoginScreen.kt index 113c9a50df..ca0f7b77e6 100644 --- a/app/src/main/java/app/gamenative/ui/screen/login/UserLoginScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/login/UserLoginScreen.kt @@ -294,6 +294,7 @@ fun UserLoginScreen( onTwoFactorLogin = viewModel::submit, onQrRetry = viewModel::onQrRetry, onSetTwoFactor = viewModel::setTwoFactorCode, + onUseGuardTotp = viewModel::useGuardTotp, onRetryConnection = onRetryConnection, onContinueOffline = onContinueOffline, onLaunchGog = { gogOAuthLauncher.launch(Intent(context, GOGOAuthActivity::class.java)) }, @@ -316,6 +317,7 @@ private fun UserLoginScreenContent( onTwoFactorLogin: () -> Unit, onQrRetry: () -> Unit, onSetTwoFactor: (String) -> Unit, + onUseGuardTotp: () -> Unit, onRetryConnection: () -> Unit, onContinueOffline: () -> Unit, onLaunchGog: () -> Unit, @@ -448,6 +450,7 @@ private fun UserLoginScreenContent( else -> "" }, onSetTwoFactor = onSetTwoFactor, + onUseGuardTotp = onUseGuardTotp, onLogin = onTwoFactorLogin, ) } else { @@ -977,6 +980,7 @@ private fun Preview_UserLoginScreen( onTwoFactorLogin = { }, onQrRetry = { }, onSetTwoFactor = { }, + onUseGuardTotp = { }, onShowLoginScreen = { }, onRetryConnection = { }, onContinueOffline = { }, @@ -1013,6 +1017,7 @@ private fun Preview_UserLoginScreen_Landscape( onTwoFactorLogin = { }, onQrRetry = { }, onSetTwoFactor = { }, + onUseGuardTotp = { }, onShowLoginScreen = { }, onRetryConnection = { }, onContinueOffline = { }, diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 5fa1f8789d..de7a24b98c 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -1106,6 +1106,7 @@ + Eller brug 2-faktor-godkendelseskoden Appen der installeres har følgende pladskrav. Vil du fortsætte?\n\n\tDownload-størrelse: %1$s\n\tStørrelse på disk: %2$s\n\tTilgængelig plads: %3$s Download-størrelse: %1$s\nStørrelse på disk: %2$s\nTilgængelig plads: %3$s Appen der installeres har brug for %1$s plads, men der er kun %2$s tilbage på denne enhed diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f5018f3155..8d4383514b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -12,6 +12,7 @@ Bitte bestätige die Anmeldung in der Steam Mobile App… Bitte gib deinen Zwei-Faktor-Code aus deiner Authenticator-App ein. Bitte gib den Authentifizierungscode ein, der an die E-Mail-Adresse %s gesendet wurde + Oder verwende den Code für die Zwei-Faktor-Authentifizierung Die App benötigt folgenden Speicherplatz. Möchtest du fortfahren?\n\n\tDownloadgröße: %1$s\n\tBelegter Speicher: %2$s\n\tVerfügbarer Speicher: %3$s Diese App benötigt %1$s Speicherplatz, aber auf diesem Gerät sind nur noch %2$s frei Bist du sicher, dass du den Download der App abbrechen möchtest? diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2c4b6ad354..a5ebc8fe79 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -12,6 +12,7 @@ Usa la aplicación móvil de Steam para confirmar tu inicio de sesión… Introduce el código de autenticación de dos factores desde tu aplicación de autenticación. Introduce el código de autenticación enviado al correo %s. + O utiliza el código de autenticación de dos factores La aplicación a instalar requiere el siguiente espacio. ¿Deseas continuar?\n\n\tTamaño de descarga: %1$s\n\tTamaño en disco: %2$s\n\tEspacio disponible: %3$s Tamaño de descarga: %1$s\nTamaño en disco: %2$s\nEspacio disponible: %3$s La aplicación a instalar requiere %1$s de espacio, pero solo quedan %2$s en este dispositivo. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1ca0954bf9..4e9be53a7e 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -12,6 +12,7 @@ Utilisez l\'application mobile Steam pour confirmer votre connexion… Veuillez entrer votre code d\'authentification à deux facteurs depuis votre application d\'authentification. Veuillez entrer le code d\'authentification envoyé à l\'adresse %s + Ou utilisez le code d\'authentification à deux facteurs L\'application en cours d\'installation nécessite l\'espace suivant. Voulez-vous continuer ?\n\n\tTaille du téléchargement : %1$s\n\tTaille sur le disque : %2$s\n\tEspace disponible : %3$s Taille du téléchargement : %1$s\nTaille sur le disque : %2$s\nEspace disponible : %3$s L\'application en cours d\'installation nécessite %1$s d\'espace mais il ne reste que %2$s sur cet appareil diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index cebe4470ae..f0804d00af 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -12,6 +12,7 @@ Usa l\'app mobile di Steam per confermare l\'accesso… Inserisci il codice di autenticazione a due fattori dalla tua app di autenticazione. Inserisci il codice di autenticazione inviato all\'email %s + Oppure usa il codice di autenticazione a due fattori L\'app che stai installando ha i seguenti requisiti di spazio. Vuoi procedere?\n\n\tDimensione Download: %1$s\n\tDimensione su Disco: %2$s\n\tSpazio Disponibile: %3$s Dimensione Download: %1$s\nSpazio su Disco: %2$s\nSpazio Disponibile: %3$s L\'app che stai installando richiede %1$s di spazio ma sono rimasti solo %2$s su questo dispositivo diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 35fc025f5f..3c6a275ab5 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -12,6 +12,7 @@ Steam 모바일 앱을 사용하여 로그인을 확인하세요… 인증 앱에서 2단계 인증 코드를 입력하세요. %s 이메일로 전송된 인증 코드를 입력하세요 + 또는 2단계 인증 코드를 사용하세요 설치할 앱의 공간 요구사항은 다음과 같습니다. 계속하시겠습니까?\n\n\t다운로드 크기: %1$s\n\t디스크 사용량: %2$s\n\t사용 가능한 공간: %3$s 다운로드 크기: %1$s\n디스크 사용량: %2$s\n사용 가능한 공간: %3$s 설치할 앱에 %1$s의 공간이 필요하지만 이 기기에는 %2$s만 남아있습니다 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 13a6da0015..f77a1a5bc5 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -12,6 +12,7 @@ Użyj aplikacji mobilnej Steam, aby potwierdzić logowanie… Podaj kod uwierzytelniania dwuskładnikowego z aplikacji uwierzytelniającej. Podaj kod uwierzytelniający wysłany na e-mail %s + Lub użyj kodu do uwierzytelniania dwuskładnikowego Instalowana aplikacja ma następujące wymagania dotyczące miejsca. Czy chcesz kontynuować?\n\n\tRozmiar pobierania: %1$s\n\tRozmiar na dysku: %2$s\n\tDostępne miejsce: %3$s Rozmiar pobierania: %1$s\nRozmiar na dysku: %2$s\nDostępne miejsce: %3$s Instalowana aplikacja wymaga %1$s miejsca, ale na tym urządzeniu pozostało tylko %2$s @@ -866,7 +867,7 @@ Menedżer sterowników Wybierz sterownik Importuj ZIP z urządzenia - + Menedżer zawartości Importuj .wcp z urządzenia diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9b35d0b033..a16c7f19c6 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1106,6 +1106,7 @@ + Ou use o código de autenticação de dois fatores O aplicativo sendo instalado tem os seguintes requisitos de espaço. Deseja continuar?\n\n\tTamanho do download: %1$s\n\tTamanho no disco: %2$s\n\tEspaço disponível: %3$s Tamanho do download: %1$s\nTamanho no disco: %2$s\nEspaço disponível: %3$s O aplicativo sendo instalado precisa de %1$s de espaço, mas há apenas %2$s restante neste dispositivo diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 0a94462744..530d7ff88e 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -12,6 +12,7 @@ Folosește aplicația Steam Mobile pentru a confirma autentificarea… Introdu codul de autentificare din aplicația ta de autentificare. Introdu codul trimis la adresa de email %s + Sau folosește codul de autentificare în doi pași Aplicația ce urmează să fie instalată are următoarele cerințe de spațiu. Vrei să continui?\n\n\tDimensiune descărcare: %1$s\n\tSpațiu pe disc: %2$s\n\tSpațiu disponibil: %3$s Dimensiune descărcare: %1$s\nSpațiu pe disc: %2$s\nSpațiu disponibil: %3$s Aplicația necesită %1$s spațiu, dar pe dispozitiv sunt disponibile doar %2$s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 264169b1a9..c4ca00e5ca 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -675,9 +675,9 @@ Ubuntu RootFs - releases.ubuntu.com/focal Переключить выпадающее меню Закрыть Лупа - Вы уже вошли на другом устройстве и играете в %s. + Вы уже вошли на другом устройстве и играете в %s. Вы всё ещё можете играть в эту игру, но это отключит другой сеанс от Steam. - Вы уже вошли на другом устройстве (%1$s) и играете в %2$s (%3$s), и это сохранение ещё не в облаке. + Вы уже вошли на другом устройстве (%1$s) и играете в %2$s (%3$s), и это сохранение ещё не в облаке. Вы всё ещё можете играть в эту игру, но это отключит другой сеанс от Steam и может создать конфликт сохранений, когда прогресс того сеанса синхронизируется Приложение запущено Сеанс приложения приостановлен. Пожалуйста, перезапустите приложение. @@ -1110,6 +1110,7 @@ https://gamenative.app Размер загрузки: %1$s Размер на диске: %2$s Доступное место: %3$s + Или введите код двухфакторной аутентификации Устанавливаемое приложение имеет следующие требования к пространству. Вы хотите продолжить? Размер загрузки: %1$s diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index a98b0949e5..1b2936ad81 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -12,6 +12,7 @@ Підтвердіть вхід, за допомогою мобільного застосунку Steam… Введіть код двофакторної автентифікації. Введіть код, відправлений на пошту: %s + Або скористайтеся кодом двофакторної аутентифікації Застосунок, що інсталюється, має такі вимоги до обсягу пам\'яті. Продовжити?\n\n\tРозмір завантаження: %1$s\n\tРозмір на диску: %2$s\n\tДоступне місце: %3$s Розмір завантаження: %1$s\nРозмір на диску: %2$s\nДоступне місце: %3$s Для інсталяції застосунка потрібно %1$s вільного місця, але на цьому пристрої доступно лише %2$s diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index da9d984a8d..d3de2881eb 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -12,6 +12,7 @@ 正在通过Steam移动应用确认登录… 请输入您验证器应用中的双重验证码 请输入发送至邮箱 %s 的验证码 + 或使用双因素认证码 要安装的应用有以下空间要求:\n\n\t下载大小:%1$s\n\t磁盘占用空间:%2$s\n\t可用空间:%3$s 下载大小:%1$s\n\t磁盘占用空间:%2$s\n\t可用空间:%3$s 要安装的应用需要 %1$s 空间,但设备仅剩 %2$s 可用空间 @@ -1541,4 +1542,4 @@ 提示:如果你使用的是 Mali GPU,请使用系统驱动。 提示:出现黑屏?尝试使用菜单中的\"%s\"选项检查驱动是否正常工作。 启用在线游玩并提升兼容性\n不一定总能正常工作\n尝试前请先备份存档 - \ No newline at end of file + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 1c37c18520..3c2be590e2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -12,6 +12,7 @@ 使用Steam行動應用程式確認登入… 請輸入您的驗證器應用程式中的雙重驗證碼 請輸入發送至郵件信箱 %s 的驗證碼 + 或使用雙因素驗證碼 正在安裝的應用程式有以下空間需求:\n\n\t下載大小: %1$s\n\t磁碟佔用空間: %2$s\n\t可用空間: %3$s 下載大小: %1$s\n磁碟佔用空間: %2$s\n可用空間: %3$s 正在安裝的應用程式需要 %1$s 的空間, 但此設備上只剩下 %2$s 的空間 @@ -1533,4 +1534,4 @@ 提示:如果你使用的是 Mali GPU,請使用系統驅動。 提示:出現黑畫面?嘗試使用選單中的「%s」選項檢查驅動是否正常運作。 啟用線上遊玩並提升相容性\n不一定總能正常運作\n嘗試前請先備份存檔 - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 69074d0826..1db791289e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ Use the Steam Mobile App to confirm your sign in… Please enter your 2-factor auth code from your authenticator app. Please enter the auth code sent to the email at %s + Or use 2-factor auth code The app being installed has the following space requirements. Would you like to proceed?\n\n\tDownload Size: %1$s\n\tSize on Disk: %2$s\n\tAvailable Space: %3$s Download Size: %1$s\nSize on Disk: %2$s\nAvailable Space: %3$s The app being installed needs %1$s of space but there is only %2$s left on this device