feat(ssh): integrate SSH terminal into settings navigation
- Add SshTerminal to SettingsRoute enum - Add SSH entry in settings list (ShellScreen -> SettingsShellScreen) - Create SshTerminalSettingsScreen hosting the SSH terminal UI - Copy SSH source files to app/src/main/java source root - Wire up SettingsDetailScreen dispatch for SshTerminal route
This commit is contained in:
@@ -24,6 +24,9 @@ import ai.openclaw.app.ui.design.ClawStatusPill
|
||||
import ai.openclaw.app.ui.design.ClawTextBadge
|
||||
import ai.openclaw.app.ui.design.ClawTextField
|
||||
import ai.openclaw.app.ui.design.ClawTheme
|
||||
import ai.openclaw.app.ui.tergent.SshTerminalManager
|
||||
import ai.openclaw.app.ui.tergent.SshConnectDialog
|
||||
import ai.openclaw.app.ui.tergent.SshTerminalScreen
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -45,6 +48,7 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
@@ -54,6 +58,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.automirrored.filled.ScreenShare
|
||||
@@ -77,12 +82,13 @@ import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -111,6 +117,7 @@ internal enum class SettingsRoute {
|
||||
Appearance,
|
||||
Health,
|
||||
About,
|
||||
SshTerminal,
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -138,6 +145,7 @@ internal fun SettingsDetailScreen(
|
||||
SettingsRoute.Appearance -> AppearanceSettingsScreen(onBack = onBack)
|
||||
SettingsRoute.Health -> HealthLogsSettingsScreen(viewModel = viewModel, onBack = onBack)
|
||||
SettingsRoute.About -> AboutSettingsScreen(viewModel = viewModel, onBack = onBack)
|
||||
SettingsRoute.SshTerminal -> SshTerminalSettingsScreen(viewModel = viewModel, onBack = onBack)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1144,3 +1152,58 @@ private fun openNotificationListenerSettings(context: Context) {
|
||||
val intent = Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SshTerminalSettingsScreen(
|
||||
viewModel: MainViewModel,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val manager = remember { SshTerminalManager() }
|
||||
var showConnectDialog by remember { mutableStateOf(false) }
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
manager.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
if (showConnectDialog) {
|
||||
ai.openclaw.app.ui.tergent.SshConnectDialog(
|
||||
onDismiss = { showConnectDialog = false },
|
||||
onConnect = { config ->
|
||||
showConnectDialog = false
|
||||
manager.connect(config)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
ai.openclaw.app.ui.tergent.SshTerminalScreen(
|
||||
manager = manager,
|
||||
onDisconnect = {
|
||||
manager.disconnect()
|
||||
onBack()
|
||||
},
|
||||
onShowConnectDialog = { showConnectDialog = true },
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
|
||||
// Back button overlay
|
||||
IconButton(
|
||||
onClick = {
|
||||
manager.disconnect()
|
||||
onBack()
|
||||
},
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(8.dp)
|
||||
.size(36.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
tint = Color(0xFF9CA3AF),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import androidx.compose.material.icons.automirrored.filled.ExitToApp
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.automirrored.filled.ScreenShare
|
||||
import androidx.compose.material.icons.filled.Cloud
|
||||
import androidx.compose.material.icons.filled.Computer
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material.icons.filled.Notifications
|
||||
@@ -724,6 +725,7 @@ private fun SettingsShellScreen(
|
||||
SettingsRow("Phone Capabilities", if (cameraEnabled) "Camera enabled" else "Locked", Icons.Default.Lock, status = !cameraEnabled, route = SettingsRoute.PhoneCapabilities),
|
||||
SettingsRow("Gateway", gatewaySummary(statusText, isConnected), Icons.Default.Cloud, status = isConnected, route = SettingsRoute.Gateway),
|
||||
SettingsRow("Appearance", "Dark", Icons.Default.Palette, route = SettingsRoute.Appearance),
|
||||
SettingsRow("SSH 终端", "Remote shell", Icons.Default.Computer, route = SettingsRoute.SshTerminal),
|
||||
SettingsRow("Health", "Diagnostics", Icons.Default.Settings, status = isConnected, route = SettingsRoute.Health),
|
||||
SettingsRow("About", "Version and update", Icons.Default.Storage, route = SettingsRoute.About),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user