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 bce25670..e7abb3d0 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 @@ -59,13 +59,11 @@ class LiveTvViewModel val channels = MutableLiveData>() val channelProgramCount = mutableMapOf() val programs = MutableLiveData() -// val programsByChannel = MutableLiveData>>(mapOf()) val fetchingItem = MutableLiveData(LoadingState.Pending) val fetchedItem = MutableLiveData(null) - private val range = 8 -// val fetchedRange = MutableLiveData(0..= it.endHours - }.sortedWith( + .sortedWith( compareBy( { channelsIdToIndex[it.channelId]!! }, { it.start }, ), ) Timber.d("Got ${programs.size} programs & ${fake.size} fake programs") - finalProgramList - .filter { it.startHours == it.endHours } - .let { Timber.e("Items with same start & end!!! %s", it) } withContext(Dispatchers.Main) { this@LiveTvViewModel.programs.value = FetchedPrograms(range, finalProgramList, finalProgramsByChannel) @@ -251,11 +242,10 @@ class LiveTvViewModel viewModelScope.launchIO(ExceptionHandler(autoToast = true)) { if (series) { api.liveTvApi.cancelSeriesTimer(timerId) - fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } else { api.liveTvApi.cancelTimer(timerId) - refreshProgram(programIndex, programId) } + fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } } } @@ -269,7 +259,6 @@ class LiveTvViewModel val d by api.liveTvApi.getDefaultTimer(programId.toServerString()) if (series) { api.liveTvApi.createSeriesTimer(d) - fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } else { val payload = TimerInfoDto( @@ -295,8 +284,8 @@ class LiveTvViewModel keepUntil = d.keepUntil, ) api.liveTvApi.createTimer(payload) - refreshProgram(programIndex, programId) } + fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range) } } @@ -325,17 +314,33 @@ class LiveTvViewModel loading.setValueOnMain(LoadingState.Success) } - fun onFocusChannel(position: RowColumn): Job? { - return channels.value?.let { channels -> + private var focusLoadingJob: Job? = null + + fun onFocusChannel(position: RowColumn) { + channels.value?.let { channels -> val fetchedRange = programs.value!!.range - val quarter = (fetchedRange.last - fetchedRange.start) / 4 - val rangeStart = fetchedRange.start + quarter - val rangeEnd = fetchedRange.last - quarter + val quarter = range / 4 + var rangeStart = fetchedRange.start + quarter + var rangeEnd = fetchedRange.last - quarter + + if (rangeEnd - rangeStart < range) { + if (position.row < range / 2) { + // Close to beginning + rangeStart = 0 + } else if (position.row > (channels.size - range / 2)) { + // Close to the end + rangeEnd = channels.size + } + } val testRange = rangeStart..= 0) { @@ -335,43 +335,50 @@ fun TvGuideGrid( // If trying to move below the final channel, then move focus out of the grid focusManager.moveFocus(FocusDirection.Down) null - } else if (channelColumnFocused) { - // If focused on the channel column, move down a channel - RowColumn(newChannelIndex, 0) } else { // Otherwise, moving to a new row - // Get current program & its start time - val currentChannel = channels[item.row].id - val currentProgram = - programs.programsByChannel[currentChannel]?.get(item.column) - if (currentProgram == null) { - // Data is loading in the background - item + // Get the new row/channel's programs + val newChannelId = channels[newChannelIndex].id + val newChannelPrograms = + programs.programsByChannel[newChannelId] + if (newChannelPrograms == null) { + // This means there is no data for the new channel and it is loading in the background + return@onPreviewKeyEvent true + } + if (channelColumnFocused) { + // If focused on the channel column, move down a channel + RowColumn(newChannelIndex, 0) } else { - val start = currentProgram.startHours - // Get the new row/channel's programs - val newChannelPrograms = - 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..= 0) { - // Found one, so focus on it - RowColumn(newChannelIndex, pIndex) + // Get current program & its start time + val currentChannel = channels[item.row].id + val currentProgram = + programs.programsByChannel[currentChannel]?.get(item.column) + if (currentProgram == null) { + // Data is loading in the background + item } else { - // Didn't find one, probably due to missing data - // So now first the first one that starts after the previously focused program + val start = currentProgram.startHours + // Find the first program where the start time (of the previously focused program) is in the middle of a program val pIndex = - newChannelPrograms.indexOfFirst { it.startHours >= start } + newChannelPrograms.indexOfFirst { start in (it.startHours..= 0) { // Found one, so focus on it RowColumn(newChannelIndex, pIndex) } else { - // Did not find one, so focus on the final program in the list - RowColumn( - newChannelIndex, - newChannelPrograms.size - 1, - ) + // Didn't find one, probably due to missing data + // So now first the first one that starts after the previously focused program + val pIndex = + newChannelPrograms.indexOfFirst { it.startHours >= start } + if (pIndex >= 0) { + // Found one, so focus on it + RowColumn(newChannelIndex, pIndex) + } else { + // Did not find one, so focus on the final program in the list + RowColumn( + newChannelIndex, + newChannelPrograms.size - 1, + ) + } } } } @@ -416,7 +423,7 @@ fun TvGuideGrid( column = newFocusedItem.column.coerceIn( 0, - programs.size - 1, + (programs.size - 1).coerceAtLeast(0), ), ) focusedItem = toFocus @@ -486,7 +493,14 @@ fun TvGuideGrid( layoutInfo = { programIndex -> val program = programs.programs[programIndex] val channelIndex = channels.indexOfFirst { it.id == program.channelId } - ProgramGuideItem.Program(channelIndex, program.startHours, program.endHours) + // Using the duration for endHour accounts for daylight savings switch + // Eg a 1:30am-1:00am show + val duration = abs(program.endHours - program.startHours) + ProgramGuideItem.Program( + channelIndex, + program.startHours, + program.startHours + duration, + ) }, ) { programIndex -> val program = programs.programs[programIndex]