mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 17:07:40 +00:00
fix(android): localize accessibility executor UI
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package ai.openclaw.app.accessibility
|
||||
|
||||
import ai.openclaw.app.i18n.nativeString
|
||||
import ai.openclaw.app.ui.OpenClawTheme
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@@ -147,7 +148,11 @@ private fun AccessibilityDevScreen(
|
||||
snapshot = observed
|
||||
selectedRef = null
|
||||
textInput = ""
|
||||
lastResult = ActionResult(ActionOutcomeCode.Completed, "Observed ${observed.nodes.size} nodes")
|
||||
lastResult =
|
||||
ActionResult(
|
||||
ActionOutcomeCode.Completed,
|
||||
nativeString("Observed \$count nodes", observed.nodes.size),
|
||||
)
|
||||
refreshForegroundPackage()
|
||||
}
|
||||
|
||||
@@ -162,7 +167,7 @@ private fun AccessibilityDevScreen(
|
||||
cancelDelayedObserve()
|
||||
delayedObserveRunning = false
|
||||
immediateObserveRunning = true
|
||||
progressMessage = "Observing…"
|
||||
progressMessage = nativeString("Observing…")
|
||||
coroutineScope.launch {
|
||||
val result = runCatching { captureSnapshot() }
|
||||
immediateObserveRunning = false
|
||||
@@ -179,7 +184,11 @@ private fun AccessibilityDevScreen(
|
||||
delayedObserveRunning = true
|
||||
startDelayedObserve(
|
||||
{ remaining ->
|
||||
progressMessage = "Observing in ${remaining}s — switch to the target app"
|
||||
progressMessage =
|
||||
nativeString(
|
||||
"Observing in \${remaining}s — switch to the target app",
|
||||
remaining,
|
||||
)
|
||||
},
|
||||
{ result ->
|
||||
delayedObserveRunning = false
|
||||
@@ -222,6 +231,9 @@ private fun AccessibilityDevScreen(
|
||||
val observeRunning = immediateObserveRunning || delayedObserveRunning
|
||||
val targetPackageMatches = canRunNodeActions(snapshot?.packageName, foregroundPackageName)
|
||||
val nodeActionsEnabled = targetPackageMatches && !observeRunning
|
||||
val snapshotLabel = snapshot?.id ?: nativeString("none")
|
||||
val snapshotPackage = snapshot?.packageName ?: nativeString("none")
|
||||
val foregroundPackage = foregroundPackageName ?: nativeString("unknown")
|
||||
Surface(
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -234,19 +246,24 @@ private fun AccessibilityDevScreen(
|
||||
modifier = Modifier.fillMaxSize().padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text("Accessibility executor", style = MaterialTheme.typography.headlineSmall)
|
||||
Text(nativeString("Accessibility executor"), style = MaterialTheme.typography.headlineSmall)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = if (connected) "Service connected" else "Service disabled",
|
||||
text =
|
||||
if (connected) {
|
||||
nativeString("Service connected")
|
||||
} else {
|
||||
nativeString("Service disabled")
|
||||
},
|
||||
color = if (connected) Color(0xFF2E7D32) else MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
if (!connected) {
|
||||
OutlinedButton(onClick = openAccessibilitySettings) {
|
||||
Text("Open settings")
|
||||
Text(nativeString("Open settings"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,37 +273,44 @@ private fun AccessibilityDevScreen(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Button(onClick = ::startImmediateObservation, enabled = connected && !observeRunning) {
|
||||
Text("Observe")
|
||||
Text(nativeString("Observe"))
|
||||
}
|
||||
OutlinedButton(onClick = ::observeDelayed, enabled = connected && !observeRunning) {
|
||||
Text("Observe in 3s")
|
||||
Text(nativeString("Observe in 3s"))
|
||||
}
|
||||
GlobalActionButton("Back", connected && !observeRunning) {
|
||||
GlobalActionButton(nativeString("Back"), connected && !observeRunning) {
|
||||
actGlobal(GlobalActionName.Back)
|
||||
}
|
||||
GlobalActionButton("Home", connected && !observeRunning) {
|
||||
GlobalActionButton(nativeString("Home"), connected && !observeRunning) {
|
||||
actGlobal(GlobalActionName.Home)
|
||||
}
|
||||
GlobalActionButton("Recents", connected && !observeRunning) {
|
||||
GlobalActionButton(nativeString("Recents"), connected && !observeRunning) {
|
||||
actGlobal(GlobalActionName.Recents)
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Snapshot: ${snapshot?.id ?: "none"}",
|
||||
text = nativeString("Snapshot: \$snapshotLabel", snapshotLabel),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
Text(
|
||||
text = "Packages: snapshot=${snapshot?.packageName ?: "none"} foreground=${foregroundPackageName ?: "unknown"}",
|
||||
text =
|
||||
nativeString(
|
||||
"Packages: snapshot=\$snapshotPackage foreground=\$foregroundPackage",
|
||||
snapshotPackage,
|
||||
foregroundPackage,
|
||||
),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
Text(
|
||||
text =
|
||||
progressMessage ?: lastResult?.let { result ->
|
||||
// Action messages are protocol diagnostics; keep them verbatim so UI evidence
|
||||
// matches the mobile.ui result returned to the agent.
|
||||
listOfNotNull(result.code.value, result.message).joinToString(" — ")
|
||||
} ?: "No action result",
|
||||
} ?: nativeString("No action result"),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
@@ -346,11 +370,16 @@ private fun SelectedNodeControls(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text("Selected ${node.ref}", style = MaterialTheme.typography.titleSmall)
|
||||
Text(
|
||||
nativeString("Selected \$reference", node.ref),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
if (showTargetMismatchNote) {
|
||||
Text(
|
||||
"Node actions run only when the target app is foreground (validated via the remote path). " +
|
||||
"Global actions and same-app actions work here.",
|
||||
nativeString(
|
||||
"Node actions run only when the target app is foreground (validated via the remote path). " +
|
||||
"Global actions and same-app actions work here.",
|
||||
),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -361,7 +390,7 @@ private fun SelectedNodeControls(
|
||||
) {
|
||||
if ("activate" in node.actions) {
|
||||
Button(onClick = { act(MobileUiAction.Activate(node.ref)) }, enabled = actionsEnabled) {
|
||||
Text("Activate")
|
||||
Text(nativeString("Activate"))
|
||||
}
|
||||
}
|
||||
if ("scroll_forward" in node.actions) {
|
||||
@@ -369,7 +398,7 @@ private fun SelectedNodeControls(
|
||||
onClick = { act(MobileUiAction.Scroll(node.ref, ScrollDirection.Forward)) },
|
||||
enabled = actionsEnabled,
|
||||
) {
|
||||
Text("Scroll forward")
|
||||
Text(nativeString("Scroll forward"))
|
||||
}
|
||||
}
|
||||
if ("scroll_backward" in node.actions) {
|
||||
@@ -377,7 +406,7 @@ private fun SelectedNodeControls(
|
||||
onClick = { act(MobileUiAction.Scroll(node.ref, ScrollDirection.Backward)) },
|
||||
enabled = actionsEnabled,
|
||||
) {
|
||||
Text("Scroll back")
|
||||
Text(nativeString("Scroll back"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,7 +418,7 @@ private fun SelectedNodeControls(
|
||||
OutlinedTextField(
|
||||
value = textInput,
|
||||
onValueChange = onTextInputChange,
|
||||
label = { Text("Text") },
|
||||
label = { Text(nativeString("Text")) },
|
||||
singleLine = true,
|
||||
enabled = actionsEnabled,
|
||||
modifier = Modifier.weight(1f),
|
||||
@@ -398,7 +427,7 @@ private fun SelectedNodeControls(
|
||||
onClick = { act(MobileUiAction.SetText(node.ref, textInput)) },
|
||||
enabled = actionsEnabled,
|
||||
) {
|
||||
Text("Set text")
|
||||
Text(nativeString("Set text"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,6 +446,7 @@ private fun NodeRow(
|
||||
selected: Boolean,
|
||||
onSelect: () -> Unit,
|
||||
) {
|
||||
val selectionMarker = if (selected) "▶ " else ""
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().clickable(onClick = onSelect),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
@@ -426,19 +456,43 @@ private fun NodeRow(
|
||||
verticalArrangement = Arrangement.spacedBy(3.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "${if (selected) "▶ " else ""}${node.ref} ${node.role}",
|
||||
text =
|
||||
selectionMarker +
|
||||
nativeString(
|
||||
"\$reference \$role",
|
||||
node.ref,
|
||||
node.role,
|
||||
),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
node.text?.let { Text("text: $it", style = MaterialTheme.typography.bodySmall) }
|
||||
node.contentDescription?.let { Text("description: $it", style = MaterialTheme.typography.bodySmall) }
|
||||
node.text?.let {
|
||||
Text(
|
||||
nativeString("text: \$value", it),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
node.contentDescription?.let {
|
||||
Text(
|
||||
nativeString("description: \$value", it),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = "bounds: ${node.boundsInScreen.flattenToString()}",
|
||||
text =
|
||||
nativeString(
|
||||
"bounds: \$value",
|
||||
node.boundsInScreen.flattenToString(),
|
||||
),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
Text(
|
||||
text = "actions: ${node.actions.joinToString().ifEmpty { "none" }}",
|
||||
text =
|
||||
nativeString(
|
||||
"actions: \$value",
|
||||
node.actions.joinToString().ifEmpty { nativeString("none") },
|
||||
),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="accessibility_service_label" translatable="false">OpenClaw UI control</string>
|
||||
<string name="accessibility_service_summary" translatable="false">Developer UI observation and control</string>
|
||||
<string name="accessibility_service_description" translatable="false">Allows the third-party OpenClaw build to inspect and control the active app during local development.</string>
|
||||
<string name="accessibility_dev_activity_label" translatable="false">OpenClaw Accessibility Developer</string>
|
||||
<string name="accessibility_service_label">OpenClaw UI control</string>
|
||||
<string name="accessibility_service_summary">Developer UI observation and control</string>
|
||||
<string name="accessibility_service_description">Allows the third-party OpenClaw build to inspect and control the active app during local development.</string>
|
||||
<string name="accessibility_dev_activity_label">OpenClaw Accessibility Developer</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user