import "pkg:/source/utils/misc.brs"
sub init()
m.top.itemComponentName = "HomeItem"
' how many rows are visible on the screen
m.top.numRows = 2
m.top.rowFocusAnimationStyle = "fixedFocusWrap"
m.top.vertFocusAnimationStyle = "fixedFocus"
m.top.showRowLabel = [true]
m.top.rowLabelOffset = [0, 20]
m.top.showRowCounter = [true]
updateSize()
m.top.setfocus(true)
m.top.observeField("rowItemSelected", "itemSelected")
' Load the Libraries from API via task
m.LoadLibrariesTask = createObject("roSGNode", "LoadItemsTask")
m.LoadLibrariesTask.observeField("content", "onLibrariesLoaded")
' set up tesk nodes for other rows
m.LoadContinueTask = createObject("roSGNode", "LoadItemsTask")
m.LoadContinueTask.itemsToLoad = "continue"
m.LoadNextUpTask = createObject("roSGNode", "LoadItemsTask")
m.LoadNextUpTask.itemsToLoad = "nextUp"
m.LoadOnNowTask = createObject("roSGNode", "LoadItemsTask")
m.LoadOnNowTask.itemsToLoad = "onNow"
m.LoadFavoritesTask = createObject("roSGNode", "LoadItemsTask")
m.LoadFavoritesTask.itemsToLoad = "favorites"
end sub
sub loadLibraries()
m.LoadLibrariesTask.control = "RUN"
end sub
sub updateSize()
m.top.translation = [111, 180]
itemHeight = 330
'Set width of Rows to cut off at edge of Safe Zone
m.top.itemSize = [1703, itemHeight]
' spacing between rows
m.top.itemSpacing = [0, 105]
' spacing between items in a row
m.top.rowItemSpacing = [20, 0]
m.top.visible = true
end sub
sub onLibrariesLoaded()
' save data for other functions
m.libraryData = m.LoadLibrariesTask.content
m.LoadLibrariesTask.unobserveField("content")
m.LoadLibrariesTask.content = []
' create My Media, Continue Watching, and Next Up rows
content = CreateObject("roSGNode", "ContentNode")
mediaRow = content.CreateChild("HomeRow")
mediaRow.title = tr("My Media")
continueRow = content.CreateChild("HomeRow")
continueRow.title = tr("Continue Watching")
nextUpRow = content.CreateChild("HomeRow")
nextUpRow.title = tr("Next Up >")
favoritesRow = content.CreateChild("HomeRow")
favoritesRow.title = tr("Favorites")
sizeArray = [
[464, 311], ' My Media
[464, 331], ' Continue Watching
[464, 331], ' Next Up
[464, 331] ' Favorites
]
haveLiveTV = false
' validate library data
if isValid(m.libraryData) and m.libraryData.count() > 0
' populate My Media row
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
for each item in filteredMedia
mediaRow.appendChild(item)
end for
' create a "Latest In" row for each library
filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes)
for each lib in filteredLatest
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program"
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
sizeArray.Push([464, 331])
else if lib.collectionType = "livetv"
' If we have Live TV, add "On Now"
onNowRow = content.CreateChild("HomeRow")
onNowRow.title = tr("On Now")
sizeArray.Push([464, 331])
haveLiveTV = true
end if
end for
end if
m.top.rowItemSize = sizeArray
m.top.content = content
' Load the Continue Watching Data
m.LoadContinueTask.observeField("content", "updateContinueItems")
m.LoadContinueTask.control = "RUN"
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
' If we have Live TV access, load "On Now" data
if haveLiveTV
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end if
end sub
sub updateHomeRows()
if m.global.playstateTask.state = "run"
m.global.playstateTask.observeField("state", "updateHomeRows")
return
end if
m.global.playstateTask.unobserveField("state")
m.LoadContinueTask.observeField("content", "updateContinueItems")
m.LoadContinueTask.control = "RUN"
end sub
sub updateFavoritesItems()
itemData = m.LoadFavoritesTask.content
m.LoadFavoritesTask.unobserveField("content")
m.LoadFavoritesTask.content = []
if itemData = invalid then return
homeRows = m.top.content
rowIndex = getRowIndex("Favorites")
if itemData.count() < 1
if isValid(rowIndex)
' remove the row
deleteFromSizeArray(rowIndex)
homeRows.removeChildIndex(rowIndex)
end if
else
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("Favorites")
itemSize = [464, 331]
for each item in itemData
usePoster = true
if lcase(item.type) = "episode" or lcase(item.type) = "audio" or lcase(item.type) = "musicartist"
usePoster = false
end if
item.usePoster = usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
if rowIndex = invalid
' insert new row under "My Media"
updateSizeArray(itemSize, 1)
homeRows.insertChild(row, 1)
else
' replace the old row
homeRows.replaceChild(row, rowIndex)
end if
end if
end sub
sub updateContinueItems()
itemData = m.LoadContinueTask.content
m.LoadContinueTask.unobserveField("content")
m.LoadContinueTask.content = []
if itemData = invalid then return
homeRows = m.top.content
continueRowIndex = getRowIndex("Continue Watching")
if itemData.count() < 1
if isValid(continueRowIndex)
' remove the row
deleteFromSizeArray(continueRowIndex)
homeRows.removeChildIndex(continueRowIndex)
end if
else
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("Continue Watching")
itemSize = [464, 331]
for each item in itemData
if isValid(item.json) and isValid(item.json.UserData) and isValid(item.json.UserData.PlayedPercentage)
item.PlayedPercentage = item.json.UserData.PlayedPercentage
end if
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
if continueRowIndex = invalid
' insert new row under "My Media"
updateSizeArray(itemSize, 1)
homeRows.insertChild(row, 1)
else
' replace the old row
homeRows.replaceChild(row, continueRowIndex)
end if
end if
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
m.LoadNextUpTask.control = "RUN"
end sub
sub updateNextUpItems()
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
m.LoadNextUpTask.content = []
if itemData = invalid then return
homeRows = m.top.content
nextUpRowIndex = getRowIndex("Next Up >")
if itemData.count() < 1
if isValid(nextUpRowIndex)
' remove the row
deleteFromSizeArray(nextUpRowIndex)
homeRows.removeChildIndex(nextUpRowIndex)
end if
else
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("Next Up") + " >"
itemSize = [464, 331]
for each item in itemData
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
if nextUpRowIndex = invalid
' insert new row under "Continue Watching"
continueRowIndex = getRowIndex("Continue Watching")
if isValid(continueRowIndex)
updateSizeArray(itemSize, continueRowIndex + 1)
homeRows.insertChild(row, continueRowIndex + 1)
else
' insert it under My Media
updateSizeArray(itemSize, 1)
homeRows.insertChild(row, 1)
end if
else
' replace the old row
homeRows.replaceChild(row, nextUpRowIndex)
end if
end if
' consider home screen loaded when above rows are loaded
if m.global.app_loaded = false
m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring
m.global.app_loaded = true
end if
' create task nodes for "Latest In" rows
filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes)
for each lib in filteredLatest
if lib.collectionType <> "livetv" and lib.collectionType <> "boxsets" and lib.json.CollectionType <> "Program"
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
metadata = { "title": lib.name }
metadata.Append({ "contentType": lib.json.CollectionType })
loadLatest.metadata = metadata
loadLatest.observeField("content", "updateLatestItems")
loadLatest.control = "RUN"
end if
end for
end sub
sub updateLatestItems(msg)
itemData = msg.GetData()
node = msg.getRoSGNode()
node.unobserveField("content")
node.content = []
if itemData = invalid then return
homeRows = m.top.content
rowIndex = getRowIndex(tr("Latest in") + " " + node.metadata.title + " >")
if itemData.count() < 1
' remove row
if isValid(rowIndex)
deleteFromSizeArray(rowIndex)
homeRows.removeChildIndex(rowIndex)
end if
else
' remake row using new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("Latest in") + " " + node.metadata.title + " >"
row.usePoster = true
' Handle specific types with different item widths
if node.metadata.contentType = "movies"
row.imageWidth = 180
itemSize = [188, 331]
else if node.metadata.contentType = "music"
row.imageWidth = 261
itemSize = [261, 331]
else
row.imageWidth = 464
itemSize = [464, 331]
end if
for each item in itemData
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
if rowIndex = invalid
' append new row
updateSizeArray(itemSize)
homeRows.appendChild(row)
else
' replace the old row
updateSizeArray(itemSize, rowIndex, "replace")
homeRows.replaceChild(row, rowIndex)
end if
end if
end sub
sub updateOnNowItems()
itemData = m.LoadOnNowTask.content
m.LoadOnNowTask.unobserveField("content")
m.LoadOnNowTask.content = []
if itemData = invalid then return
homeRows = m.top.content
onNowRowIndex = getRowIndex("On Now")
if itemData.count() < 1
if isValid(onNowRowIndex)
' remove the row
deleteFromSizeArray(onNowRowIndex)
homeRows.removeChildIndex(onNowRowIndex)
end if
else
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("On Now")
itemSize = [464, 331]
for each item in itemData
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
if onNowRowIndex = invalid
' insert new row under "My Media"
updateSizeArray(itemSize, 1)
homeRows.insertChild(row, 1)
else
' replace the old row
homeRows.replaceChild(row, onNowRowIndex)
end if
end if
end sub
function getRowIndex(rowTitle as string)
rowIndex = invalid
for i = 1 to m.top.content.getChildCount() - 1
' skip row 0 since it's always "My Media"
tmpRow = m.top.content.getChild(i)
if tmpRow.title = rowTitle
rowIndex = i
exit for
end if
end for
return rowIndex
end function
sub updateSizeArray(rowItemSize, rowIndex = invalid, action = "insert")
sizeArray = m.top.rowItemSize
' append by default
if rowIndex = invalid
rowIndex = sizeArray.count()
end if
newSizeArray = []
for i = 0 to sizeArray.count()
if rowIndex = i
if action = "replace"
newSizeArray.Push(rowItemSize)
else if action = "insert"
newSizeArray.Push(rowItemSize)
if isValid(sizeArray[i])
newSizeArray.Push(sizeArray[i])
end if
end if
else if isValid(sizeArray[i])
newSizeArray.Push(sizeArray[i])
end if
end for
m.top.rowItemSize = newSizeArray
end sub
sub deleteFromSizeArray(rowIndex)
updateSizeArray([0, 0], rowIndex, "delete")
end sub
sub itemSelected()
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
'Prevent the selected item event from double firing
m.top.selectedItem = invalid
end sub
function onKeyEvent(key as string, press as boolean) as boolean
handled = false
if press
if key = "play"
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
if isValid(itemToPlay) and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
m.top.quickPlayNode = itemToPlay
end if
handled = true
end if
if key = "replay"
m.top.jumpToRowItem = [m.top.rowItemFocused[0], 0]
end if
end if
return handled
end function
function filterNodeArray(nodeArray as object, nodeKey as string, excludeArray as object) as object
if excludeArray.IsEmpty() then return nodeArray
newNodeArray = []
for each node in nodeArray
excludeThisNode = false
for each exclude in excludeArray
if node[nodeKey] = exclude
excludeThisNode = true
end if
end for
if excludeThisNode = false
newNodeArray.Push(node)
end if
end for
return newNodeArray
end function