mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
WIP
This commit is contained in:
parent
8f08f0d118
commit
bf28209255
2 changed files with 84 additions and 58 deletions
|
|
@ -58,14 +58,14 @@ class LiveTvViewModel
|
||||||
|
|
||||||
val channels = MutableLiveData<List<TvChannel>>()
|
val channels = MutableLiveData<List<TvChannel>>()
|
||||||
val channelProgramCount = mutableMapOf<UUID, Int>()
|
val channelProgramCount = mutableMapOf<UUID, Int>()
|
||||||
val programs = MutableLiveData<List<TvProgram>>()
|
val programs = MutableLiveData<FetchedPrograms>()
|
||||||
val programsByChannel = MutableLiveData<Map<UUID, List<TvProgram>>>(mapOf())
|
// val programsByChannel = MutableLiveData<Map<UUID, List<TvProgram>>>(mapOf())
|
||||||
|
|
||||||
val fetchingItem = MutableLiveData<LoadingState>(LoadingState.Pending)
|
val fetchingItem = MutableLiveData<LoadingState>(LoadingState.Pending)
|
||||||
val fetchedItem = MutableLiveData<BaseItem?>(null)
|
val fetchedItem = MutableLiveData<BaseItem?>(null)
|
||||||
|
|
||||||
private val range = 8
|
private val range = 8
|
||||||
val fetchedRange = MutableLiveData<IntRange>(0..<range)
|
// val fetchedRange = MutableLiveData<IntRange>(0..<range)
|
||||||
|
|
||||||
fun init(firstLoad: Boolean) {
|
fun init(firstLoad: Boolean) {
|
||||||
start = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS)
|
start = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS)
|
||||||
|
|
@ -100,9 +100,12 @@ class LiveTvViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun fetchProgramsWithLoading(channels: List<TvChannel>) {
|
private suspend fun fetchProgramsWithLoading(
|
||||||
|
channels: List<TvChannel>,
|
||||||
|
range: IntRange,
|
||||||
|
) {
|
||||||
loading.setValueOnMain(LoadingState.Loading)
|
loading.setValueOnMain(LoadingState.Loading)
|
||||||
fetchPrograms(channels, fetchedRange.value!!)
|
fetchPrograms(channels, range)
|
||||||
loading.setValueOnMain(LoadingState.Success)
|
loading.setValueOnMain(LoadingState.Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,12 +115,13 @@ class LiveTvViewModel
|
||||||
) = mutex.withLock {
|
) = mutex.withLock {
|
||||||
val maxStartDate = start.plusHours(MAX_HOURS).minusMinutes(1)
|
val maxStartDate = start.plusHours(MAX_HOURS).minusMinutes(1)
|
||||||
val minEndDate = start.plusMinutes(1L)
|
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 =
|
val request =
|
||||||
GetProgramsDto(
|
GetProgramsDto(
|
||||||
maxStartDate = maxStartDate,
|
maxStartDate = maxStartDate,
|
||||||
minEndDate = minEndDate,
|
minEndDate = minEndDate,
|
||||||
channelIds = channels.map { it.id },
|
channelIds = channelsToFetch.map { it.id },
|
||||||
sortBy = listOf(ItemSortBy.START_DATE),
|
sortBy = listOf(ItemSortBy.START_DATE),
|
||||||
)
|
)
|
||||||
val programs =
|
val programs =
|
||||||
|
|
@ -161,7 +165,8 @@ class LiveTvViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
val programsByChannel = programs.groupBy { it.channelId }
|
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<TvProgram>()
|
val fake = mutableListOf<TvProgram>()
|
||||||
val finalProgramsByChannel =
|
val finalProgramsByChannel =
|
||||||
programsByChannel.toMutableMap().apply {
|
programsByChannel.toMutableMap().apply {
|
||||||
|
|
@ -209,9 +214,8 @@ class LiveTvViewModel
|
||||||
.filter { it.startHours == it.endHours }
|
.filter { it.startHours == it.endHours }
|
||||||
.let { Timber.e("Items with same start & end!!! %s", it) }
|
.let { Timber.e("Items with same start & end!!! %s", it) }
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
this@LiveTvViewModel.programs.value = finalProgramList
|
this@LiveTvViewModel.programs.value =
|
||||||
this@LiveTvViewModel.programsByChannel.value = finalProgramsByChannel
|
FetchedPrograms(range, finalProgramList, finalProgramsByChannel)
|
||||||
this@LiveTvViewModel.fetchedRange.value = range
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +251,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)
|
||||||
fetchProgramsWithLoading(channels.value.orEmpty())
|
fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range)
|
||||||
} else {
|
} else {
|
||||||
api.liveTvApi.cancelTimer(timerId)
|
api.liveTvApi.cancelTimer(timerId)
|
||||||
refreshProgram(programIndex, programId)
|
refreshProgram(programIndex, programId)
|
||||||
|
|
@ -265,7 +269,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)
|
||||||
fetchProgramsWithLoading(channels.value.orEmpty())
|
fetchProgramsWithLoading(channels.value.orEmpty(), programs.value!!.range)
|
||||||
} else {
|
} else {
|
||||||
val payload =
|
val payload =
|
||||||
TimerInfoDto(
|
TimerInfoDto(
|
||||||
|
|
@ -301,36 +305,37 @@ class LiveTvViewModel
|
||||||
programId: UUID,
|
programId: UUID,
|
||||||
) = mutex.withLock {
|
) = mutex.withLock {
|
||||||
loading.setValueOnMain(LoadingState.Loading)
|
loading.setValueOnMain(LoadingState.Loading)
|
||||||
val program by api.liveTvApi.getProgram(programId.toServerString())
|
// TODO
|
||||||
val newProgram =
|
// val program by api.liveTvApi.getProgram(programId.toServerString())
|
||||||
programs.value?.getOrNull(programIndex)?.copy(
|
// val newProgram =
|
||||||
isRecording = program.timerId.isNotNullOrBlank(),
|
// programs.value?.getOrNull(programIndex)?.copy(
|
||||||
isSeriesRecording = program.seriesTimerId.isNotNullOrBlank(),
|
// isRecording = program.timerId.isNotNullOrBlank(),
|
||||||
)
|
// isSeriesRecording = program.seriesTimerId.isNotNullOrBlank(),
|
||||||
Timber.v("new program %s", newProgram)
|
// )
|
||||||
if (newProgram != null) {
|
// Timber.v("new program %s", newProgram)
|
||||||
programs.value
|
// if (newProgram != null) {
|
||||||
?.toMutableList()
|
// programs.value
|
||||||
?.apply {
|
// ?.toMutableList()
|
||||||
this[programIndex] = newProgram
|
// ?.apply {
|
||||||
}?.let {
|
// this[programIndex] = newProgram
|
||||||
this@LiveTvViewModel.programs.setValueOnMain(it)
|
// }?.let {
|
||||||
}
|
// this@LiveTvViewModel.programs.setValueOnMain(it)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
loading.setValueOnMain(LoadingState.Success)
|
loading.setValueOnMain(LoadingState.Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onFocusChannel(position: RowColumn): Job? {
|
fun onFocusChannel(position: RowColumn): Job? {
|
||||||
return channels.value?.let { channels ->
|
return channels.value?.let { channels ->
|
||||||
val fetchedRange = fetchedRange.value!!
|
val fetchedRange = programs.value!!.range
|
||||||
val quarter = (fetchedRange.last - fetchedRange.start) / 4
|
val quarter = (fetchedRange.last - fetchedRange.start) / 4
|
||||||
val rangeStart = fetchedRange.start + quarter
|
val rangeStart = fetchedRange.start + quarter
|
||||||
val rangeEnd = fetchedRange.last - quarter
|
val rangeEnd = fetchedRange.last - quarter
|
||||||
val testRange = rangeStart..<rangeEnd
|
val testRange = rangeStart..<rangeEnd
|
||||||
|
|
||||||
Timber.v(
|
// Timber.v(
|
||||||
"onFocusChannel: position=$position, fetchedRange=$fetchedRange, testRange=$testRange",
|
// "onFocusChannel: position=$position, fetchedRange=$fetchedRange, testRange=$testRange",
|
||||||
)
|
// )
|
||||||
val fetchStart = (position.row - range).coerceAtLeast(0)
|
val fetchStart = (position.row - range).coerceAtLeast(0)
|
||||||
val fetchEnd = (position.row + range).coerceAtMost(channels.size)
|
val fetchEnd = (position.row + range).coerceAtMost(channels.size)
|
||||||
val newFetchRange = fetchStart..<fetchEnd
|
val newFetchRange = fetchStart..<fetchEnd
|
||||||
|
|
@ -340,7 +345,7 @@ class LiveTvViewModel
|
||||||
if (position.row !in testRange && !newFetchRange.within(fetchedRange)) {
|
if (position.row !in testRange && !newFetchRange.within(fetchedRange)) {
|
||||||
Timber.v("Loading more programs for channels $newFetchRange")
|
Timber.v("Loading more programs for channels $newFetchRange")
|
||||||
return viewModelScope.launchIO {
|
return viewModelScope.launchIO {
|
||||||
fetchPrograms(channels, newFetchRange)
|
fetchProgramsWithLoading(channels, newFetchRange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|
@ -396,3 +401,9 @@ enum class ProgramCategory(
|
||||||
SPORTS(AppColors.DarkRed),
|
SPORTS(AppColors.DarkRed),
|
||||||
FAKE(null),
|
FAKE(null),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class FetchedPrograms(
|
||||||
|
val range: IntRange,
|
||||||
|
val programs: List<TvProgram>,
|
||||||
|
val programsByChannel: Map<UUID, List<TvProgram>>,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -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.data.RowColumn
|
||||||
import com.github.damontecres.wholphin.ui.enableMarquee
|
import com.github.damontecres.wholphin.ui.enableMarquee
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
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.rememberPosition
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
|
@ -78,9 +79,9 @@ fun TvGuideGrid(
|
||||||
}
|
}
|
||||||
val loading by viewModel.loading.observeAsState(LoadingState.Pending)
|
val loading by viewModel.loading.observeAsState(LoadingState.Pending)
|
||||||
val channels by viewModel.channels.observeAsState(listOf())
|
val channels by viewModel.channels.observeAsState(listOf())
|
||||||
val programs by viewModel.programs.observeAsState(listOf())
|
val programs by viewModel.programs.observeAsState(FetchedPrograms(0..0, listOf(), mapOf()))
|
||||||
val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf())
|
// val programsByChannel by viewModel.programsByChannel.observeAsState(mapOf())
|
||||||
val fetchedRange by viewModel.fetchedRange.observeAsState(0..0)
|
// val fetchedRange by viewModel.fetchedRange.observeAsState(0..0)
|
||||||
when (val state = loading) {
|
when (val state = loading) {
|
||||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||||
LoadingState.Pending,
|
LoadingState.Pending,
|
||||||
|
|
@ -103,11 +104,11 @@ fun TvGuideGrid(
|
||||||
TvGuideGrid(
|
TvGuideGrid(
|
||||||
loading = state is LoadingState.Loading,
|
loading = state is LoadingState.Loading,
|
||||||
channels = channels,
|
channels = channels,
|
||||||
programList = programs,
|
// programList = programs,
|
||||||
programs = programsByChannel,
|
programs = programs,
|
||||||
channelProgramCount = viewModel.channelProgramCount,
|
channelProgramCount = viewModel.channelProgramCount,
|
||||||
start = viewModel.start,
|
start = viewModel.start,
|
||||||
channelOffset = fetchedRange.start,
|
// channelOffset = fetchedRange.start,
|
||||||
onClickChannel = { index, channel ->
|
onClickChannel = { index, channel ->
|
||||||
viewModel.navigationManager.navigateTo(
|
viewModel.navigationManager.navigateTo(
|
||||||
Destination.Playback(
|
Destination.Playback(
|
||||||
|
|
@ -195,14 +196,15 @@ const val CHANNEL_COLUMN = -1
|
||||||
fun TvGuideGrid(
|
fun TvGuideGrid(
|
||||||
loading: Boolean,
|
loading: Boolean,
|
||||||
channels: List<TvChannel>,
|
channels: List<TvChannel>,
|
||||||
programList: List<TvProgram>,
|
// programList: List<TvProgram>,
|
||||||
programs: Map<UUID, List<TvProgram>>,
|
// programs: Map<UUID, List<TvProgram>>,
|
||||||
|
programs: FetchedPrograms,
|
||||||
channelProgramCount: Map<UUID, Int>,
|
channelProgramCount: Map<UUID, Int>,
|
||||||
start: LocalDateTime,
|
start: LocalDateTime,
|
||||||
onClickChannel: (Int, TvChannel) -> Unit,
|
onClickChannel: (Int, TvChannel) -> Unit,
|
||||||
onClickProgram: (Int, TvProgram) -> Unit,
|
onClickProgram: (Int, TvProgram) -> Unit,
|
||||||
onFocus: (RowColumn) -> Unit,
|
onFocus: (RowColumn) -> Unit,
|
||||||
channelOffset: Int,
|
// channelOffset: Int,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
@ -213,16 +215,18 @@ fun TvGuideGrid(
|
||||||
var focusedItem by rememberPosition(RowColumn(0, 0))
|
var focusedItem by rememberPosition(RowColumn(0, 0))
|
||||||
val focusedChannelIndex = focusedItem.row
|
val focusedChannelIndex = focusedItem.row
|
||||||
val focusedProgramIndex =
|
val focusedProgramIndex =
|
||||||
remember(channelOffset, focusedItem) {
|
remember(programs.range, focusedItem) {
|
||||||
focusedItem.let { focus ->
|
focusedItem.let { focus ->
|
||||||
(channelOffset..<focus.row).sumOf { channelProgramCount[channels[it].id]!! } + focus.column
|
(programs.range.start..<focus.row).sumOf {
|
||||||
|
val channelId = channels[it].id
|
||||||
|
channelProgramCount[channelId] ?: 0
|
||||||
|
} + focus.column
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(focusedProgramIndex) {
|
LaunchedEffect(focusedProgramIndex) {
|
||||||
// Timber.v("Focusing on $focusedItem, programIndex=$focusedProgramIndex")
|
// Timber.v("Focusing on $focusedItem, programIndex=$focusedProgramIndex")
|
||||||
scope.launch(ExceptionHandler()) {
|
scope.launch(ExceptionHandler()) {
|
||||||
// Timber.v("program=${programList.getOrNull(focusedProgramIndex)}")
|
|
||||||
state.animateToProgram(focusedProgramIndex, Alignment.Center)
|
state.animateToProgram(focusedProgramIndex, Alignment.Center)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -250,6 +254,10 @@ fun TvGuideGrid(
|
||||||
if (it.type == KeyEventType.KeyUp) {
|
if (it.type == KeyEventType.KeyUp) {
|
||||||
return@onPreviewKeyEvent false
|
return@onPreviewKeyEvent false
|
||||||
}
|
}
|
||||||
|
if (isDpad(it) && loading) {
|
||||||
|
// Prevent movement during loading
|
||||||
|
return@onPreviewKeyEvent true
|
||||||
|
}
|
||||||
val item = focusedItem
|
val item = focusedItem
|
||||||
val newFocusedItem =
|
val newFocusedItem =
|
||||||
when (it.key) {
|
when (it.key) {
|
||||||
|
|
@ -295,13 +303,13 @@ fun TvGuideGrid(
|
||||||
} else {
|
} else {
|
||||||
val currentChannel = channels[item.row].id
|
val currentChannel = channels[item.row].id
|
||||||
val currentProgram =
|
val currentProgram =
|
||||||
programs[currentChannel]?.get(item.column)
|
programs.programsByChannel[currentChannel]?.get(item.column)
|
||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
item
|
item
|
||||||
} else {
|
} else {
|
||||||
val start = currentProgram.startHours
|
val start = currentProgram.startHours
|
||||||
val newChannelPrograms =
|
val newChannelPrograms =
|
||||||
programs[channels[newChannelIndex].id].orEmpty()
|
programs.programsByChannel[channels[newChannelIndex].id].orEmpty()
|
||||||
val pIndex =
|
val pIndex =
|
||||||
newChannelPrograms.indexOfFirst { start in (it.startHours..<it.endHours) }
|
newChannelPrograms.indexOfFirst { start in (it.startHours..<it.endHours) }
|
||||||
if (pIndex >= 0) {
|
if (pIndex >= 0) {
|
||||||
|
|
@ -335,7 +343,7 @@ fun TvGuideGrid(
|
||||||
// Get current program & its start time
|
// Get current program & its start time
|
||||||
val currentChannel = channels[item.row].id
|
val currentChannel = channels[item.row].id
|
||||||
val currentProgram =
|
val currentProgram =
|
||||||
programs[currentChannel]?.get(item.column)
|
programs.programsByChannel[currentChannel]?.get(item.column)
|
||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
// Data is loading in the background
|
// Data is loading in the background
|
||||||
item
|
item
|
||||||
|
|
@ -343,7 +351,7 @@ fun TvGuideGrid(
|
||||||
val start = currentProgram.startHours
|
val start = currentProgram.startHours
|
||||||
// Get the new row/channel's programs
|
// Get the new row/channel's programs
|
||||||
val newChannelPrograms =
|
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
|
// Find the first program where the start time (of the previously focused program) is in the middle of a program
|
||||||
val pIndex =
|
val pIndex =
|
||||||
newChannelPrograms.indexOfFirst { start in (it.startHours..<it.endHours) }
|
newChannelPrograms.indexOfFirst { start in (it.startHours..<it.endHours) }
|
||||||
|
|
@ -378,13 +386,16 @@ fun TvGuideGrid(
|
||||||
} else {
|
} else {
|
||||||
val currentChannel = channels[item.row].id
|
val currentChannel = channels[item.row].id
|
||||||
val currentProgram =
|
val currentProgram =
|
||||||
programs[currentChannel]?.get(item.column)
|
programs.programsByChannel[currentChannel]?.get(item.column)
|
||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
// Data is loading in the background
|
// Data is loading in the background
|
||||||
return@onPreviewKeyEvent true
|
return@onPreviewKeyEvent true
|
||||||
}
|
}
|
||||||
Timber.v("Clicked on %s", currentProgram)
|
Timber.v("Clicked on %s", currentProgram)
|
||||||
onClickProgram.invoke(focusedProgramIndex, currentProgram)
|
onClickProgram.invoke(
|
||||||
|
focusedProgramIndex,
|
||||||
|
currentProgram,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
@ -396,7 +407,7 @@ fun TvGuideGrid(
|
||||||
|
|
||||||
if (newFocusedItem != null) {
|
if (newFocusedItem != null) {
|
||||||
val channel = channels[newFocusedItem.row]
|
val channel = channels[newFocusedItem.row]
|
||||||
val programs = programs[channel.id].orEmpty()
|
val programs = programs.programsByChannel[channel.id].orEmpty()
|
||||||
// Ensure it isn't going out of range
|
// Ensure it isn't going out of range
|
||||||
val toFocus =
|
val toFocus =
|
||||||
newFocusedItem
|
newFocusedItem
|
||||||
|
|
@ -424,7 +435,12 @@ fun TvGuideGrid(
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
colors = SurfaceDefaults.colors(MaterialTheme.colorScheme.tertiary.copy(alpha = .25f)),
|
colors =
|
||||||
|
SurfaceDefaults.colors(
|
||||||
|
MaterialTheme.colorScheme.tertiary.copy(
|
||||||
|
alpha = .25f,
|
||||||
|
),
|
||||||
|
),
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
// Empty
|
// Empty
|
||||||
|
|
@ -465,16 +481,15 @@ fun TvGuideGrid(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
programs(
|
programs(
|
||||||
count = programList.size,
|
count = programs.programs.size,
|
||||||
layoutInfo = { programIndex ->
|
layoutInfo = { programIndex ->
|
||||||
val program = programList[programIndex]
|
val program = programs.programs[programIndex]
|
||||||
val channelIndex = channels.indexOfFirst { it.id == program.channelId }
|
val channelIndex = channels.indexOfFirst { it.id == program.channelId }
|
||||||
ProgramGuideItem.Program(channelIndex, program.startHours, program.endHours)
|
ProgramGuideItem.Program(channelIndex, program.startHours, program.endHours)
|
||||||
},
|
},
|
||||||
) { programIndex ->
|
) { programIndex ->
|
||||||
val program = programList[programIndex]
|
val program = programs.programs[programIndex]
|
||||||
val focused =
|
val focused =
|
||||||
gridHasFocus && !channelColumnFocused && programIndex == focusedProgramIndex
|
gridHasFocus && !channelColumnFocused && programIndex == focusedProgramIndex
|
||||||
val background =
|
val background =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue