git.iko.soy/opencode-android
on f9ed438 help sign in
107 lines 4.4 kB history raw
1package soy.iko.opencode.ui.server
3import androidx.compose.foundation.layout.Column
4import androidx.compose.foundation.layout.fillMaxWidth
5import androidx.compose.foundation.layout.padding
6import androidx.compose.foundation.rememberScrollState
7import androidx.compose.foundation.verticalScroll
8import androidx.compose.material.icons.Icons
9import androidx.compose.material.icons.automirrored.filled.ArrowBack
10import androidx.compose.material3.Button
11import androidx.compose.material3.ExperimentalMaterial3Api
12import androidx.compose.material3.Icon
13import androidx.compose.material3.IconButton
14import androidx.compose.material3.OutlinedTextField
15import androidx.compose.material3.Scaffold
16import androidx.compose.material3.Text
17import androidx.compose.material3.TopAppBar
18import androidx.compose.runtime.Composable
19import androidx.compose.runtime.getValue
20import androidx.compose.ui.Modifier
21import androidx.compose.ui.text.input.KeyboardType
22import androidx.compose.ui.text.input.PasswordVisualTransformation
23import androidx.compose.foundation.text.KeyboardOptions
24import androidx.compose.foundation.layout.Arrangement
25import androidx.compose.ui.unit.dp
26import androidx.lifecycle.compose.collectAsStateWithLifecycle
27import androidx.lifecycle.viewmodel.compose.viewModel
28import soy.iko.opencode.di.AppContainer
29import soy.iko.opencode.ui.vmFactory
31@OptIn(ExperimentalMaterial3Api::class)
32@Composable
33fun ServerEditScreen(
34 container: AppContainer,
35 profileId: String?,
36 onDone: () -> Unit,
37) {
38 val vm: ServerEditViewModel =
39 viewModel(factory = vmFactory { ServerEditViewModel(container, profileId) })
40 val state by vm.state.collectAsStateWithLifecycle()
42 Scaffold(
43 topBar = {
44 TopAppBar(
45 title = { Text(if (state.isNew) "Add server" else "Edit server") },
46 navigationIcon = {
47 IconButton(onClick = onDone) {
48 Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
49 }
50 },
51 )
52 },
53 ) { padding ->
54 Column(
55 modifier = Modifier
56 .padding(padding)
57 .padding(16.dp)
58 .verticalScroll(rememberScrollState()),
59 verticalArrangement = Arrangement.spacedBy(12.dp),
60 ) {
61 OutlinedTextField(
62 value = state.label,
63 onValueChange = { v -> vm.update { it.copy(label = v) } },
64 label = { Text("Label (optional)") },
65 singleLine = true,
66 modifier = Modifier.fillMaxWidth(),
67 )
68 OutlinedTextField(
69 value = state.baseUrl,
70 onValueChange = { v -> vm.update { it.copy(baseUrl = v) } },
71 label = { Text("Base URL") },
72 placeholder = { Text("http://192.168.1.10:4096") },
73 singleLine = true,
74 keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri),
75 modifier = Modifier.fillMaxWidth(),
76 )
77 Text(
78 "Auth is optional — only needed if the server runs with OPENCODE_SERVER_PASSWORD. " +
79 "Username defaults to \"opencode\".",
80 style = androidx.compose.material3.MaterialTheme.typography.bodySmall,
81 )
82 OutlinedTextField(
83 value = state.username,
84 onValueChange = { v -> vm.update { it.copy(username = v) } },
85 label = { Text("Username (optional)") },
86 singleLine = true,
87 modifier = Modifier.fillMaxWidth(),
88 )
89 OutlinedTextField(
90 value = state.password,
91 onValueChange = { v -> vm.update { it.copy(password = v) } },
92 label = { Text("Password (optional)") },
93 singleLine = true,
94 visualTransformation = PasswordVisualTransformation(),
95 keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
96 modifier = Modifier.fillMaxWidth(),
97 )
98 Button(
99 onClick = { vm.save(onDone) },
100 enabled = state.canSave,
101 modifier = Modifier.fillMaxWidth(),
102 ) {
103 Text("Save")
104 }
105 }
106 }