2023-10-03 16:11:25 +00:00
|
|
|
import "pkg:/source/utils/misc.bs"
|
2023-11-27 22:14:19 +00:00
|
|
|
import "pkg:/source/constants/HomeRowItemSizes.bs"
|
2023-11-23 13:52:44 +00:00
|
|
|
|
2023-12-02 13:47:35 +00:00
|
|
|
const LOADING_WAIT_TIME = 2
|
2023-12-02 04:05:15 +00:00
|
|
|
|
2020-03-03 23:01:13 +00:00
|
|
|
sub init()
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.itemComponentName = "HomeItem"
|
|
|
|
' how many rows are visible on the screen
|
|
|
|
m.top.numRows = 2
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.rowFocusAnimationStyle = "fixedFocusWrap"
|
|
|
|
m.top.vertFocusAnimationStyle = "fixedFocus"
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.showRowLabel = [true]
|
|
|
|
m.top.rowLabelOffset = [0, 20]
|
2023-12-02 04:05:15 +00:00
|
|
|
' Hide the row counter to prevent flicker. We'll show it once loading timer fires
|
|
|
|
m.top.showRowCounter = [false]
|
|
|
|
|
|
|
|
m.top.content = CreateObject("roSGNode", "ContentNode")
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
m.loadingTimer = createObject("roSGNode", "Timer")
|
2023-12-02 13:47:35 +00:00
|
|
|
m.loadingTimer.duration = LOADING_WAIT_TIME
|
2023-12-02 04:05:15 +00:00
|
|
|
m.loadingTimer.observeField("fire", "loadingTimerComplete")
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
updateSize()
|
2020-03-12 18:33:45 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.setfocus(true)
|
2020-03-12 18:33:45 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.observeField("rowItemSelected", "itemSelected")
|
2020-04-04 22:24:47 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' Load the Libraries from API via task
|
|
|
|
m.LoadLibrariesTask = createObject("roSGNode", "LoadItemsTask")
|
|
|
|
m.LoadLibrariesTask.observeField("content", "onLibrariesLoaded")
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' set up task nodes for other rows
|
2023-10-22 22:37:37 +00:00
|
|
|
m.LoadContinueWatchingTask = createObject("roSGNode", "LoadItemsTask")
|
|
|
|
m.LoadContinueWatchingTask.itemsToLoad = "continue"
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.LoadNextUpTask = createObject("roSGNode", "LoadItemsTask")
|
|
|
|
m.LoadNextUpTask.itemsToLoad = "nextUp"
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2021-12-18 06:31:28 +00:00
|
|
|
m.LoadOnNowTask = createObject("roSGNode", "LoadItemsTask")
|
2021-12-20 14:57:22 +00:00
|
|
|
m.LoadOnNowTask.itemsToLoad = "onNow"
|
2022-11-05 00:37:54 +00:00
|
|
|
|
|
|
|
m.LoadFavoritesTask = createObject("roSGNode", "LoadItemsTask")
|
|
|
|
m.LoadFavoritesTask.itemsToLoad = "favorites"
|
2020-03-03 23:01:13 +00:00
|
|
|
end sub
|
|
|
|
|
2021-06-26 10:18:09 +00:00
|
|
|
sub loadLibraries()
|
2021-07-09 20:08:32 +00:00
|
|
|
m.LoadLibrariesTask.control = "RUN"
|
2021-06-26 10:18:09 +00:00
|
|
|
end sub
|
2020-12-08 15:56:13 +00:00
|
|
|
|
2020-03-03 23:01:13 +00:00
|
|
|
sub updateSize()
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.translation = [111, 180]
|
2022-07-12 23:15:59 +00:00
|
|
|
itemHeight = 330
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
'Set width of Rows to cut off at edge of Safe Zone
|
|
|
|
m.top.itemSize = [1703, itemHeight]
|
2020-06-10 14:40:09 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' spacing between rows
|
2022-07-12 23:15:59 +00:00
|
|
|
m.top.itemSpacing = [0, 105]
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' spacing between items in a row
|
|
|
|
m.top.rowItemSpacing = [20, 0]
|
2020-03-03 23:01:13 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Default size to wide poster, the most used size
|
|
|
|
m.top.rowItemSize = homeRowItemSizes.WIDE_POSTER
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.visible = true
|
2020-03-03 23:01:13 +00:00
|
|
|
end sub
|
|
|
|
|
2023-11-22 19:58:21 +00:00
|
|
|
' processUserSections: Loop through user's chosen home section settings and generate the content for each row
|
|
|
|
'
|
2023-12-02 04:05:15 +00:00
|
|
|
sub processUserSections()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.expectedRowCount = 1 ' the favorites row is hardcoded to always show atm
|
|
|
|
m.processedRowCount = 0
|
|
|
|
|
|
|
|
' calculate expected row count by processing homesections
|
|
|
|
for i = 0 to 6
|
|
|
|
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
|
|
|
|
if sectionName = "latestmedia"
|
|
|
|
' expect 1 row per filtered media library
|
|
|
|
m.filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes)
|
|
|
|
for each latestLibrary in m.filteredLatest
|
|
|
|
if latestLibrary.collectionType <> "boxsets" and latestLibrary.collectionType <> "livetv" and latestLibrary.json.CollectionType <> "Program"
|
|
|
|
m.expectedRowCount++
|
|
|
|
end if
|
|
|
|
end for
|
|
|
|
else if sectionName <> "none"
|
|
|
|
m.expectedRowCount++
|
|
|
|
end if
|
|
|
|
end for
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
' Add home sections in order based on user settings
|
|
|
|
loadedSections = 0
|
2023-09-30 21:36:16 +00:00
|
|
|
for i = 0 to 6
|
2023-10-22 22:37:37 +00:00
|
|
|
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
|
2023-12-04 17:18:59 +00:00
|
|
|
sectionLoaded = false
|
|
|
|
if sectionName <> "none"
|
|
|
|
sectionLoaded = addHomeSection(sectionName)
|
|
|
|
end if
|
2023-10-22 22:37:37 +00:00
|
|
|
|
|
|
|
' Count how many sections with data are loaded
|
|
|
|
if sectionLoaded then loadedSections++
|
|
|
|
|
|
|
|
' If 2 sections with data are loaded or we're at the end of the web client section data, consider the home view loaded
|
2023-11-22 19:58:21 +00:00
|
|
|
if not m.global.app_loaded
|
|
|
|
if loadedSections = 2 or i = 6
|
2023-10-22 22:37:37 +00:00
|
|
|
m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring
|
|
|
|
m.global.app_loaded = true
|
|
|
|
end if
|
|
|
|
end if
|
2023-09-30 21:36:16 +00:00
|
|
|
end for
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Favorites isn't an option in Web settings, so we manually add it to the end for now
|
|
|
|
addHomeSection("favorites")
|
2023-11-22 19:58:21 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Start the timer for creating the content rows before we set the cursor size
|
|
|
|
m.loadingTimer.control = "start"
|
|
|
|
end sub
|
2023-11-22 19:58:21 +00:00
|
|
|
|
|
|
|
' onLibrariesLoaded: Handler when LoadLibrariesTask returns data
|
|
|
|
'
|
|
|
|
sub onLibrariesLoaded()
|
|
|
|
' save data for other functions
|
|
|
|
m.libraryData = m.LoadLibrariesTask.content
|
|
|
|
m.LoadLibrariesTask.unobserveField("content")
|
|
|
|
m.LoadLibrariesTask.content = []
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
processUserSections()
|
2023-09-30 21:36:16 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' getOriginalSectionIndex: Gets the index of a section from user settings and adds count of currently known latest media sections
|
|
|
|
'
|
|
|
|
' @param {string} sectionName - Name of section we're looking up
|
|
|
|
'
|
|
|
|
' @return {integer} indicating index of section taking latest media sections into account
|
|
|
|
function getOriginalSectionIndex(sectionName as string) as integer
|
|
|
|
searchSectionName = LCase(sectionName).Replace(" ", "")
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionIndex = 0
|
|
|
|
indexLatestMediaSection = 0
|
2023-10-22 22:37:37 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
for i = 0 to 6
|
|
|
|
settingSectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
|
|
|
|
if settingSectionName = "latestmedia"
|
|
|
|
indexLatestMediaSection = i
|
|
|
|
end if
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
if settingSectionName = searchSectionName
|
|
|
|
sectionIndex = i
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
end for
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' If the latest media section is before the section we're searching for, then we need to account for how many latest media rows there are
|
|
|
|
addLatestMediaSectionCount = (indexLatestMediaSection < sectionIndex)
|
|
|
|
|
|
|
|
if addLatestMediaSectionCount
|
|
|
|
for i = sectionIndex to m.top.content.getChildCount() - 1
|
|
|
|
sectionToTest = m.top.content.getChild(i)
|
|
|
|
if LCase(Left(sectionToTest.title, 6)) = "latest"
|
|
|
|
sectionIndex++
|
|
|
|
end if
|
|
|
|
end for
|
|
|
|
end if
|
|
|
|
|
|
|
|
return sectionIndex
|
|
|
|
end function
|
|
|
|
|
|
|
|
' removeHomeSection: Removes a home section from the home rows
|
|
|
|
'
|
|
|
|
' @param {string} sectionToRemove - Title property of section we're removing
|
|
|
|
sub removeHomeSection(sectionTitleToRemove as string)
|
|
|
|
if not isValid(sectionTitleToRemove) then return
|
|
|
|
|
|
|
|
sectionTitle = LCase(sectionTitleToRemove).Replace(" ", "")
|
|
|
|
if not sectionExists(sectionTitle) then return
|
|
|
|
|
|
|
|
sectionIndexToRemove = getSectionIndex(sectionTitle)
|
2023-11-22 17:14:35 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
m.top.content.removeChildIndex(sectionIndexToRemove)
|
2023-12-03 00:34:46 +00:00
|
|
|
setRowItemSize()
|
2023-11-22 17:14:35 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' setRowItemSize: Loops through all home sections and sets the correct item sizes per row
|
2023-11-22 17:14:35 +00:00
|
|
|
'
|
2023-12-02 04:05:15 +00:00
|
|
|
sub setRowItemSize()
|
|
|
|
if not isValid(m.top.content) then return
|
2023-11-22 17:14:35 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
homeSections = m.top.content.getChildren(-1, 0)
|
|
|
|
newSizeArray = CreateObject("roArray", homeSections.count(), false)
|
|
|
|
|
|
|
|
for i = 0 to homeSections.count() - 1
|
|
|
|
newSizeArray[i] = isValid(homeSections[i].cursorSize) ? homeSections[i].cursorSize : homeRowItemSizes.WIDE_POSTER
|
2023-11-22 17:14:35 +00:00
|
|
|
end for
|
|
|
|
m.top.rowItemSize = newSizeArray
|
2023-12-03 03:10:25 +00:00
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
' If we have processed the expected number of content rows, stop the loading timer and run the complete function
|
|
|
|
if m.expectedRowCount = m.processedRowCount
|
2023-12-03 03:10:25 +00:00
|
|
|
m.loadingTimer.control = "stop"
|
|
|
|
loadingTimerComplete()
|
|
|
|
end if
|
2023-09-30 21:36:16 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' loadingTimerComplete: Event handler for when loading wait time has expired
|
|
|
|
'
|
|
|
|
sub loadingTimerComplete()
|
2023-12-03 03:10:25 +00:00
|
|
|
if not m.top.showRowCounter[0]
|
|
|
|
' Show the row counter to prevent flicker
|
|
|
|
m.top.showRowCounter = [true]
|
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
end sub
|
|
|
|
|
|
|
|
' addHomeSection: Adds a new home section to the home rows.
|
|
|
|
'
|
|
|
|
' @param {string} sectionType - Type of section to add
|
|
|
|
' @return {boolean} indicating if the section was handled
|
|
|
|
function addHomeSection(sectionType as string) as boolean
|
2023-09-30 21:36:16 +00:00
|
|
|
' Poster size library items
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "livetv"
|
|
|
|
createLiveTVRow()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' Poster size library items
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "smalllibrarytiles"
|
|
|
|
createLibraryRow()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' Continue Watching items
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "resume"
|
|
|
|
createContinueWatchingRow()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' Next Up items
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "nextup"
|
|
|
|
createNextUpRow()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' Latest items in each library
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "latestmedia"
|
|
|
|
createLatestInRows()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' Favorite Items
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionType = "favorites"
|
|
|
|
createFavoritesRow()
|
2023-10-22 22:37:37 +00:00
|
|
|
return true
|
2023-09-30 21:36:16 +00:00
|
|
|
end if
|
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
' This section type isn't supported.
|
|
|
|
' Count it as processed since we aren't going to do anything else with it
|
|
|
|
m.processedRowCount++
|
2023-10-22 22:37:37 +00:00
|
|
|
return false
|
|
|
|
end function
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' createLibraryRow: Creates a row displaying the user's libraries
|
|
|
|
'
|
|
|
|
sub createLibraryRow()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2023-09-30 21:36:16 +00:00
|
|
|
' Ensure we have data
|
|
|
|
if not isValidAndNotEmpty(m.libraryData) then return
|
2023-01-10 00:38:50 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("My Media")
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-07 17:01:17 +00:00
|
|
|
' We don't refresh library data, so if section already exists, exit
|
|
|
|
if sectionExists(sectionName)
|
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
|
|
|
row.title = sectionName
|
|
|
|
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.WIDE_POSTER
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
|
|
|
|
for each item in filteredMedia
|
2023-12-02 04:05:15 +00:00
|
|
|
row.appendChild(item)
|
2023-09-30 21:36:16 +00:00
|
|
|
end for
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Row does not exist, insert it into the home view
|
|
|
|
m.top.content.insertChild(row, getOriginalSectionIndex("smalllibrarytiles"))
|
|
|
|
setRowItemSize()
|
2023-09-30 21:36:16 +00:00
|
|
|
end sub
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' createLatestInRows: Creates a row displaying latest items in each of the user's libraries
|
|
|
|
'
|
|
|
|
sub createLatestInRows()
|
2023-09-30 21:36:16 +00:00
|
|
|
' Ensure we have data
|
|
|
|
if not isValidAndNotEmpty(m.libraryData) then return
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
' create a "Latest In" row for each library
|
2023-12-04 17:18:59 +00:00
|
|
|
for each lib in m.filteredLatest
|
2023-09-30 21:36:16 +00:00
|
|
|
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" 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
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' sectionExists: Checks if passed section exists in home row content
|
|
|
|
'
|
|
|
|
' @param {string} sectionTitle - Title of section we're checking for
|
|
|
|
'
|
|
|
|
' @return {boolean} indicating if the section currently exists in the home row content
|
|
|
|
function sectionExists(sectionTitle as string) as boolean
|
|
|
|
if not isValid(sectionTitle) then return false
|
|
|
|
if not isValid(m.top.content) then return false
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
homeSections = m.top.content.getChildren(-1, 0)
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
for each section in homeSections
|
|
|
|
if LCase(section.title).Replace(" ", "") = searchSectionTitle
|
|
|
|
return true
|
|
|
|
end if
|
|
|
|
end for
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
return false
|
|
|
|
end function
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' getSectionIndex: Returns index of requested section in home row content
|
|
|
|
'
|
|
|
|
' @param {string} sectionTitle - Title of section we're checking for
|
|
|
|
'
|
|
|
|
' @return {integer} indicating index of request section
|
|
|
|
function getSectionIndex(sectionTitle as string) as integer
|
|
|
|
if not isValid(sectionTitle) then return false
|
|
|
|
if not isValid(m.top.content) then return false
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
homeSections = m.top.content.getChildren(-1, 0)
|
2023-04-13 19:41:11 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionIndex = homeSections.count()
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
for each section in homeSections
|
|
|
|
if LCase(section.title).Replace(" ", "") = searchSectionTitle
|
|
|
|
sectionIndex = i
|
|
|
|
exit for
|
|
|
|
end if
|
|
|
|
i++
|
|
|
|
end for
|
|
|
|
|
|
|
|
return sectionIndex
|
|
|
|
end function
|
|
|
|
|
|
|
|
' createLiveTVRow: Creates a row displaying the live tv now on section
|
|
|
|
'
|
|
|
|
sub createLiveTVRow()
|
|
|
|
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
|
|
|
|
m.LoadOnNowTask.control = "RUN"
|
|
|
|
end sub
|
|
|
|
|
|
|
|
' createContinueWatchingRow: Creates a row displaying items the user can continue watching
|
|
|
|
'
|
|
|
|
sub createContinueWatchingRow()
|
2023-04-13 19:41:11 +00:00
|
|
|
' Load the Continue Watching Data
|
2023-10-22 22:37:37 +00:00
|
|
|
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
|
|
|
|
m.LoadContinueWatchingTask.control = "RUN"
|
2023-09-30 21:36:16 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' createNextUpRow: Creates a row displaying next episodes up to watch
|
|
|
|
'
|
|
|
|
sub createNextUpRow()
|
|
|
|
sectionName = tr("Next Up") + ">"
|
|
|
|
|
|
|
|
if not sectionExists(sectionName)
|
|
|
|
nextUpRow = m.top.content.CreateChild("HomeRow")
|
|
|
|
nextUpRow.title = sectionName
|
|
|
|
nextUpRow.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
nextUpRow.cursorSize = homeRowItemSizes.WIDE_POSTER
|
2023-11-29 21:06:54 +00:00
|
|
|
end if
|
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
' Load the Next Up Data
|
|
|
|
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
|
|
|
|
m.LoadNextUpTask.control = "RUN"
|
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' createFavoritesRow: Creates a row displaying items from the user's favorites list
|
|
|
|
'
|
|
|
|
sub createFavoritesRow()
|
2023-04-13 19:41:11 +00:00
|
|
|
' Load the Favorites Data
|
|
|
|
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
|
|
|
|
m.LoadFavoritesTask.control = "RUN"
|
2022-05-24 16:23:42 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateHomeRows: Update function exposed to outside components
|
|
|
|
'
|
2021-06-26 10:18:09 +00:00
|
|
|
sub updateHomeRows()
|
2023-12-02 04:05:15 +00:00
|
|
|
' Hide the row counter to prevent flicker. We'll show it once loading timer fires
|
|
|
|
m.top.showRowCounter = [false]
|
2023-11-29 21:06:54 +00:00
|
|
|
processUserSections()
|
2021-06-26 10:18:09 +00:00
|
|
|
end sub
|
2020-03-24 00:45:40 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateFavoritesItems: Processes LoadFavoritesTask content. Removes, Creates, or Updates favorites row as needed
|
|
|
|
'
|
2022-11-05 00:37:54 +00:00
|
|
|
sub updateFavoritesItems()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2022-11-05 00:37:54 +00:00
|
|
|
itemData = m.LoadFavoritesTask.content
|
|
|
|
m.LoadFavoritesTask.unobserveField("content")
|
|
|
|
m.LoadFavoritesTask.content = []
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("Favorites")
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
if not isValidAndNotEmpty(itemData)
|
2023-12-02 04:05:15 +00:00
|
|
|
removeHomeSection(sectionName)
|
2023-09-30 21:36:16 +00:00
|
|
|
return
|
2023-12-02 04:05:15 +00:00
|
|
|
end if
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' remake row using the new data
|
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
|
|
|
row.title = sectionName
|
|
|
|
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.WIDE_POSTER
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
for each item in itemData
|
|
|
|
usePoster = true
|
2022-11-05 00:37:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
if lcase(item.type) = "episode" or lcase(item.type) = "audio" or lcase(item.type) = "musicartist"
|
|
|
|
usePoster = false
|
|
|
|
end if
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
item.usePoster = usePoster
|
|
|
|
item.imageWidth = row.imageWidth
|
|
|
|
row.appendChild(item)
|
|
|
|
end for
|
2023-11-29 21:06:54 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionExists(sectionName)
|
|
|
|
m.top.content.replaceChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
|
|
|
return
|
2022-11-05 00:37:54 +00:00
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
|
|
|
|
m.top.content.insertChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
2022-11-05 00:37:54 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateContinueWatchingItems: Processes LoadContinueWatchingTask content. Removes, Creates, or Updates continue watching row as needed
|
|
|
|
'
|
2023-10-22 22:37:37 +00:00
|
|
|
sub updateContinueWatchingItems()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2023-10-22 22:37:37 +00:00
|
|
|
itemData = m.LoadContinueWatchingTask.content
|
|
|
|
m.LoadContinueWatchingTask.unobserveField("content")
|
|
|
|
m.LoadContinueWatchingTask.content = []
|
2020-03-24 07:37:45 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("Continue Watching")
|
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
if not isValidAndNotEmpty(itemData)
|
2023-12-02 04:05:15 +00:00
|
|
|
removeHomeSection(sectionName)
|
2023-09-30 21:36:16 +00:00
|
|
|
return
|
|
|
|
end if
|
2022-12-10 02:53:00 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("Continue Watching")
|
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
' remake row using the new data
|
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
2023-12-02 04:05:15 +00:00
|
|
|
row.title = sectionName
|
|
|
|
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.WIDE_POSTER
|
2020-03-24 07:37:45 +00:00
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
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
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2023-04-13 19:41:11 +00:00
|
|
|
|
2023-09-30 21:36:16 +00:00
|
|
|
item.usePoster = row.usePoster
|
|
|
|
item.imageWidth = row.imageWidth
|
|
|
|
row.appendChild(item)
|
|
|
|
end for
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Row already exists, replace it with new content
|
|
|
|
if sectionExists(sectionName)
|
|
|
|
m.top.content.replaceChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
|
|
|
return
|
|
|
|
end if
|
|
|
|
|
|
|
|
' Row does not exist, insert it into the home view
|
|
|
|
m.top.content.insertChild(row, getOriginalSectionIndex("resume"))
|
|
|
|
setRowItemSize()
|
2022-05-24 16:23:42 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateNextUpItems: Processes LoadNextUpTask content. Removes, Creates, or Updates next up row as needed
|
|
|
|
'
|
2022-07-12 23:15:59 +00:00
|
|
|
sub updateNextUpItems()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2022-07-12 23:15:59 +00:00
|
|
|
itemData = m.LoadNextUpTask.content
|
|
|
|
m.LoadNextUpTask.unobserveField("content")
|
|
|
|
m.LoadNextUpTask.content = []
|
2023-11-23 13:52:44 +00:00
|
|
|
m.LoadNextUpTask.control = "STOP"
|
2022-05-24 16:23:42 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("Next Up") + " >"
|
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
if not isValidAndNotEmpty(itemData)
|
2023-12-02 04:05:15 +00:00
|
|
|
removeHomeSection(sectionName)
|
2023-09-30 21:36:16 +00:00
|
|
|
return
|
2023-12-02 04:05:15 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
' remake row using the new data
|
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
|
|
|
row.title = tr("Next Up") + " >"
|
|
|
|
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.WIDE_POSTER
|
|
|
|
|
|
|
|
for each item in itemData
|
|
|
|
item.usePoster = row.usePoster
|
|
|
|
item.imageWidth = row.imageWidth
|
|
|
|
row.appendChild(item)
|
|
|
|
end for
|
2022-05-24 16:23:42 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' Row already exists, replace it with new content
|
|
|
|
if sectionExists(sectionName)
|
|
|
|
m.top.content.replaceChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
|
|
|
return
|
2020-03-24 07:37:45 +00:00
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
|
|
|
|
' Row does not exist, insert it into the home view
|
|
|
|
m.top.content.insertChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
2021-06-26 10:18:09 +00:00
|
|
|
end sub
|
2021-07-09 20:08:32 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateLatestItems: Processes LoadItemsTask content. Removes, Creates, or Updates latest in {library} row as needed
|
|
|
|
'
|
|
|
|
' @param {dynamic} msg - LoadItemsTask
|
2021-06-26 10:18:09 +00:00
|
|
|
sub updateLatestItems(msg)
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2021-07-09 20:08:32 +00:00
|
|
|
itemData = msg.GetData()
|
2020-03-24 07:37:45 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
node = msg.getRoSGNode()
|
|
|
|
node.unobserveField("content")
|
2022-07-12 23:15:59 +00:00
|
|
|
node.content = []
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("Latest in") + " " + node.metadata.title + " >"
|
2023-09-30 21:36:16 +00:00
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
if not isValidAndNotEmpty(itemData)
|
2023-09-30 21:36:16 +00:00
|
|
|
removeHomeSection(sectionName)
|
|
|
|
return
|
2023-12-02 04:05:15 +00:00
|
|
|
end if
|
2023-11-11 04:34:19 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
imagesize = homeRowItemSizes.WIDE_POSTER
|
2023-11-11 04:34:19 +00:00
|
|
|
|
2023-12-02 23:30:33 +00:00
|
|
|
if isValid(node.metadata.contentType)
|
|
|
|
if LCase(node.metadata.contentType) = "movies"
|
|
|
|
imagesize = homeRowItemSizes.MOVIE_POSTER
|
|
|
|
else if LCase(node.metadata.contentType) = "music"
|
|
|
|
imagesize = homeRowItemSizes.MUSIC_ALBUM
|
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
end if
|
2023-11-22 17:14:35 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' remake row using new data
|
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
|
|
|
row.title = sectionName
|
|
|
|
row.imageWidth = imagesize[0]
|
|
|
|
row.cursorSize = imagesize
|
2023-12-02 13:29:42 +00:00
|
|
|
row.usePoster = true
|
2023-11-11 04:34:19 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
for each item in itemData
|
|
|
|
item.usePoster = row.usePoster
|
|
|
|
item.imageWidth = row.imageWidth
|
|
|
|
row.appendChild(item)
|
|
|
|
end for
|
2020-03-12 18:33:45 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
if sectionExists(sectionName)
|
|
|
|
' Row already exists, replace it with new content
|
|
|
|
m.top.content.replaceChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
|
|
|
return
|
2023-11-22 23:23:04 +00:00
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
|
|
|
|
m.top.content.insertChild(row, getOriginalSectionIndex("latestmedia"))
|
|
|
|
setRowItemSize()
|
2023-11-22 23:23:04 +00:00
|
|
|
end sub
|
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' updateOnNowItems: Processes LoadOnNowTask content. Removes, Creates, or Updates latest in on now row as needed
|
|
|
|
'
|
2021-12-17 06:18:19 +00:00
|
|
|
sub updateOnNowItems()
|
2023-12-04 17:18:59 +00:00
|
|
|
m.processedRowCount++
|
2021-12-17 06:18:19 +00:00
|
|
|
itemData = m.LoadOnNowTask.content
|
|
|
|
m.LoadOnNowTask.unobserveField("content")
|
2022-07-12 23:15:59 +00:00
|
|
|
m.LoadOnNowTask.content = []
|
2021-12-17 06:18:19 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
sectionName = tr("On Now")
|
|
|
|
|
2023-12-04 17:18:59 +00:00
|
|
|
if not isValidAndNotEmpty(itemData)
|
2023-12-02 04:05:15 +00:00
|
|
|
removeHomeSection(sectionName)
|
2023-09-30 21:36:16 +00:00
|
|
|
return
|
2023-12-02 04:05:15 +00:00
|
|
|
end if
|
2023-11-23 13:52:44 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
' remake row using the new data
|
|
|
|
row = CreateObject("roSGNode", "HomeRow")
|
|
|
|
row.title = tr("On Now")
|
|
|
|
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.WIDE_POSTER
|
2022-07-12 23:15:59 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
for each item in itemData
|
|
|
|
row.usePoster = false
|
2021-12-17 06:18:19 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
if (not isValid(item.thumbnailURL) or item.thumbnailURL = "") and isValid(item.json) and isValid(item.json.imageURL)
|
|
|
|
item.thumbnailURL = item.json.imageURL
|
|
|
|
row.usePoster = true
|
|
|
|
row.imageWidth = homeRowItemSizes.MOVIE_POSTER[0]
|
|
|
|
row.cursorSize = homeRowItemSizes.MOVIE_POSTER
|
|
|
|
end if
|
2023-11-23 13:52:44 +00:00
|
|
|
|
2023-12-02 04:05:15 +00:00
|
|
|
item.usePoster = row.usePoster
|
|
|
|
item.imageWidth = row.imageWidth
|
|
|
|
row.appendChild(item)
|
|
|
|
end for
|
|
|
|
|
|
|
|
' Row already exists, replace it with new content
|
|
|
|
if sectionExists(sectionName)
|
|
|
|
m.top.content.replaceChild(row, getSectionIndex(sectionName))
|
|
|
|
setRowItemSize()
|
|
|
|
return
|
2020-03-24 07:37:45 +00:00
|
|
|
end if
|
2023-12-02 04:05:15 +00:00
|
|
|
|
|
|
|
' Row does not exist, insert it into the home view
|
|
|
|
m.top.content.insertChild(row, getOriginalSectionIndex("livetv"))
|
|
|
|
setRowItemSize()
|
2020-03-24 07:31:36 +00:00
|
|
|
end sub
|
|
|
|
|
2021-06-26 10:18:09 +00:00
|
|
|
sub itemSelected()
|
2023-11-23 13:52:44 +00:00
|
|
|
m.selectedRowItem = m.top.rowItemSelected
|
2023-11-22 23:23:04 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
|
2023-05-07 01:26:02 +00:00
|
|
|
|
|
|
|
'Prevent the selected item event from double firing
|
|
|
|
m.top.selectedItem = invalid
|
2021-06-26 10:18:09 +00:00
|
|
|
end sub
|
2020-03-12 18:33:45 +00:00
|
|
|
|
2020-04-04 22:24:47 +00:00
|
|
|
function onKeyEvent(key as string, press as boolean) as boolean
|
2021-07-09 20:08:32 +00:00
|
|
|
if press
|
|
|
|
if key = "play"
|
2023-09-16 21:18:03 +00:00
|
|
|
print "play was pressed from homerow"
|
2021-07-09 20:08:32 +00:00
|
|
|
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
|
2023-09-16 21:18:03 +00:00
|
|
|
if isValid(itemToPlay)
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.quickPlayNode = itemToPlay
|
|
|
|
end if
|
2023-09-16 21:18:03 +00:00
|
|
|
return true
|
|
|
|
else if key = "replay"
|
2022-06-25 21:29:24 +00:00
|
|
|
m.top.jumpToRowItem = [m.top.rowItemFocused[0], 0]
|
2023-09-16 21:18:03 +00:00
|
|
|
return true
|
2022-06-25 21:29:24 +00:00
|
|
|
end if
|
2020-12-08 08:39:58 +00:00
|
|
|
end if
|
2023-09-16 21:18:03 +00:00
|
|
|
return false
|
2020-04-04 22:24:47 +00:00
|
|
|
end function
|
2020-12-06 04:59:32 +00:00
|
|
|
|
|
|
|
function filterNodeArray(nodeArray as object, nodeKey as string, excludeArray as object) as object
|
2021-07-09 20:08:32 +00:00
|
|
|
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
|
2020-12-06 04:59:32 +00:00
|
|
|
end for
|
2021-07-09 20:08:32 +00:00
|
|
|
return newNodeArray
|
2022-05-30 12:57:40 +00:00
|
|
|
end function
|