mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
181 lines
6.9 KiB
Kotlin
181 lines
6.9 KiB
Kotlin
package ru.fromchat.ui.setup
|
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
import androidx.compose.foundation.layout.Column
|
|
import androidx.compose.foundation.layout.Row
|
|
import androidx.compose.foundation.layout.Spacer
|
|
import androidx.compose.foundation.layout.WindowInsets
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
import androidx.compose.foundation.layout.height
|
|
import androidx.compose.foundation.layout.ime
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.foundation.layout.width
|
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
|
import androidx.compose.foundation.rememberScrollState
|
|
import androidx.compose.foundation.verticalScroll
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
import androidx.compose.material3.Button
|
|
import androidx.compose.material3.Checkbox
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
import androidx.compose.material3.Icon
|
|
import androidx.compose.material3.IconButton
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.OutlinedTextField
|
|
import androidx.compose.material3.Scaffold
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.TopAppBar
|
|
import androidx.compose.material3.TopAppBarDefaults
|
|
import androidx.compose.material3.rememberTopAppBarState
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
import androidx.compose.ui.unit.dp
|
|
import com.pr0gramm3r101.utils.navigateAndWipeBackStack
|
|
import com.pr0gramm3r101.utils.storage.ServerConfigData
|
|
import kotlinx.coroutines.launch
|
|
import org.jetbrains.compose.resources.stringResource
|
|
import ru.fromchat.Res
|
|
import ru.fromchat.api.ApiClient
|
|
import ru.fromchat.api.WebSocketManager
|
|
import ru.fromchat.back
|
|
import ru.fromchat.core.config.Config
|
|
import ru.fromchat.https_enabled
|
|
import ru.fromchat.save_continue
|
|
import ru.fromchat.server_config_subtitle
|
|
import ru.fromchat.server_config_title
|
|
import ru.fromchat.server_url_hint
|
|
import ru.fromchat.server_url_label
|
|
import ru.fromchat.ui.LocalNavController
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@Composable
|
|
fun ServerConfigScreen() {
|
|
val navController = LocalNavController.current
|
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
|
|
|
// Load existing config if available
|
|
var serverUrl by remember { mutableStateOf("fromchat.ru") }
|
|
var httpsEnabled by remember { mutableStateOf(true) }
|
|
|
|
LaunchedEffect(Unit) {
|
|
val config = Config.serverConfig.value
|
|
if (config != null) {
|
|
serverUrl = config.serverUrl
|
|
httpsEnabled = config.httpsEnabled
|
|
}
|
|
}
|
|
var isLoading by remember { mutableStateOf(false) }
|
|
val scope = rememberCoroutineScope()
|
|
|
|
Scaffold(
|
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
topBar = {
|
|
TopAppBar(
|
|
title = {},
|
|
navigationIcon = {
|
|
IconButton(onClick = navController::navigateUp) {
|
|
Icon(
|
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
|
contentDescription = stringResource(Res.string.back)
|
|
)
|
|
}
|
|
},
|
|
scrollBehavior = scrollBehavior
|
|
)
|
|
}
|
|
) { innerPadding ->
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.padding(innerPadding)
|
|
.windowInsetsPadding(WindowInsets.ime)
|
|
.padding(horizontal = 24.dp)
|
|
.verticalScroll(rememberScrollState()),
|
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
verticalArrangement = Arrangement.Center
|
|
) {
|
|
Text(
|
|
text = stringResource(Res.string.server_config_title),
|
|
style = MaterialTheme.typography.headlineMedium
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
|
Text(
|
|
text = stringResource(Res.string.server_config_subtitle),
|
|
style = MaterialTheme.typography.bodyMedium,
|
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(32.dp))
|
|
|
|
OutlinedTextField(
|
|
value = serverUrl,
|
|
onValueChange = { serverUrl = it },
|
|
label = { Text(stringResource(Res.string.server_url_label)) },
|
|
placeholder = { Text(stringResource(Res.string.server_url_hint)) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
singleLine = true
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(16.dp))
|
|
|
|
Row(
|
|
modifier = Modifier.fillMaxWidth(),
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
Checkbox(
|
|
checked = httpsEnabled,
|
|
onCheckedChange = { httpsEnabled = it }
|
|
)
|
|
Spacer(modifier = Modifier.width(8.dp))
|
|
Text(stringResource(Res.string.https_enabled))
|
|
}
|
|
|
|
Spacer(modifier = Modifier.height(32.dp))
|
|
|
|
Button(
|
|
onClick = {
|
|
isLoading = true
|
|
scope.launch {
|
|
val config = ServerConfigData(serverUrl, httpsEnabled)
|
|
Config.updateServerConfig(config)
|
|
|
|
// Ensure we're logged out when server config changes
|
|
try {
|
|
ApiClient.token?.let { token ->
|
|
ApiClient.logout(token)
|
|
}
|
|
} catch (e: Exception) {
|
|
// Ignore logout errors
|
|
}
|
|
|
|
// Clear API client state
|
|
ApiClient.token = null
|
|
ApiClient.user = null
|
|
|
|
// Shutdown WebSocket (will reconnect on login)
|
|
WebSocketManager.shutdown()
|
|
|
|
// Navigate to login and wipe entire back stack
|
|
navController.navigateAndWipeBackStack("login")
|
|
}
|
|
},
|
|
enabled = !isLoading && serverUrl.isNotBlank(),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(Res.string.save_continue))
|
|
}
|
|
}
|
|
}
|
|
}
|