diff --git a/app/src/main/java/com/rainy/token/ui/settings/CredentialEditScreen.kt b/app/src/main/java/com/rainy/token/ui/settings/CredentialEditScreen.kt index eb5ffba..e2a3b9a 100644 --- a/app/src/main/java/com/rainy/token/ui/settings/CredentialEditScreen.kt +++ b/app/src/main/java/com/rainy/token/ui/settings/CredentialEditScreen.kt @@ -993,6 +993,13 @@ private fun WorkBuddyCredentialForm( ) { Text(stringResource(R.string.action_mobile_browser_login)) } + } else { + OutlinedButton( + onClick = onStartInAppLogin, + modifier = Modifier.fillMaxWidth() + ) { + Text(stringResource(R.string.action_login_in_app)) + } } Text( text = stringResource(R.string.field_trae_region), diff --git a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginScreen.kt b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginScreen.kt index cf039a6..19102cc 100644 --- a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginScreen.kt +++ b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginScreen.kt @@ -37,7 +37,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.key import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.platform.LocalContext @@ -78,18 +77,6 @@ fun WebViewLoginScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val snackbarHostState = remember { SnackbarHostState() } val context = LocalContext.current - // Trae/WorkBuddy 国际版:进入即用手机浏览器登录,回调/轮询结果自动回填到应用 - val browserLoginService = service == ServiceType.TRAE || service == ServiceType.WORKBUDDY - val browserLoginRegion = region != null && region.equals("INTL", ignoreCase = true) - var autoBrowserStarted by rememberSaveable { mutableStateOf(false) } - LaunchedEffect(uiState.loginUrl, uiState.externalBrowserWaiting, uiState.loginSucceeded, autoBrowserStarted) { - if (browserLoginService && browserLoginRegion && !autoBrowserStarted && - uiState.loginUrl.isNotBlank() && !uiState.externalBrowserWaiting && !uiState.loginSucceeded - ) { - autoBrowserStarted = true - viewModel.openExternalBrowser() - } - } var webViewGeneration by remember { mutableStateOf(0) } var pageLoading by remember { mutableStateOf(true) } var pageError by remember { mutableStateOf(null) } diff --git a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt index 9010707..6656e7b 100644 --- a/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt +++ b/app/src/main/java/com/rainy/token/ui/webview/WebViewLoginViewModel.kt @@ -152,6 +152,10 @@ class WebViewLoginViewModel @Inject constructor( val deviceId = traeDeviceId() val callbackUrl = buildTraeAuthUrl(LOGIN_WEBVIEW_CALLBACK_PORT) _uiState.update { it.copy(loginUrl = callbackUrl) } + if (region == "INTL") { + // 国际版登录页在系统浏览器完成,回调由本地服务器自动接收并回填 + openExternalBrowser() + } return } @@ -369,6 +373,8 @@ class WebViewLoginViewModel @Inject constructor( .addHeader("X-Client-ID", "codebuddy-cli") .addHeader("X-Client-Version", "2.143.1") .addHeader("X-Product", "SaaS") + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("Content-Type", "application/json") .post("{}".toRequestBody("application/json".toMediaTypeOrNull())) .build() @@ -397,6 +403,10 @@ class WebViewLoginViewModel @Inject constructor( } _uiState.update { it.copy(loginUrl = authURL) } workBuddyPollingJob = viewModelScope.launch { pollWorkBuddyToken(state) } + if (region == "INTL") { + // 国际版登录页在系统浏览器完成,凭据由轮询自动回填 + openExternalBrowser() + } } catch (_: Exception) { _uiState.update { it.copy(error = UiText.Resource(R.string.error_network_generic)) @@ -421,6 +431,8 @@ class WebViewLoginViewModel @Inject constructor( .addHeader("X-Client-Version", "2.143.1") .addHeader("X-Product", "SaaS") .addHeader("X-No-Authorization", "1") + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("X-Requested-With", "XMLHttpRequest") .get() .build() val body = withContext(Dispatchers.IO) {