diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/LiveTvViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/LiveTvViewModel.kt index 03030c7a..bce25670 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/LiveTvViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/LiveTvViewModel.kt @@ -58,14 +58,14 @@ class LiveTvViewModel val channels = MutableLiveData>() val channelProgramCount = mutableMapOf() - val programs = MutableLiveData>() - val programsByChannel = MutableLiveData>>(mapOf()) + val programs = MutableLiveData() +// val programsByChannel = MutableLiveData>>(mapOf()) val fetchingItem = MutableLiveData(LoadingState.Pending) val fetchedItem = MutableLiveData(null) private val range = 8 - val fetchedRange = MutableLiveData(0..(0..) { + private suspend fun fetchProgramsWithLoading( + channels: List, + range: IntRange, + ) { loading.setValueOnMain(LoadingState.Loading) - fetchPrograms(channels, fetchedRange.value!!) + fetchPrograms(channels, range) loading.setValueOnMain(LoadingState.Success) } @@ -112,12 +115,13 @@ class LiveTvViewModel ) = mutex.withLock { val maxStartDate = start.plusHours(MAX_HOURS).minusMinutes(1) val minEndDate = start.plusMinutes(1L) - Timber.v("Fetching programs for ${channels.size} channels") + val channelsToFetch = channels.subList(range.first, range.last) + Timber.v("Fetching programs for $range channels ${channelsToFetch.size}") val request = GetProgramsDto( maxStartDate = maxStartDate, minEndDate = minEndDate, - channelIds = channels.map { it.id }, + channelIds = channelsToFetch.map { it.id }, sortBy = listOf(ItemSortBy.START_DATE), ) val programs = @@ -161,7 +165,8 @@ class LiveTvViewModel } val programsByChannel = programs.groupBy { it.channelId } - val emptyChannels = channels.filter { programsByChannel[it.id].orEmpty().isEmpty() } + val emptyChannels = + channelsToFetch.filter { programsByChannel[it.id].orEmpty().isEmpty() } val fake = mutableListOf() val finalProgramsByChannel = programsByChannel.toMutableMap().apply { @@ -209,9 +214,8 @@ class LiveTvViewModel .filter { it.startHours == it.endHours } .let { Timber.e("Items with same start & end!!! %s", it) } withContext(Dispatchers.Main) { - this@LiveTvViewModel.programs.value = finalProgramList - this@LiveTvViewModel.programsByChannel.value = finalProgramsByChannel - this@LiveTvViewModel.fetchedRange.value = range + this@LiveTvViewModel.programs.value = + FetchedPrograms(range, finalProgramList, finalProgramsByChannel) } } @@ -247,7 +251,7 @@ class LiveTvViewModel viewModelScope.launchIO(ExceptionHandler(autoToast = true)) { if (series) { api.liveTvApi.cancelSeriesTimer(timerId) - fetchProgramsWithLoading(channels.value.orEmpty()) + fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } else { api.liveTvApi.cancelTimer(timerId) refreshProgram(programIndex, programId) @@ -265,7 +269,7 @@ class LiveTvViewModel val d by api.liveTvApi.getDefaultTimer(programId.toServerString()) if (series) { api.liveTvApi.createSeriesTimer(d) - fetchProgramsWithLoading(channels.value.orEmpty()) + fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } else { val payload = TimerInfoDto( @@ -301,36 +305,37 @@ class LiveTvViewModel programId: UUID, ) = mutex.withLock { loading.setValueOnMain(LoadingState.Loading) - val program by api.liveTvApi.getProgram(programId.toServerString()) - val newProgram = - programs.value?.getOrNull(programIndex)?.copy( - isRecording = program.timerId.isNotNullOrBlank(), - isSeriesRecording = program.seriesTimerId.isNotNullOrBlank(), - ) - Timber.v("new program %s", newProgram) - if (newProgram != null) { - programs.value - ?.toMutableList() - ?.apply { - this[programIndex] = newProgram - }?.let { - this@LiveTvViewModel.programs.setValueOnMain(it) - } - } + // TODO +// val program by api.liveTvApi.getProgram(programId.toServerString()) +// val newProgram = +// programs.value?.getOrNull(programIndex)?.copy( +// isRecording = program.timerId.isNotNullOrBlank(), +// isSeriesRecording = program.seriesTimerId.isNotNullOrBlank(), +// ) +// Timber.v("new program %s", newProgram) +// if (newProgram != null) { +// programs.value +// ?.toMutableList() +// ?.apply { +// this[programIndex] = newProgram +// }?.let { +// this@LiveTvViewModel.programs.setValueOnMain(it) +// } +// } loading.setValueOnMain(LoadingState.Success) } fun onFocusChannel(position: RowColumn): Job? { return channels.value?.let { channels -> - val fetchedRange = fetchedRange.value!! + val fetchedRange = programs.value!!.range val quarter = (fetchedRange.last - fetchedRange.start) / 4 val rangeStart = fetchedRange.start + quarter val rangeEnd = fetchedRange.last - quarter val testRange = rangeStart.., + val programsByChannel: Map>, +) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/TvGuideGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/TvGuideGrid.kt index afa1b882..613d1908 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/TvGuideGrid.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/TvGuideGrid.kt @@ -51,6 +51,7 @@ import com.github.damontecres.wholphin.ui.components.LoadingPage import com.github.damontecres.wholphin.ui.data.RowColumn import com.github.damontecres.wholphin.ui.enableMarquee import com.github.damontecres.wholphin.ui.nav.Destination +import com.github.damontecres.wholphin.ui.playback.isDpad import com.github.damontecres.wholphin.ui.rememberPosition import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.util.ExceptionHandler @@ -78,9 +79,9 @@ fun TvGuideGrid( } val loading by viewModel.loading.observeAsState(LoadingState.Pending) val channels by viewModel.channels.observeAsState(listOf()) - val programs by viewModel.programs.observeAsState(listOf()) - val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf()) - val fetchedRange by viewModel.fetchedRange.observeAsState(0..0) + val programs by viewModel.programs.observeAsState(FetchedPrograms(0..0, listOf(), mapOf())) +// val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf()) +// val fetchedRange by viewModel.fetchedRange.observeAsState(0..0) when (val state = loading) { is LoadingState.Error -> ErrorMessage(state, modifier) LoadingState.Pending, @@ -103,11 +104,11 @@ fun TvGuideGrid( TvGuideGrid( loading = state is LoadingState.Loading, channels = channels, - programList = programs, - programs = programsByChannel, +// programList = programs, + programs = programs, channelProgramCount = viewModel.channelProgramCount, start = viewModel.start, - channelOffset = fetchedRange.start, +// channelOffset = fetchedRange.start, onClickChannel = { index, channel -> viewModel.navigationManager.navigateTo( Destination.Playback( @@ -195,14 +196,15 @@ const val CHANNEL_COLUMN = -1 fun TvGuideGrid( loading: Boolean, channels: List, - programList: List, - programs: Map>, +// programList: List, +// programs: Map>, + programs: FetchedPrograms, channelProgramCount: Map, start: LocalDateTime, onClickChannel: (Int, TvChannel) -> Unit, onClickProgram: (Int, TvProgram) -> Unit, onFocus: (RowColumn) -> Unit, - channelOffset: Int, +// channelOffset: Int, modifier: Modifier = Modifier, ) { val context = LocalContext.current @@ -213,16 +215,18 @@ fun TvGuideGrid( var focusedItem by rememberPosition(RowColumn(0, 0)) val focusedChannelIndex = focusedItem.row val focusedProgramIndex = - remember(channelOffset, focusedItem) { + remember(programs.range, focusedItem) { focusedItem.let { focus -> - (channelOffset..= 0) { @@ -335,7 +343,7 @@ fun TvGuideGrid( // Get current program & its start time val currentChannel = channels[item.row].id val currentProgram = - programs[currentChannel]?.get(item.column) + programs.programsByChannel[currentChannel]?.get(item.column) if (currentProgram == null) { // Data is loading in the background item @@ -343,7 +351,7 @@ fun TvGuideGrid( val start = currentProgram.startHours // Get the new row/channel's programs val newChannelPrograms = - programs[channels[newChannelIndex].id].orEmpty() + programs.programsByChannel[channels[newChannelIndex].id].orEmpty() // Find the first program where the start time (of the previously focused program) is in the middle of a program val pIndex = newChannelPrograms.indexOfFirst { start in (it.startHours.. - val program = programList[programIndex] + val program = programs.programs[programIndex] val channelIndex = channels.indexOfFirst { it.id == program.channelId } ProgramGuideItem.Program(channelIndex, program.startHours, program.endHours) }, ) { programIndex -> - val program = programList[programIndex] + val program = programs.programs[programIndex] val focused = gridHasFocus && !channelColumnFocused && programIndex == focusedProgramIndex val background =