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