feat(login): Trae/WorkBuddy INTL 提供手机浏览器登录并自动回填;Trae CN 保留软件内登录
This commit is contained in:
parent
dab9b7b272
commit
525b91f370
@ -16,8 +16,8 @@ android {
|
|||||||
applicationId = "com.rainy.token"
|
applicationId = "com.rainy.token"
|
||||||
minSdk = 31
|
minSdk = 31
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 41
|
versionCode = 42
|
||||||
versionName = "1.7.21"
|
versionName = "1.7.22"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@ -319,6 +319,7 @@ fun ServiceDetailScreen(
|
|||||||
hasCredential = uiState.hasCredential,
|
hasCredential = uiState.hasCredential,
|
||||||
isManualMode = isManualMode,
|
isManualMode = isManualMode,
|
||||||
service = service,
|
service = service,
|
||||||
|
region = uiState.region,
|
||||||
triggerState = triggerState,
|
triggerState = triggerState,
|
||||||
models = models,
|
models = models,
|
||||||
selectedModel = selectedModel,
|
selectedModel = selectedModel,
|
||||||
@ -2105,6 +2106,7 @@ private fun ActionButtons(
|
|||||||
hasCredential: Boolean,
|
hasCredential: Boolean,
|
||||||
isManualMode: Boolean,
|
isManualMode: Boolean,
|
||||||
service: ServiceType,
|
service: ServiceType,
|
||||||
|
region: String?,
|
||||||
triggerState: TriggerState,
|
triggerState: TriggerState,
|
||||||
models: List<String>,
|
models: List<String>,
|
||||||
selectedModel: String?,
|
selectedModel: String?,
|
||||||
@ -2225,6 +2227,18 @@ private fun ActionButtons(
|
|||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trae/WorkBuddy 国际版:直接应用内登录(回调解析凭据)
|
||||||
|
if ((service == ServiceType.TRAE || service == ServiceType.WORKBUDDY) &&
|
||||||
|
region != null && region.equals("INTL", ignoreCase = true)
|
||||||
|
) {
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = onStartWebViewLogin,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.action_mobile_browser_login))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hasCredential && !isManualMode) {
|
if (hasCredential && !isManualMode) {
|
||||||
Button(
|
Button(
|
||||||
onClick = onRefresh,
|
onClick = onRefresh,
|
||||||
|
|||||||
@ -816,27 +816,37 @@ private fun TraeCredentialForm(
|
|||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.outline
|
color = MaterialTheme.colorScheme.outline
|
||||||
)
|
)
|
||||||
OutlinedButton(
|
if (region.uppercase() != "INTL") {
|
||||||
onClick = onStartInAppLogin,
|
OutlinedButton(
|
||||||
modifier = Modifier.fillMaxWidth()
|
onClick = onStartInAppLogin,
|
||||||
) {
|
modifier = Modifier.fillMaxWidth()
|
||||||
Text(stringResource(R.string.action_login_in_app))
|
) {
|
||||||
|
Text(stringResource(R.string.action_login_in_app))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
OutlinedTextField(
|
if (region.uppercase() == "INTL") {
|
||||||
value = callbackUrl,
|
OutlinedButton(
|
||||||
onValueChange = onCallbackUrlChange,
|
onClick = onStartInAppLogin,
|
||||||
label = { Text(stringResource(R.string.field_trae_callback_url)) },
|
modifier = Modifier.fillMaxWidth()
|
||||||
supportingText = { Text(stringResource(R.string.field_trae_callback_hint)) },
|
) {
|
||||||
minLines = 1,
|
Text(stringResource(R.string.action_mobile_browser_login))
|
||||||
maxLines = 3,
|
}
|
||||||
modifier = Modifier.fillMaxWidth()
|
OutlinedTextField(
|
||||||
)
|
value = callbackUrl,
|
||||||
OutlinedButton(
|
onValueChange = onCallbackUrlChange,
|
||||||
onClick = { onImportCallback(callbackUrl) },
|
label = { Text(stringResource(R.string.field_trae_callback_url)) },
|
||||||
enabled = callbackUrl.isNotBlank(),
|
supportingText = { Text(stringResource(R.string.field_trae_callback_hint)) },
|
||||||
modifier = Modifier.fillMaxWidth()
|
minLines = 1,
|
||||||
) {
|
maxLines = 3,
|
||||||
Text(stringResource(R.string.action_parse_callback))
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = { onImportCallback(callbackUrl) },
|
||||||
|
enabled = callbackUrl.isNotBlank(),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.action_parse_callback))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = jwt,
|
value = jwt,
|
||||||
@ -976,11 +986,13 @@ private fun WorkBuddyCredentialForm(
|
|||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.outline
|
color = MaterialTheme.colorScheme.outline
|
||||||
)
|
)
|
||||||
OutlinedButton(
|
if (region.uppercase() == "INTL") {
|
||||||
onClick = onStartInAppLogin,
|
OutlinedButton(
|
||||||
modifier = Modifier.fillMaxWidth()
|
onClick = onStartInAppLogin,
|
||||||
) {
|
modifier = Modifier.fillMaxWidth()
|
||||||
Text(stringResource(R.string.action_login_in_app))
|
) {
|
||||||
|
Text(stringResource(R.string.action_mobile_browser_login))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.field_trae_region),
|
text = stringResource(R.string.field_trae_region),
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.key
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@ -77,6 +78,18 @@ fun WebViewLoginScreen(
|
|||||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val context = LocalContext.current
|
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 webViewGeneration by remember { mutableStateOf(0) }
|
||||||
var pageLoading by remember { mutableStateOf(true) }
|
var pageLoading by remember { mutableStateOf(true) }
|
||||||
var pageError by remember { mutableStateOf<String?>(null) }
|
var pageError by remember { mutableStateOf<String?>(null) }
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<string name="action_clear">清除</string>
|
<string name="action_clear">清除</string>
|
||||||
<string name="action_save">保存</string>
|
<string name="action_save">保存</string>
|
||||||
<string name="action_login_in_app">软件内登录</string>
|
<string name="action_login_in_app">软件内登录</string>
|
||||||
|
<string name="action_mobile_browser_login">手机浏览器登录</string>
|
||||||
<string name="action_jump">跳转</string>
|
<string name="action_jump">跳转</string>
|
||||||
<string name="action_prev_page">◀ 上一页</string>
|
<string name="action_prev_page">◀ 上一页</string>
|
||||||
<string name="action_next_page">下一页 ▶</string>
|
<string name="action_next_page">下一页 ▶</string>
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<string name="action_clear">清除</string>
|
<string name="action_clear">清除</string>
|
||||||
<string name="action_save">儲存</string>
|
<string name="action_save">儲存</string>
|
||||||
<string name="action_login_in_app">軟體內登入</string>
|
<string name="action_login_in_app">軟體內登入</string>
|
||||||
|
<string name="action_mobile_browser_login">手機瀏覽器登入</string>
|
||||||
<string name="action_jump">跳轉</string>
|
<string name="action_jump">跳轉</string>
|
||||||
<string name="action_prev_page">◀ 上一頁</string>
|
<string name="action_prev_page">◀ 上一頁</string>
|
||||||
<string name="action_next_page">下一頁 ▶</string>
|
<string name="action_next_page">下一頁 ▶</string>
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
<string name="action_clear">Clear</string>
|
<string name="action_clear">Clear</string>
|
||||||
<string name="action_save">Save</string>
|
<string name="action_save">Save</string>
|
||||||
<string name="action_login_in_app">Sign in within app</string>
|
<string name="action_login_in_app">Sign in within app</string>
|
||||||
|
<string name="action_mobile_browser_login">Sign in via mobile browser</string>
|
||||||
<string name="action_jump">Go</string>
|
<string name="action_jump">Go</string>
|
||||||
<string name="action_prev_page">◀ Prev</string>
|
<string name="action_prev_page">◀ Prev</string>
|
||||||
<string name="action_next_page">Next ▶</string>
|
<string name="action_next_page">Next ▶</string>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user