mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 08:01:20 +02:00
Show loading indicator when refreshing guide data
This commit is contained in:
parent
be7bb65a7e
commit
36287be5d4
3 changed files with 411 additions and 371 deletions
|
|
@ -90,6 +90,12 @@ class LiveTvViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchProgramsWithLoading(channels: List<TvChannel>) {
|
||||||
|
loading.setValueOnMain(LoadingState.Loading)
|
||||||
|
fetchPrograms(channels)
|
||||||
|
loading.setValueOnMain(LoadingState.Success)
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun fetchPrograms(channels: List<TvChannel>) =
|
private suspend fun fetchPrograms(channels: List<TvChannel>) =
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val maxStartDate = start.plusHours(MAX_HOURS).minusMinutes(1)
|
val maxStartDate = start.plusHours(MAX_HOURS).minusMinutes(1)
|
||||||
|
|
@ -203,7 +209,7 @@ class LiveTvViewModel
|
||||||
viewModelScope.launchIO(ExceptionHandler(autoToast = true)) {
|
viewModelScope.launchIO(ExceptionHandler(autoToast = true)) {
|
||||||
if (series) {
|
if (series) {
|
||||||
api.liveTvApi.cancelSeriesTimer(timerId)
|
api.liveTvApi.cancelSeriesTimer(timerId)
|
||||||
fetchPrograms(channels.value.orEmpty())
|
fetchProgramsWithLoading(channels.value.orEmpty())
|
||||||
} else {
|
} else {
|
||||||
api.liveTvApi.cancelTimer(timerId)
|
api.liveTvApi.cancelTimer(timerId)
|
||||||
refreshProgram(programIndex, programId)
|
refreshProgram(programIndex, programId)
|
||||||
|
|
@ -221,7 +227,7 @@ class LiveTvViewModel
|
||||||
val d by api.liveTvApi.getDefaultTimer(programId.toServerString())
|
val d by api.liveTvApi.getDefaultTimer(programId.toServerString())
|
||||||
if (series) {
|
if (series) {
|
||||||
api.liveTvApi.createSeriesTimer(d)
|
api.liveTvApi.createSeriesTimer(d)
|
||||||
fetchPrograms(channels.value.orEmpty())
|
fetchProgramsWithLoading(channels.value.orEmpty())
|
||||||
} else {
|
} else {
|
||||||
val payload =
|
val payload =
|
||||||
TimerInfoDto(
|
TimerInfoDto(
|
||||||
|
|
@ -256,6 +262,7 @@ class LiveTvViewModel
|
||||||
programIndex: Int,
|
programIndex: Int,
|
||||||
programId: UUID,
|
programId: UUID,
|
||||||
) = mutex.withLock {
|
) = mutex.withLock {
|
||||||
|
loading.setValueOnMain(LoadingState.Loading)
|
||||||
val program by api.liveTvApi.getProgram(programId.toServerString())
|
val program by api.liveTvApi.getProgram(programId.toServerString())
|
||||||
val newProgram =
|
val newProgram =
|
||||||
programs.value?.getOrNull(programIndex)?.copy(
|
programs.value?.getOrNull(programIndex)?.copy(
|
||||||
|
|
@ -272,6 +279,7 @@ class LiveTvViewModel
|
||||||
this@LiveTvViewModel.programs.setValueOnMain(it)
|
this@LiveTvViewModel.programs.setValueOnMain(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loading.setValueOnMain(LoadingState.Success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
|
@ -129,6 +130,17 @@ fun ProgramDialog(
|
||||||
maxLines = 3,
|
maxLines = 3,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
) {
|
||||||
if (dto.isSeries ?: false) {
|
if (dto.isSeries ?: false) {
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
@ -181,6 +193,7 @@ fun ProgramDialog(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (now.isAfter(dto.startDate!!) && now.isBefore(dto.endDate!!)) {
|
if (now.isAfter(dto.startDate!!) && now.isBefore(dto.endDate!!)) {
|
||||||
Button(
|
Button(
|
||||||
onClick = onWatch,
|
onClick = onWatch,
|
||||||
|
|
@ -205,4 +218,5 @@ fun ProgramDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -43,6 +45,7 @@ import androidx.tv.material3.Text
|
||||||
import androidx.tv.material3.contentColorFor
|
import androidx.tv.material3.contentColorFor
|
||||||
import androidx.tv.material3.surfaceColorAtElevation
|
import androidx.tv.material3.surfaceColorAtElevation
|
||||||
import coil3.compose.AsyncImage
|
import coil3.compose.AsyncImage
|
||||||
|
import com.github.damontecres.wholphin.ui.components.CircularProgress
|
||||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||||
import com.github.damontecres.wholphin.ui.enableMarquee
|
import com.github.damontecres.wholphin.ui.enableMarquee
|
||||||
|
|
@ -78,12 +81,12 @@ fun TvGuideGrid(
|
||||||
val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf())
|
val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf())
|
||||||
when (val state = loading) {
|
when (val state = loading) {
|
||||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||||
|
|
||||||
LoadingState.Loading,
|
|
||||||
LoadingState.Pending,
|
LoadingState.Pending,
|
||||||
-> LoadingPage(modifier)
|
-> LoadingPage(modifier)
|
||||||
|
|
||||||
LoadingState.Success -> {
|
LoadingState.Loading,
|
||||||
|
LoadingState.Success,
|
||||||
|
-> {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val fetchedItem by viewModel.fetchedItem.observeAsState(null)
|
val fetchedItem by viewModel.fetchedItem.observeAsState(null)
|
||||||
val loadingItem by viewModel.fetchingItem.observeAsState(LoadingState.Pending)
|
val loadingItem by viewModel.fetchingItem.observeAsState(LoadingState.Pending)
|
||||||
|
|
@ -96,6 +99,7 @@ fun TvGuideGrid(
|
||||||
}
|
}
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
TvGuideGrid(
|
TvGuideGrid(
|
||||||
|
loading = state is LoadingState.Loading,
|
||||||
channels = channels,
|
channels = channels,
|
||||||
programList = programs,
|
programList = programs,
|
||||||
programs = programsByChannel,
|
programs = programsByChannel,
|
||||||
|
|
@ -183,6 +187,7 @@ const val CHANNEL_COLUMN = -1
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TvGuideGrid(
|
fun TvGuideGrid(
|
||||||
|
loading: Boolean,
|
||||||
channels: List<TvChannel>,
|
channels: List<TvChannel>,
|
||||||
programList: List<TvProgram>,
|
programList: List<TvProgram>,
|
||||||
programs: Map<UUID, List<TvProgram>>,
|
programs: Map<UUID, List<TvProgram>>,
|
||||||
|
|
@ -225,12 +230,13 @@ fun TvGuideGrid(
|
||||||
|
|
||||||
var gridHasFocus by rememberSaveable { mutableStateOf(false) }
|
var gridHasFocus by rememberSaveable { mutableStateOf(false) }
|
||||||
var channelColumnFocused by rememberSaveable { mutableStateOf(false) }
|
var channelColumnFocused by rememberSaveable { mutableStateOf(false) }
|
||||||
|
Box(modifier = modifier) {
|
||||||
ProgramGuide(
|
ProgramGuide(
|
||||||
state = state,
|
state = state,
|
||||||
dimensions = dimensions,
|
dimensions = dimensions,
|
||||||
modifier =
|
modifier =
|
||||||
modifier
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
gridHasFocus = it.hasFocus
|
gridHasFocus = it.hasFocus
|
||||||
}.focusable()
|
}.focusable()
|
||||||
|
|
@ -574,4 +580,16 @@ fun TvGuideGrid(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (loading) {
|
||||||
|
CircularProgress(
|
||||||
|
Modifier
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.background.copy(alpha = .5f),
|
||||||
|
shape = CircleShape,
|
||||||
|
).size(64.dp)
|
||||||
|
.padding(16.dp)
|
||||||
|
.align(Alignment.BottomEnd),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue