jf-roku/docs/api/components_home_HomeRows.bs.html

685 lines
58 KiB
HTML
Raw Normal View History

2023-11-11 13:41:20 +00:00
<!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: components/home/HomeRows.bs</title><!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
2023-12-05 16:56:00 +00:00
<![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(baseURL=(baseURL="https://jellyfin.github.io/jellyfin-roku/").replace(/https?:\/\//i,"")).substr(baseURL.indexOf("/"))</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d=
import "pkg:/source/constants/HomeRowItemSizes.bs"
const LOADING_WAIT_TIME = 2
2023-10-06 03:18:36 +00:00
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]
2023-12-05 16:56:00 +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")
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
m.loadingTimer = createObject("roSGNode", "Timer")
m.loadingTimer.duration = LOADING_WAIT_TIME
m.loadingTimer.observeField("fire", "loadingTimerComplete")
2023-10-27 02:20:25 +00:00
2023-10-06 03:18:36 +00:00
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")
2023-12-05 16:56:00 +00:00
' set up task nodes for other rows
2023-10-27 02:20:25 +00:00
m.LoadContinueWatchingTask = createObject("roSGNode", "LoadItemsTask")
m.LoadContinueWatchingTask.itemsToLoad = "continue"
2023-10-06 03:18:36 +00:00
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]
2023-12-05 16:56:00 +00:00
' Default size to wide poster, the most used size
m.top.rowItemSize = homeRowItemSizes.WIDE_POSTER
2023-10-06 03:18:36 +00:00
m.top.visible = true
end sub
2023-12-05 16:56:00 +00:00
' processUserSections: Loop through user's chosen home section settings and generate the content for each row
'
sub processUserSections()
m.expectedRowCount = 1 ' the favorites row is hardcoded to always show atm
m.processedRowCount = 0
2023-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
' 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 &lt;> "boxsets" and latestLibrary.collectionType &lt;> "livetv" and latestLibrary.json.CollectionType &lt;> "Program"
m.expectedRowCount++
end if
end for
else if sectionName &lt;> "none"
m.expectedRowCount++
end if
end for
2023-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
' Add home sections in order based on user settings
loadedSections = 0
2023-10-27 02:20:25 +00:00
for i = 0 to 6
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
2023-12-05 16:56:00 +00:00
sectionLoaded = false
if sectionName &lt;> "none"
sectionLoaded = addHomeSection(sectionName)
end if
2023-10-27 02:20:25 +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-12-05 16:56:00 +00:00
if not m.global.app_loaded
if loadedSections = 2 or i = 6
2023-10-27 02:20:25 +00:00
m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring
m.global.app_loaded = true
end if
end if
end for
2023-12-05 16:56:00 +00:00
' Favorites isn't an option in Web settings, so we manually add it to the end for now
addHomeSection("favorites")
' Start the timer for creating the content rows before we set the cursor size
m.loadingTimer.control = "start"
end sub
' 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-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
processUserSections()
2023-10-27 02:20:25 +00:00
end sub
2023-12-05 16:56:00 +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-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
sectionIndex = 0
indexLatestMediaSection = 0
2023-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +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-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
if settingSectionName = searchSectionName
sectionIndex = i
2023-10-27 02:20:25 +00:00
end if
end for
2023-12-05 16:56:00 +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 &lt; 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-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
m.top.content.removeChildIndex(sectionIndexToRemove)
setRowItemSize()
end sub
' setRowItemSize: Loops through all home sections and sets the correct item sizes per row
'
sub setRowItemSize()
if not isValid(m.top.content) then return
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
end for
m.top.rowItemSize = newSizeArray
' If we have processed the expected number of content rows, stop the loading timer and run the complete function
if m.expectedRowCount = m.processedRowCount
m.loadingTimer.control = "stop"
loadingTimerComplete()
end if
end sub
' loadingTimerComplete: Event handler for when loading wait time has expired
'
sub loadingTimerComplete()
if not m.top.showRowCounter[0]
' Show the row counter to prevent flicker
m.top.showRowCounter = [true]
end if
2023-10-27 02:20:25 +00:00
end sub
2023-12-05 16:56:00 +00:00
' 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-10-27 02:20:25 +00:00
' Poster size library items
2023-12-05 16:56:00 +00:00
if sectionType = "livetv"
createLiveTVRow()
2023-10-27 02:20:25 +00:00
return true
end if
' Poster size library items
2023-12-05 16:56:00 +00:00
if sectionType = "smalllibrarytiles"
createLibraryRow()
2023-10-27 02:20:25 +00:00
return true
end if
' Continue Watching items
2023-12-05 16:56:00 +00:00
if sectionType = "resume"
createContinueWatchingRow()
2023-10-27 02:20:25 +00:00
return true
end if
' Next Up items
2023-12-05 16:56:00 +00:00
if sectionType = "nextup"
createNextUpRow()
2023-10-27 02:20:25 +00:00
return true
end if
' Latest items in each library
2023-12-05 16:56:00 +00:00
if sectionType = "latestmedia"
createLatestInRows()
2023-10-27 02:20:25 +00:00
return true
end if
' Favorite Items
2023-12-05 16:56:00 +00:00
if sectionType = "favorites"
createFavoritesRow()
2023-10-27 02:20:25 +00:00
return true
end if
2023-12-05 16:56:00 +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-27 02:20:25 +00:00
return false
end function
2023-12-05 16:56:00 +00:00
' createLibraryRow: Creates a row displaying the user's libraries
'
sub createLibraryRow()
m.processedRowCount++
2023-10-27 02:20:25 +00:00
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
sectionName = tr("My Media")
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
row = CreateObject("roSGNode", "HomeRow")
row.title = sectionName
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
row.cursorSize = homeRowItemSizes.WIDE_POSTER
2023-10-06 03:18:36 +00:00
2023-10-27 02:20:25 +00:00
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
for each item in filteredMedia
2023-12-05 16:56:00 +00:00
row.appendChild(item)
2023-10-27 02:20:25 +00:00
end for
2023-12-05 16:56:00 +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("smalllibrarytiles"))
setRowItemSize()
2023-10-27 02:20:25 +00:00
end sub
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
' createLatestInRows: Creates a row displaying latest items in each of the user's libraries
'
sub createLatestInRows()
2023-10-27 02:20:25 +00:00
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
2023-10-06 03:18:36 +00:00
2023-10-27 02:20:25 +00:00
' create a "Latest In" row for each library
2023-12-05 16:56:00 +00:00
for each lib in m.filteredLatest
2023-10-27 02:20:25 +00:00
if lib.collectionType &lt;> "boxsets" and lib.collectionType &lt;> "livetv" and lib.json.CollectionType &lt;> "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-05 16:56:00 +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-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
homeSections = m.top.content.getChildren(-1, 0)
for each section in homeSections
if LCase(section.title).Replace(" ", "") = searchSectionTitle
return true
end if
end for
return false
end function
' 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
searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
homeSections = m.top.content.getChildren(-1, 0)
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()
2023-10-27 02:20:25 +00:00
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end sub
2023-12-05 16:56:00 +00:00
' createContinueWatchingRow: Creates a row displaying items the user can continue watching
'
sub createContinueWatchingRow()
2023-10-06 03:18:36 +00:00
' Load the Continue Watching Data
2023-10-27 02:20:25 +00:00
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
m.LoadContinueWatchingTask.control = "RUN"
end sub
2023-12-05 16:56:00 +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
end if
2023-10-27 02:20:25 +00:00
' Load the Next Up Data
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
m.LoadNextUpTask.control = "RUN"
end sub
2023-12-05 16:56:00 +00:00
' createFavoritesRow: Creates a row displaying items from the user's favorites list
'
sub createFavoritesRow()
2023-10-06 03:18:36 +00:00
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
end sub
2023-12-05 16:56:00 +00:00
' updateHomeRows: Update function exposed to outside components
'
2023-10-06 03:18:36 +00:00
sub updateHomeRows()
2023-12-05 16:56:00 +00:00
' Hide the row counter to prevent flicker. We'll show it once loading timer fires
m.top.showRowCounter = [false]
processUserSections()
2023-10-06 03:18:36 +00:00
end sub
2023-12-05 16:56:00 +00:00
' updateFavoritesItems: Processes LoadFavoritesTask content. Removes, Creates, or Updates favorites row as needed
'
2023-10-06 03:18:36 +00:00
sub updateFavoritesItems()
2023-12-05 16:56:00 +00:00
m.processedRowCount++
2023-10-06 03:18:36 +00:00
itemData = m.LoadFavoritesTask.content
m.LoadFavoritesTask.unobserveField("content")
m.LoadFavoritesTask.content = []
2023-12-05 16:56:00 +00:00
sectionName = tr("Favorites")
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
2023-10-27 02:20:25 +00:00
return
2023-12-05 16:56:00 +00:00
end if
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +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
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
for each item in itemData
usePoster = true
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if lcase(item.type) = "episode" or lcase(item.type) = "audio" or lcase(item.type) = "musicartist"
usePoster = false
end if
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
item.usePoster = usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
2023-10-27 02:20:25 +00:00
2023-12-05 16:56:00 +00:00
if sectionExists(sectionName)
m.top.content.replaceChild(row, getSectionIndex(sectionName))
setRowItemSize()
return
2023-10-06 03:18:36 +00:00
end if
2023-12-05 16:56:00 +00:00
m.top.content.insertChild(row, getSectionIndex(sectionName))
setRowItemSize()
2023-10-06 03:18:36 +00:00
end sub
2023-12-05 16:56:00 +00:00
' updateContinueWatchingItems: Processes LoadContinueWatchingTask content. Removes, Creates, or Updates continue watching row as needed
'
2023-10-27 02:20:25 +00:00
sub updateContinueWatchingItems()
2023-12-05 16:56:00 +00:00
m.processedRowCount++
2023-10-27 02:20:25 +00:00
itemData = m.LoadContinueWatchingTask.content
m.LoadContinueWatchingTask.unobserveField("content")
m.LoadContinueWatchingTask.content = []
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
sectionName = tr("Continue Watching")
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
2023-10-27 02:20:25 +00:00
return
end if
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
sectionName = tr("Continue Watching")
2023-10-27 02:20:25 +00:00
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
2023-12-05 16:56:00 +00:00
row.title = sectionName
row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
row.cursorSize = homeRowItemSizes.WIDE_POSTER
2023-10-06 03:18:36 +00:00
2023-10-27 02:20:25 +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
2023-10-06 03:18:36 +00:00
end if
2023-10-27 02:20:25 +00:00
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
2023-12-05 16:56:00 +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()
2023-10-06 03:18:36 +00:00
end sub
2023-12-05 16:56:00 +00:00
' updateNextUpItems: Processes LoadNextUpTask content. Removes, Creates, or Updates next up row as needed
'
2023-10-06 03:18:36 +00:00
sub updateNextUpItems()
2023-12-05 16:56:00 +00:00
m.processedRowCount++
2023-10-06 03:18:36 +00:00
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
m.LoadNextUpTask.content = []
2023-12-05 16:56:00 +00:00
m.LoadNextUpTask.control = "STOP"
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
sectionName = tr("Next Up") + " >"
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
2023-10-27 02:20:25 +00:00
return
2023-10-06 03:18:36 +00:00
end if
2023-12-05 16:56:00 +00:00
' 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
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
for each item in itemData
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
' Row already exists, replace it with new content
if sectionExists(sectionName)
m.top.content.replaceChild(row, getSectionIndex(sectionName))
setRowItemSize()
return
end if
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
' Row does not exist, insert it into the home view
m.top.content.insertChild(row, getSectionIndex(sectionName))
setRowItemSize()
2023-10-06 03:18:36 +00:00
end sub
2023-12-05 16:56:00 +00:00
' updateLatestItems: Processes LoadItemsTask content. Removes, Creates, or Updates latest in {library} row as needed
'
' @param {dynamic} msg - LoadItemsTask
2023-10-06 03:18:36 +00:00
sub updateLatestItems(msg)
2023-12-05 16:56:00 +00:00
m.processedRowCount++
2023-10-06 03:18:36 +00:00
itemData = msg.GetData()
node = msg.getRoSGNode()
node.unobserveField("content")
node.content = []
2023-12-05 16:56:00 +00:00
sectionName = tr("Latest in") + " " + node.metadata.title + " >"
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if not isValidAndNotEmpty(itemData)
2023-10-27 02:20:25 +00:00
removeHomeSection(sectionName)
return
2023-12-05 16:56:00 +00:00
end if
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
imagesize = homeRowItemSizes.WIDE_POSTER
2023-11-11 13:47:32 +00:00
2023-12-05 16:56:00 +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
2023-11-11 13:47:32 +00:00
end if
2023-12-05 16:56:00 +00:00
end if
2023-11-11 13:47:32 +00:00
2023-12-05 16:56:00 +00:00
' remake row using new data
row = CreateObject("roSGNode", "HomeRow")
row.title = sectionName
row.imageWidth = imagesize[0]
row.cursorSize = imagesize
row.usePoster = true
2023-11-11 13:47:32 +00:00
2023-12-05 16:56:00 +00:00
for each item in itemData
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
end for
2023-11-11 13:47:32 +00:00
2023-12-05 16:56:00 +00:00
if sectionExists(sectionName)
' Row already exists, replace it with new content
m.top.content.replaceChild(row, getSectionIndex(sectionName))
setRowItemSize()
2023-11-11 13:47:32 +00:00
return
2023-10-06 03:18:36 +00:00
end if
2023-12-05 16:56:00 +00:00
m.top.content.insertChild(row, getOriginalSectionIndex("latestmedia"))
setRowItemSize()
2023-10-06 03:18:36 +00:00
end sub
2023-12-05 16:56:00 +00:00
' updateOnNowItems: Processes LoadOnNowTask content. Removes, Creates, or Updates latest in on now row as needed
'
2023-10-06 03:18:36 +00:00
sub updateOnNowItems()
2023-12-05 16:56:00 +00:00
m.processedRowCount++
2023-10-06 03:18:36 +00:00
itemData = m.LoadOnNowTask.content
m.LoadOnNowTask.unobserveField("content")
m.LoadOnNowTask.content = []
2023-12-05 16:56:00 +00:00
sectionName = tr("On Now")
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
2023-10-27 02:20:25 +00:00
return
2023-10-06 03:18:36 +00:00
end if
2023-12-05 16:56:00 +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
2023-10-06 03:18:36 +00:00
2023-12-05 16:56:00 +00:00
for each item in itemData
row.usePoster = false
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
2023-10-06 03:18:36 +00:00
end if
2023-12-05 16:56:00 +00:00
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
2023-10-06 03:18:36 +00:00
end for
2023-12-05 16:56:00 +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("livetv"))
setRowItemSize()
2023-10-06 03:18:36 +00:00
end sub
sub itemSelected()
2023-12-05 16:56:00 +00:00
m.selectedRowItem = m.top.rowItemSelected
2023-10-06 03:18:36 +00:00
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
if press
if key = "play"
2023-10-28 21:26:12 +00:00
print "play was pressed from homerow"
2023-10-06 03:18:36 +00:00
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
2023-10-28 21:26:12 +00:00
if isValid(itemToPlay)
2023-10-06 03:18:36 +00:00
m.top.quickPlayNode = itemToPlay
end if
2023-10-28 21:26:12 +00:00
return true
else if key = "replay"
2023-10-06 03:18:36 +00:00
m.top.jumpToRowItem = [m.top.rowItemFocused[0], 0]
2023-10-28 21:26:12 +00:00
return true
2023-10-06 03:18:36 +00:00
end if
end if
2023-10-28 21:26:12 +00:00
return false
2023-10-06 03:18:36 +00:00
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
2023-12-05 16:56:00 +00:00
</code></pre></article></section><footer class="footer" id="PeOAagUepe"><div class="wrapper"><span class="jsdoc-message">Automatically generated using <a href="https://github.com/jsdoc/jsdoc" target="_blank">JSDoc</a> and the <a href="https://github.com/ankitskvmdam/clean-jsdoc-theme" target="_blank">clean-jsdoc-theme</a>.</span></div></footer></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><a href="/" class="sidebar-title sidebar-title-anchor">jellyfin-roku Code Documentation</a><div class="mobile-nav-links"><div class="external-link navbar-item"><a id="jellyfin-link-mobile" href="https://jellyfin.org/" target="_blank">Jellyfin</a></div><div class="external-link navbar-item"><a id="github-link-mobile" href="https://github.com/jellyfin/jellyfin-roku" target="_blank">GitHub</a></div><div class="external-link navbar-item"><a id="forum-link-mobile" href="https://forum.jellyfin.org/f-roku-development" target="_blank">Forum</a></div><div class="external-link navbar-item"><a id="matrix-link-mobile" href="https://matrix.to/#/#jellyfin-dev-roku:matrix.org" target="_blank">Matrix</a></div></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-AlbumData.html">AlbumData</a></div><div class="sidebar-section-children"><a href="module-AlbumGrid.html">AlbumGrid</a></div><div class="sidebar-section-children"><a href="module-AlbumTrackList.html">AlbumTrackList</a></div><div class="sidebar-section-children"><a href="module-AlbumView.html">AlbumView</a></div><div class="sidebar-section-children"><a href="module-Alpha.html">Alpha</a></div><div class="sidebar-section-children"><a href="module-ArtistView.html">ArtistView</a></div><div class="sidebar-section-children"><a href="module-AudioPlayer.html">AudioPlayer</a></div><div class="sidebar-section-children"><a href="module-AudioPlayerView.html">AudioPlayerView</a></div><div class="sidebar-section-children"><a href="module-AudioTrackListItem.html">AudioTrackListItem</a></div><div class="sidebar-section-children"><a href="module-ButtonGroupHoriz.html">ButtonGroupHoriz</a></div><div class="sidebar-section-children"><a href="module-ButtonGroupVert.html">ButtonGroupVert</a></div><div class="sidebar-section-children"><a href="module-ChannelData.html">ChannelData</a></div><div class="sidebar-section-children"><a href="module-Clock.html">Clock</a></div><div class="sidebar-section-children"><a href="module-CollectionData.html">CollectionData</a></div><div class="sidebar-section-children"><a href="module-ConfigData.html">ConfigData</a></div><div class="sidebar-section-children"><a href="module-ConfigItem.html">ConfigItem</a></div><div class="sidebar-section-children"><a href="module-ConfigList.html">ConfigList</a></div><div class="sidebar-section-children"><a href="module-ExtrasItem.html">ExtrasItem</a></div><div class="sidebar-section-children"><a href="module-ExtrasRowList.html">ExtrasRowList</a></div><div class="sidebar-section-children"><a href="module-FavoriteItemsTask.html">FavoriteItemsTask</a></div><div class="sidebar-section-children"><a href="module-Folder