Добавлен индикатор загрузки и подключен снэкбар
Этот коммит содержится в:
родитель
d7aefcb03d
Коммит
7d6531af1f
@ -1,7 +1,10 @@
|
||||
package ru.csasq.cit_is_bot
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
@ -12,7 +15,9 @@ import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
@ -65,22 +70,33 @@ fun App() {
|
||||
colorScheme = darkScheme,
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
val snackbarHostState = remember {
|
||||
SnackbarHostState()
|
||||
val progressIndicatorState = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val snackbarHostState = SnackbarHostState()
|
||||
val floatingActionButtonState = remember {
|
||||
mutableStateOf<(@Composable () -> Unit)?>(null)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = "Сообщения",
|
||||
Column {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = "Сообщения",
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
},
|
||||
)
|
||||
when {
|
||||
progressIndicatorState.value -> LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
@ -119,12 +135,12 @@ fun App() {
|
||||
snackbarHost = {
|
||||
SnackbarHost(
|
||||
hostState = snackbarHostState,
|
||||
) {
|
||||
) { snackbarData ->
|
||||
Snackbar(
|
||||
snackbarData = it,
|
||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
contentColor = MaterialTheme.colorScheme.error,
|
||||
actionColor = MaterialTheme.colorScheme.onErrorContainer,
|
||||
snackbarData = snackbarData,
|
||||
// containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
// contentColor = MaterialTheme.colorScheme.error,
|
||||
// actionColor = MaterialTheme.colorScheme.onErrorContainer,
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -145,6 +161,8 @@ fun App() {
|
||||
ScenariosScreen(
|
||||
navController,
|
||||
paddingValues,
|
||||
progressIndicatorState,
|
||||
snackbarHostState,
|
||||
floatingActionButtonState,
|
||||
)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
@ -84,11 +85,15 @@ enum class MessageType(
|
||||
fun ScenarioDialog(
|
||||
scenarioDialogState: MutableState<Scenario?>,
|
||||
client: HttpClient,
|
||||
onSuccess: () -> Unit,
|
||||
properties: DialogProperties = DialogProperties(
|
||||
usePlatformDefaultWidth = false,
|
||||
),
|
||||
) {
|
||||
val coroutine = rememberCoroutineScope()
|
||||
val progressIndicatorState = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val nameState = remember {
|
||||
mutableStateOf(scenarioDialogState.value?.name)
|
||||
}
|
||||
@ -119,71 +124,98 @@ fun ScenarioDialog(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = scenarioDialogState.value?.id?.let {
|
||||
"Изменить сценарий"
|
||||
} ?: "Добавить сценарий",
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
scenarioDialogState.value = null
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.baseline_close_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
Button(
|
||||
onClick = {
|
||||
scenarioDialogState.value?.name = nameState.value!!
|
||||
coroutine.launch {
|
||||
val response = client.put("https://cit.csasq.ru/api/scripts") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(scenarioDialogState.value)
|
||||
}
|
||||
when(response.status) {
|
||||
HttpStatusCode.Created -> scenarioDialogState.value = null
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
Column {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = "Сохранить",
|
||||
text = scenarioDialogState.value?.id?.let {
|
||||
"Изменить сценарий"
|
||||
} ?: "Добавить сценарий",
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
}
|
||||
val dropdownMenuState = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
IconButton(
|
||||
onClick = {
|
||||
dropdownMenuState.value = true
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.baseline_more_vert_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = dropdownMenuState.value,
|
||||
onDismissRequest = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
) {
|
||||
scenarioDialogState.value?.let {
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
scenarioDialogState.value = null
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.baseline_close_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
Button(
|
||||
onClick = {
|
||||
scenarioDialogState.value?.name = nameState.value!!
|
||||
coroutine.launch {
|
||||
progressIndicatorState.value = true
|
||||
val response = client.put("https://cit.csasq.ru/api/scripts") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(scenarioDialogState.value)
|
||||
}
|
||||
progressIndicatorState.value = false
|
||||
when (response.status) {
|
||||
HttpStatusCode.Created -> {
|
||||
onSuccess()
|
||||
scenarioDialogState.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = "Сохранить",
|
||||
)
|
||||
}
|
||||
val dropdownMenuState = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
IconButton(
|
||||
onClick = {
|
||||
dropdownMenuState.value = true
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.baseline_more_vert_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = dropdownMenuState.value,
|
||||
onDismissRequest = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
) {
|
||||
scenarioDialogState.value?.let {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = "Удалить",
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = "Удалить",
|
||||
text = "Сообщить о проблеме",
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = "Справка",
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
@ -191,29 +223,15 @@ fun ScenarioDialog(
|
||||
},
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = "Сообщить о проблеме",
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = "Справка",
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
dropdownMenuState.value = false
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
when {
|
||||
progressIndicatorState.value -> LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
ExtendedFloatingActionButton(
|
||||
|
@ -8,6 +8,8 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@ -15,6 +17,7 @@ import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
@ -46,8 +49,11 @@ data class Scenario(
|
||||
fun ScenariosScreen(
|
||||
navController: NavController,
|
||||
paddingValues: PaddingValues,
|
||||
progressIndicatorState: MutableState<Boolean>,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
floatingActionButtonState: MutableState<(@Composable () -> Unit)?>,
|
||||
) {
|
||||
val snackbarCoroutineScope = rememberCoroutineScope()
|
||||
val verticalScrollState = rememberScrollState()
|
||||
val floatingActionButtonExpandedState = remember {
|
||||
mutableStateOf(true)
|
||||
@ -74,7 +80,9 @@ fun ScenariosScreen(
|
||||
}
|
||||
LaunchedEffect(false) {
|
||||
client.launch {
|
||||
progressIndicatorState.value = true
|
||||
val response = client.get("https://cit.csasq.ru/api/scripts")
|
||||
progressIndicatorState.value = false
|
||||
when (response.status) {
|
||||
HttpStatusCode.OK -> scenarioList.addAll(response.body())
|
||||
}
|
||||
@ -127,7 +135,7 @@ fun ScenariosScreen(
|
||||
}
|
||||
val captionAnnotatedString = buildAnnotatedString {
|
||||
append(it.time)
|
||||
append(" \u2022 ")
|
||||
append(" \u2022 ")
|
||||
append(it.messageNumber)
|
||||
}
|
||||
SwitchButton(
|
||||
@ -147,6 +155,14 @@ fun ScenariosScreen(
|
||||
ScenarioDialog(
|
||||
scenarioDialogState = scenarioDialogState,
|
||||
client = client,
|
||||
onSuccess = {
|
||||
snackbarCoroutineScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = "Сценарий сохранен",
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user