Добавлен индикатор загрузки и подключен снэкбар

Этот коммит содержится в:
Глеб Иваницкий 2024-08-28 11:53:32 +03:00
родитель d7aefcb03d
Коммит 7d6531af1f
3 изменённых файлов: 149 добавлений и 97 удалений

Просмотреть файл

@ -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 = {
Column {
TopAppBar( TopAppBar(
title = { title = {
Text( 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,6 +124,7 @@ fun ScenarioDialog(
modifier = Modifier modifier = Modifier
.fillMaxSize(), .fillMaxSize(),
topBar = { topBar = {
Column {
TopAppBar( TopAppBar(
title = { title = {
Text( Text(
@ -126,7 +132,7 @@ fun ScenarioDialog(
"Изменить сценарий" "Изменить сценарий"
} ?: "Добавить сценарий", } ?: "Добавить сценарий",
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 1, softWrap = false,
) )
}, },
navigationIcon = { navigationIcon = {
@ -146,12 +152,17 @@ fun ScenarioDialog(
onClick = { onClick = {
scenarioDialogState.value?.name = nameState.value!! scenarioDialogState.value?.name = nameState.value!!
coroutine.launch { coroutine.launch {
progressIndicatorState.value = true
val response = client.put("https://cit.csasq.ru/api/scripts") { val response = client.put("https://cit.csasq.ru/api/scripts") {
contentType(ContentType.Application.Json) contentType(ContentType.Application.Json)
setBody(scenarioDialogState.value) setBody(scenarioDialogState.value)
} }
when(response.status) { progressIndicatorState.value = false
HttpStatusCode.Created -> scenarioDialogState.value = null when (response.status) {
HttpStatusCode.Created -> {
onSuccess()
scenarioDialogState.value = null
}
} }
} }
}, },
@ -214,6 +225,13 @@ fun ScenarioDialog(
} }
}, },
) )
when {
progressIndicatorState.value -> LinearProgressIndicator(
modifier = Modifier
.fillMaxWidth(),
)
}
}
}, },
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())
} }
@ -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,
)
}
},
) )
} }
} }