From ed55fafeb53883e86e33fc39849d24c5c3d3318e Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 09:34:25 -0500
Subject: [PATCH 01/20] Fix home image size
Fixes #1493
---
components/home/HomeRows.bs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 100a41b06..1ae7b93a7 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -188,7 +188,14 @@ sub createLatestInRows(content as dynamic, sizeArray as dynamic)
m.homeSectionIndexes.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), m.homeSectionIndexes.count)
m.homeSectionIndexes.count++
- sizeArray.Push([464, 331])
+
+ if LCase(lib.collectionType) = "movies"
+ sizeArray.Push([188, 331])
+ else if LCase(lib.collectionType) = "music"
+ sizeArray.Push([261, 331])
+ else
+ sizeArray.Push([464, 331])
+ end if
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
@@ -482,7 +489,6 @@ sub updateLatestItems(msg)
m.homeSectionIndexes.AddReplace(sectionName, rowIndex)
m.top.content.insertChild(row, rowIndex)
- updateSizeArray(itemSize, rowIndex)
return
end if
From 0a7d74d291f79d38843c09f1795b5eb3763defea Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 11:05:20 -0500
Subject: [PATCH 02/20] Revert "Fix home image size"
This reverts commit ed55fafeb53883e86e33fc39849d24c5c3d3318e.
---
components/home/HomeRows.bs | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 1ae7b93a7..100a41b06 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -188,14 +188,7 @@ sub createLatestInRows(content as dynamic, sizeArray as dynamic)
m.homeSectionIndexes.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), m.homeSectionIndexes.count)
m.homeSectionIndexes.count++
-
- if LCase(lib.collectionType) = "movies"
- sizeArray.Push([188, 331])
- else if LCase(lib.collectionType) = "music"
- sizeArray.Push([261, 331])
- else
- sizeArray.Push([464, 331])
- end if
+ sizeArray.Push([464, 331])
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
@@ -489,6 +482,7 @@ sub updateLatestItems(msg)
m.homeSectionIndexes.AddReplace(sectionName, rowIndex)
m.top.content.insertChild(row, rowIndex)
+ updateSizeArray(itemSize, rowIndex)
return
end if
From 35dfa54a29e39cc0fd8666c74d11e21579d5ab96 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 12:14:35 -0500
Subject: [PATCH 03/20] Rework how we keep track of row item sizes
---
components/home/HomeRows.bs | 200 +++++++++++++++++++-----------------
1 file changed, 103 insertions(+), 97 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 100a41b06..56ebdec7e 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -12,9 +12,7 @@ sub init()
m.top.rowLabelOffset = [0, 20]
m.top.showRowCounter = [true]
- m.homeSectionIndexes = {
- count: 0
- }
+ m.homeSections = {}
updateSize()
@@ -67,13 +65,12 @@ sub onLibrariesLoaded()
m.LoadLibrariesTask.content = []
content = CreateObject("roSGNode", "ContentNode")
- sizeArray = []
loadedSections = 0
' Add sections in order based on user settings
for i = 0 to 6
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
- sectionLoaded = addHomeSection(content, sizeArray, sectionName)
+ sectionLoaded = addHomeSection(content, sectionName)
' Count how many sections with data are loaded
if sectionLoaded then loadedSections++
@@ -88,9 +85,10 @@ sub onLibrariesLoaded()
end for
' Favorites isn't an option on Web settings, so we must manually add it for now
- addHomeSection(content, sizeArray, "favorites")
+ addHomeSection(content, "favorites")
+
+ setRowItemSizes()
- m.top.rowItemSize = sizeArray
m.top.content = content
end sub
@@ -98,57 +96,71 @@ end sub
sub removeHomeSection(sectionType as string)
sectionName = LCase(sectionType)
- removedSectionIndex = m.homeSectionIndexes[sectionName]
+ removedSection = m.homeSections[sectionName]
- if not isValid(removedSectionIndex) then return
+ if not isValid(removedSection) then return
+ if not isValid(removedSection.index) then return
- for each section in m.homeSectionIndexes
- if m.homeSectionIndexes[section] > removedSectionIndex
- m.homeSectionIndexes[section]--
+ for each section in m.homeSections
+ if m.homeSections[section].index > removedSection.index
+ m.homeSections[section].index--
end if
end for
- m.homeSectionIndexes.Delete(sectionName)
+ m.homeSections.Delete(sectionName)
+ m.top.content.removeChildIndex(removedSection.index)
+
+ setRowItemSizes()
+end sub
+
+' setRowItemSizes: Loops through all home sections and sets the correct item sizes per row
+'
+sub setRowItemSizes()
+ newSizeArray = CreateObject("roArray", m.homeSections.count(), false)
+
+ for each section in m.homeSections
+ newSizeArray[m.homeSections[section].index] = m.homeSections[section].imagesize
+ end for
- m.top.content.removeChildIndex(removedSectionIndex)
+ m.top.rowItemSize = newSizeArray
end sub
' Adds a new home section to the home rows.
' Returns a boolean indicating whether the section was handled.
-function addHomeSection(content as dynamic, sizeArray as dynamic, sectionName as string) as boolean
+function addHomeSection(content as dynamic, sectionName as string) as boolean
' Poster size library items
if sectionName = "livetv"
- createLiveTVRow(content, sizeArray)
+ createLiveTVRow(content)
return true
end if
' Poster size library items
if sectionName = "smalllibrarytiles"
- createLibraryRow(content, sizeArray)
+ createLibraryRow(content)
return true
end if
' Continue Watching items
if sectionName = "resume"
- createContinueWatchingRow(content, sizeArray)
+ createContinueWatchingRow(content)
return true
end if
' Next Up items
if sectionName = "nextup"
- createNextUpRow(content, sizeArray)
+ createNextUpRow(content)
return true
end if
' Latest items in each library
if sectionName = "latestmedia"
- createLatestInRows(content, sizeArray)
+ createLatestInRows(content)
return true
end if
' Favorite Items
if sectionName = "favorites"
- createFavoritesRow(content, sizeArray)
+ createFavoritesRow(content)
return true
end if
@@ -156,17 +168,17 @@ function addHomeSection(content as dynamic, sizeArray as dynamic, sectionName as
end function
' Create a row displaying the user's libraries
-sub createLibraryRow(content as dynamic, sizeArray as dynamic)
+sub createLibraryRow(content as dynamic)
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
mediaRow = content.CreateChild("HomeRow")
mediaRow.title = tr("My Media")
- m.homeSectionIndexes.AddReplace("library", m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
-
- sizeArray.push([464, 331])
+ m.homeSections.AddReplace("library", {
+ imageSize: [464, 331],
+ index: m.homeSections.count()
+ })
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
for each item in filteredMedia
@@ -175,7 +187,7 @@ sub createLibraryRow(content as dynamic, sizeArray as dynamic)
end sub
' Create a row displaying latest items in each of the user's libraries
-sub createLatestInRows(content as dynamic, sizeArray as dynamic)
+sub createLatestInRows(content as dynamic)
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
@@ -186,9 +198,18 @@ sub createLatestInRows(content as dynamic, sizeArray as dynamic)
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
- m.homeSectionIndexes.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
- sizeArray.Push([464, 331])
+ imagesize = [464, 331]
+
+ if LCase(lib.collectionType) = "movies"
+ imagesize = [188, 331]
+ else if LCase(lib.collectionType) = "music"
+ imagesize = [261, 331]
+ end if
+
+ m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
+ imageSize: imagesize,
+ index: m.homeSections.count()
+ })
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
@@ -205,24 +226,26 @@ sub createLatestInRows(content as dynamic, sizeArray as dynamic)
end sub
' Create a row displaying the live tv now on section
-sub createLiveTVRow(content as dynamic, sizeArray as dynamic)
+sub createLiveTVRow(content as dynamic)
contentRow = content.CreateChild("HomeRow")
contentRow.title = tr("On Now")
- m.homeSectionIndexes.AddReplace("livetv", m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
- sizeArray.push([464, 331])
+ m.homeSections.AddReplace("livetv", {
+ imageSize: [464, 331],
+ index: m.homeSections.count()
+ })
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end sub
' Create a row displaying items the user can continue watching
-sub createContinueWatchingRow(content as dynamic, sizeArray as dynamic)
+sub createContinueWatchingRow(content as dynamic)
continueWatchingRow = content.CreateChild("HomeRow")
continueWatchingRow.title = tr("Continue Watching")
- m.homeSectionIndexes.AddReplace("resume", m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
- sizeArray.push([464, 331])
+ m.homeSections.AddReplace("resume", {
+ imageSize: [464, 331],
+ index: m.homeSections.count()
+ })
' Load the Continue Watching Data
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
@@ -230,12 +253,13 @@ sub createContinueWatchingRow(content as dynamic, sizeArray as dynamic)
end sub
' Create a row displaying next episodes up to watch
-sub createNextUpRow(content as dynamic, sizeArray as dynamic)
+sub createNextUpRow(content as dynamic)
nextUpRow = content.CreateChild("HomeRow")
nextUpRow.title = tr("Next Up >")
- m.homeSectionIndexes.AddReplace("nextup", m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
- sizeArray.push([464, 331])
+ m.homeSections.AddReplace("nextup", {
+ imageSize: [464, 331],
+ index: m.homeSections.count()
+ })
' Load the Next Up Data
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
@@ -243,13 +267,14 @@ sub createNextUpRow(content as dynamic, sizeArray as dynamic)
end sub
' Create a row displaying items from the user's favorites list
-sub createFavoritesRow(content as dynamic, sizeArray as dynamic)
+sub createFavoritesRow(content as dynamic)
favoritesRow = content.CreateChild("HomeRow")
favoritesRow.title = tr("Favorites")
- sizeArray.Push([464, 331])
- m.homeSectionIndexes.AddReplace("favorites", m.homeSectionIndexes.count)
- m.homeSectionIndexes.count++
+ m.homeSections.AddReplace("favorites", {
+ imageSize: [464, 331],
+ index: m.homeSections.count()
+ })
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
@@ -259,25 +284,25 @@ end sub
' Update home row data
sub updateHomeRows()
' If resume section exists, reload row's data
- if m.homeSectionIndexes.doesExist("resume")
+ if m.homeSections.doesExist("resume")
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
m.LoadContinueWatchingTask.control = "RUN"
end if
' If next up section exists, reload row's data
- if m.homeSectionIndexes.doesExist("nextup")
+ if m.homeSections.doesExist("nextup")
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
m.LoadNextUpTask.control = "RUN"
end if
' If favorites section exists, reload row's data
- if m.homeSectionIndexes.doesExist("favorites")
+ if m.homeSections.doesExist("favorites")
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
end if
' If live tv's on now section exists, reload row's data
- if m.homeSectionIndexes.doesExist("livetv")
+ if m.homeSections.doesExist("livetv")
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end if
@@ -285,7 +310,7 @@ sub updateHomeRows()
' If latest in library section exists, reload row's data
hasLatestHomeSection = false
- for each section in m.homeSectionIndexes
+ for each section in m.homeSections
if LCase(Left(section, 6)) = "latest"
hasLatestHomeSection = true
exit for
@@ -295,6 +320,7 @@ sub updateHomeRows()
if hasLatestHomeSection
updateLatestInRows()
end if
+
end sub
sub updateFavoritesItems()
@@ -304,7 +330,7 @@ sub updateFavoritesItems()
if itemData = invalid then return
- rowIndex = m.homeSectionIndexes.favorites
+ rowIndex = m.homeSections.favorites.index
if itemData.count() < 1
removeHomeSection("favorites")
@@ -359,7 +385,7 @@ sub updateContinueWatchingItems()
end for
' replace the old row
- m.top.content.replaceChild(row, m.homeSectionIndexes.resume)
+ m.top.content.replaceChild(row, m.homeSections.resume.index)
end sub
sub updateNextUpItems()
@@ -383,7 +409,7 @@ sub updateNextUpItems()
end for
' replace the old row
- m.top.content.replaceChild(row, m.homeSectionIndexes.nextup)
+ m.top.content.replaceChild(row, m.homeSections.nextup.index)
end if
end sub
@@ -449,22 +475,23 @@ sub updateLatestItems(msg)
row.appendChild(item)
end for
- rowIndex = m.homeSectionIndexes[sectionName]
+ if isValid(m.homeSections[sectionName])
+ rowIndex = m.homeSections[sectionName].index
- ' Replace the old row
- if isValid(rowIndex)
- updateSizeArray(itemSize, rowIndex, "replace")
- m.top.content.replaceChild(row, rowIndex)
- return
+ ' Replace the old row
+ if isValid(rowIndex)
+ m.top.content.replaceChild(row, rowIndex)
+ return
+ end if
end if
' Determine highest index of a Lastest In section so we can append the new section after it
highestLatestHomeSectionIndex = 0
- for each section in m.homeSectionIndexes
+ for each section in m.homeSections
if LCase(Left(section, 6)) = "latest"
- if m.homeSectionIndexes[section] > highestLatestHomeSectionIndex
- highestLatestHomeSectionIndex = m.homeSectionIndexes[section]
+ if m.homeSections[section].index > highestLatestHomeSectionIndex
+ highestLatestHomeSectionIndex = m.homeSections[section].index
end if
end if
end for
@@ -473,16 +500,21 @@ sub updateLatestItems(msg)
rowIndex = highestLatestHomeSectionIndex + 1
' Advance all the indexes greater than or equal than our new row
- for each section in m.homeSectionIndexes
- if m.homeSectionIndexes[section] >= rowIndex
- m.homeSectionIndexes[section]++
+ for each section in m.homeSections
+ if m.homeSections[section].index >= rowIndex
+ m.homeSections[section].index++
end if
end for
- m.homeSectionIndexes.AddReplace(sectionName, rowIndex)
+ m.homeSections.AddReplace(sectionName, {
+ imageSize: itemSize,
+ index: rowIndex
+ })
m.top.content.insertChild(row, rowIndex)
- updateSizeArray(itemSize, rowIndex)
+
+ ' We've inserted a new row, we must set the row sizes again to ensure they're correct
+ setRowItemSizes()
return
end if
@@ -502,7 +534,7 @@ sub updateOnNowItems()
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("On Now")
- itemSize = [464, 331]
+ 'itemSize = [464, 331]
row.imageWidth = 464
for each item in itemData
row.usePoster = false
@@ -510,7 +542,7 @@ sub updateOnNowItems()
item.thumbnailURL = item.json.imageURL
row.usePoster = true
row.imageWidth = 180
- itemSize = [188, 331]
+ 'itemSize = [188, 331]
end if
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
@@ -518,35 +550,9 @@ sub updateOnNowItems()
end for
' replace the old row
- updateSizeArray(itemSize, m.homeSectionIndexes.livetv, "replace")
- m.top.content.replaceChild(row, m.homeSectionIndexes.livetv)
-
- end if
-end sub
+ m.top.content.replaceChild(row, m.homeSections.livetv.index)
-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 itemSelected()
From 142419ce66f88c705fc4306b30725497900ffbe6 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 14:58:21 -0500
Subject: [PATCH 04/20] Add sections to home view on update as needed
---
components/home/HomeRows.bs | 71 +++++++++++++------------------------
1 file changed, 25 insertions(+), 46 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 56ebdec7e..25acd3ac0 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -58,14 +58,14 @@ sub updateSize()
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 = []
+' processUserSections: Loop through user's chosen home section settings and generate the content for each row
+'
+' @return {dynamic} content node filled with child nodes for each row
+function processUserSections() as dynamic
+ m.homeSections = {}
- content = CreateObject("roSGNode", "ContentNode")
loadedSections = 0
+ content = CreateObject("roSGNode", "ContentNode")
' Add sections in order based on user settings
for i = 0 to 6
@@ -76,8 +76,8 @@ sub onLibrariesLoaded()
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
- if loadedSections = 2 or i = 6
- if not m.global.app_loaded
+ if not m.global.app_loaded
+ if loadedSections = 2 or i = 6
m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring
m.global.app_loaded = true
end if
@@ -87,6 +87,20 @@ sub onLibrariesLoaded()
' Favorites isn't an option on Web settings, so we must manually add it for now
addHomeSection(content, "favorites")
+ return content
+end function
+
+
+' 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 = []
+
+ content = processUserSections()
+
setRowItemSizes()
m.top.content = content
@@ -283,44 +297,9 @@ end sub
' Update home row data
sub updateHomeRows()
- ' If resume section exists, reload row's data
- if m.homeSections.doesExist("resume")
- m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
- m.LoadContinueWatchingTask.control = "RUN"
- end if
-
- ' If next up section exists, reload row's data
- if m.homeSections.doesExist("nextup")
- m.LoadNextUpTask.observeField("content", "updateNextUpItems")
- m.LoadNextUpTask.control = "RUN"
- end if
-
- ' If favorites section exists, reload row's data
- if m.homeSections.doesExist("favorites")
- m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
- m.LoadFavoritesTask.control = "RUN"
- end if
-
- ' If live tv's on now section exists, reload row's data
- if m.homeSections.doesExist("livetv")
- m.LoadOnNowTask.observeField("content", "updateOnNowItems")
- m.LoadOnNowTask.control = "RUN"
- end if
-
- ' If latest in library section exists, reload row's data
- hasLatestHomeSection = false
-
- for each section in m.homeSections
- if LCase(Left(section, 6)) = "latest"
- hasLatestHomeSection = true
- exit for
- end if
- end for
-
- if hasLatestHomeSection
- updateLatestInRows()
- end if
-
+ content = processUserSections()
+ setRowItemSizes()
+ m.top.content = content
end sub
sub updateFavoritesItems()
From a5af2555bf8a62274a38c75157e08c75ef7376cd Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 18:23:04 -0500
Subject: [PATCH 05/20] Reset focus to selected item when returning to home
view
---
components/home/HomeRows.bs | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 25acd3ac0..9ab208768 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -333,6 +333,8 @@ sub updateFavoritesItems()
' replace the old row
m.top.content.replaceChild(row, rowIndex)
+ ' Set focus on previously focused item
+ setFocusToPreviousFocusedItem()
end if
end sub
@@ -365,6 +367,8 @@ sub updateContinueWatchingItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.resume.index)
+ ' Set focus on previously focused item
+ setFocusToPreviousFocusedItem()
end sub
sub updateNextUpItems()
@@ -389,6 +393,8 @@ sub updateNextUpItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.nextup.index)
+ ' Set focus on previously focused item
+ setFocusToPreviousFocusedItem()
end if
end sub
@@ -460,6 +466,10 @@ sub updateLatestItems(msg)
' Replace the old row
if isValid(rowIndex)
m.top.content.replaceChild(row, rowIndex)
+
+ ' Set focus on previously focused item
+ setFocusToPreviousFocusedItem()
+
return
end if
end if
@@ -499,6 +509,16 @@ sub updateLatestItems(msg)
end if
end sub
+' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
+'
+sub setFocusToPreviousFocusedItem()
+ if isValid(m.selectedRowItem)
+ if isValid(m.homeSections[m.selectedRowItem[0]])
+ m.top.jumpToRowItem = [m.homeSections[m.selectedRowItem[0]].index, m.selectedRowItem[1]]
+ end if
+ end if
+end sub
+
sub updateOnNowItems()
itemData = m.LoadOnNowTask.content
m.LoadOnNowTask.unobserveField("content")
@@ -530,11 +550,19 @@ sub updateOnNowItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.livetv.index)
+ ' Set focus on previously focused item
+ setFocusToPreviousFocusedItem()
end if
end sub
sub itemSelected()
+ for each section in m.homeSections
+ if m.homeSections[section].index = m.top.rowItemSelected[0]
+ m.selectedRowItem = [section, m.top.rowItemSelected[1]]
+ end if
+ end for
+
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
'Prevent the selected item event from double firing
From 06af8b203019b5e8e7453ed6e2b1072260ded035 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 22 Nov 2023 20:55:41 -0500
Subject: [PATCH 06/20] Don't allow Roku's component reuse to mess up library
fonts
---
components/home/HomeItem.bs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/components/home/HomeItem.bs b/components/home/HomeItem.bs
index f83be55ad..ff84644d2 100644
--- a/components/home/HomeItem.bs
+++ b/components/home/HomeItem.bs
@@ -65,6 +65,10 @@ sub itemContentChanged()
' Format the Data based on the type of Home Data
if itemData.type = "CollectionFolder" or itemData.type = "UserView" or itemData.type = "Channel"
+ m.itemText.font.size = 35
+ m.itemText.height = 64
+ m.itemText.horizAlign = "center"
+ m.itemText.vertAlign = "bottom"
m.itemText.text = itemData.name
m.itemPoster.uri = itemData.widePosterURL
return
From 867667f5168d1619f290682c6ad1a6db8cba32d1 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Thu, 23 Nov 2023 08:52:44 -0500
Subject: [PATCH 07/20] Add setting to match web's home sections
---
.vscode/settings.json | 2 +-
components/ImageSizes.bs | 5 +++
components/home/HomeRows.bs | 75 ++++++++++++++++++++++++------------
locale/en_US/translations.ts | 10 +++++
settings/settings.json | 7 ++++
source/utils/misc.bs | 3 ++
source/utils/session.bs | 14 +++++++
7 files changed, 90 insertions(+), 26 deletions(-)
create mode 100644 components/ImageSizes.bs
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a005ef427..746c772b1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -18,4 +18,4 @@
"docs/api/**": true
},
"brightscriptcomment.addExtraAtStartAndEnd": false
-}
+}
\ No newline at end of file
diff --git a/components/ImageSizes.bs b/components/ImageSizes.bs
new file mode 100644
index 000000000..2371a30fc
--- /dev/null
+++ b/components/ImageSizes.bs
@@ -0,0 +1,5 @@
+namespace imageSizes
+ const WIDE_POSTER = [464, 331]
+ const MOVIE_POSTER = [188, 331]
+ const MUSIC_ALBUM = [261, 331]
+end namespace
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 9ab208768..f5895e88c 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,4 +1,9 @@
import "pkg:/source/utils/misc.bs"
+import "pkg:/components/ImageSizes.bs"
+
+' The maximum number of seconds we will show the loading spinner and delay the user from using the home view while the content loads
+' We use this to wait for the rows to load so we can reset focus to the row/item once it loads
+const MAX_TIME_HOME_LOADING_SPINNER_SHOWN = 1
sub init()
m.top.itemComponentName = "HomeItem"
@@ -14,6 +19,11 @@ sub init()
m.homeSections = {}
+ m.loadingTimer = createObject("roSGNode", "Timer")
+ m.loadingTimer.duration = MAX_TIME_HOME_LOADING_SPINNER_SHOWN
+ m.loadingTimer.repeat = true
+ m.loadingTimer.observeField("fire", "stopLoadingSpinner")
+
updateSize()
m.top.setfocus(true)
@@ -190,7 +200,7 @@ sub createLibraryRow(content as dynamic)
mediaRow.title = tr("My Media")
m.homeSections.AddReplace("library", {
- imageSize: [464, 331],
+ imageSize: imageSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -212,12 +222,12 @@ sub createLatestInRows(content as dynamic)
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
- imagesize = [464, 331]
+ imagesize = imageSizes.WIDE_POSTER
if LCase(lib.collectionType) = "movies"
- imagesize = [188, 331]
+ imagesize = imageSizes.MOVIE_POSTER
else if LCase(lib.collectionType) = "music"
- imagesize = [261, 331]
+ imagesize = imageSizes.MUSIC_ALBUM
end if
m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
@@ -244,7 +254,7 @@ sub createLiveTVRow(content as dynamic)
contentRow = content.CreateChild("HomeRow")
contentRow.title = tr("On Now")
m.homeSections.AddReplace("livetv", {
- imageSize: [464, 331],
+ imageSize: imageSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -257,7 +267,7 @@ sub createContinueWatchingRow(content as dynamic)
continueWatchingRow = content.CreateChild("HomeRow")
continueWatchingRow.title = tr("Continue Watching")
m.homeSections.AddReplace("resume", {
- imageSize: [464, 331],
+ imageSize: imageSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -271,7 +281,7 @@ sub createNextUpRow(content as dynamic)
nextUpRow = content.CreateChild("HomeRow")
nextUpRow.title = tr("Next Up >")
m.homeSections.AddReplace("nextup", {
- imageSize: [464, 331],
+ imageSize: imageSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -286,7 +296,7 @@ sub createFavoritesRow(content as dynamic)
favoritesRow.title = tr("Favorites")
m.homeSections.AddReplace("favorites", {
- imageSize: [464, 331],
+ imageSize: imageSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -297,6 +307,7 @@ end sub
' Update home row data
sub updateHomeRows()
+ startMediaLoadingSpinner()
content = processUserSections()
setRowItemSizes()
m.top.content = content
@@ -375,6 +386,7 @@ sub updateNextUpItems()
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
m.LoadNextUpTask.content = []
+ m.LoadNextUpTask.control = "STOP"
if itemData = invalid then return
@@ -444,14 +456,14 @@ sub updateLatestItems(msg)
row.usePoster = true
' Handle specific types with different item widths
if node.metadata.contentType = "movies"
- row.imageWidth = 180
- itemSize = [188, 331]
+ row.imageWidth = imageSizes.MOVIE_POSTER[0]
+ itemSize = imageSizes.MOVIE_POSTER
else if node.metadata.contentType = "music"
- row.imageWidth = 261
- itemSize = [261, 331]
+ row.imageWidth = imageSizes.MUSIC_ALBUM[0]
+ itemSize = imageSizes.MUSIC_ALBUM
else
- row.imageWidth = 464
- itemSize = [464, 331]
+ row.imageWidth = imageSizes.WIDE_POSTER[0]
+ itemSize = imageSizes.WIDE_POSTER
end if
for each item in itemData
@@ -512,9 +524,21 @@ end sub
' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
'
sub setFocusToPreviousFocusedItem()
+ m.loadingTimer.control = "start"
+
if isValid(m.selectedRowItem)
- if isValid(m.homeSections[m.selectedRowItem[0]])
- m.top.jumpToRowItem = [m.homeSections[m.selectedRowItem[0]].index, m.selectedRowItem[1]]
+ ' Set focus to row if it exists
+ itemRow = m.top.content.getChild(m.top.rowItemSelected[0])
+ if isValid(itemRow)
+ m.top.jumpToItem = m.top.rowItemSelected[0]
+
+ ' Set focus to column if it exists
+ itemColumn = itemRow.getChild(m.top.rowItemSelected[1])
+ if isValid(itemColumn)
+ m.top.jumpToRowItem = [m.selectedRowItem[0], m.selectedRowItem[1]]
+ m.loadingTimer.control = "stop"
+ stopLoadingSpinner()
+ end if
end if
end if
end sub
@@ -533,16 +557,18 @@ sub updateOnNowItems()
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("On Now")
- 'itemSize = [464, 331]
- row.imageWidth = 464
+ row.imageWidth = imageSizes.WIDE_POSTER[0]
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 = 180
- 'itemSize = [188, 331]
+ row.imageWidth = imageSizes.MOVIE_POSTER[0]
+
+ m.homeSections.livetv.imageSize = imageSizes.MOVIE_POSTER
end if
+
item.usePoster = row.usePoster
item.imageWidth = row.imageWidth
row.appendChild(item)
@@ -553,15 +579,14 @@ sub updateOnNowItems()
' Set focus on previously focused item
setFocusToPreviousFocusedItem()
+ ' We may now have different poster sizes. Reset the row item sizes
+ setRowItemSizes()
+
end if
end sub
sub itemSelected()
- for each section in m.homeSections
- if m.homeSections[section].index = m.top.rowItemSelected[0]
- m.selectedRowItem = [section, m.top.rowItemSelected[1]]
- end if
- end for
+ m.selectedRowItem = m.top.rowItemSelected
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
diff --git a/locale/en_US/translations.ts b/locale/en_US/translations.ts
index eccdff59e..54af561bf 100644
--- a/locale/en_US/translations.ts
+++ b/locale/en_US/translations.ts
@@ -1231,5 +1231,15 @@
No Chapter Data FoundMessage shown in OSD when no chapter data is returned by the API
+
+
+ Use Web's Home Section Arrangement
+ User Setting - Setting title
+
+
+
+ Make the arrangement of the Roku home view sections match the web's home screen. Jellyfin will need to be closed and reopened for change to take effect.
+ User Setting - Setting description
+
\ No newline at end of file
diff --git a/settings/settings.json b/settings/settings.json
index 497202f62..bbe713860 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -231,6 +231,13 @@
"settingName": "ui.home.splashBackground",
"type": "bool",
"default": "false"
+ },
+ {
+ "title": "Use Web's Home Section Arrangement",
+ "description": "Make the arrangement of the Roku home view sections match the web's home screen. Jellyfin will need to be closed and reopened for change to take effect.",
+ "settingName": "ui.home.useWebSectionArrangement",
+ "type": "bool",
+ "default": "false"
}
]
},
diff --git a/source/utils/misc.bs b/source/utils/misc.bs
index 3cb48ed96..e9d2c5f80 100644
--- a/source/utils/misc.bs
+++ b/source/utils/misc.bs
@@ -459,6 +459,9 @@ sub startLoadingSpinner()
end sub
sub startMediaLoadingSpinner()
+ if not isValid(m.scene)
+ m.scene = m.top.getScene()
+ end if
dialog = createObject("roSGNode", "ProgressDialog")
dialog.id = "invisibiledialog"
dialog.visible = false
diff --git a/source/utils/session.bs b/source/utils/session.bs
index d252661b0..14518d355 100644
--- a/source/utils/session.bs
+++ b/source/utils/session.bs
@@ -226,6 +226,20 @@ namespace session
userPreferences = customPrefs
rowTypes = []
+ ' If this is a first time user, set the useWebSectionArrangement setting to true
+ ' This way the home view for upgrading users is not changed without them opting in
+ if not isValid(m.global.app.lastRunVersion)
+ set_user_setting("ui.home.useWebSectionArrangement", "true")
+ end if
+
+ useWebSectionArrangement = m.global.session.user.settings["ui.home.useWebSectionArrangement"]
+
+ if isValid(useWebSectionArrangement)
+ if not useWebSectionArrangement
+ userPreferences.delete("homesection0")
+ end if
+ end if
+
' If user has no section preferences, use default settings
if not userPreferences.doesExist("homesection0")
userPreferences = {
From 40925199d46657ee60c3c111bf6d1978e0eb44fc Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 25 Nov 2023 08:25:31 -0500
Subject: [PATCH 08/20] Review Updates & Bug Fix
Fix Roku component reuse bug
Don't repeat loadingTimer
Move ImageSizes enum to source folder
Update setting text & translation
Check selectedRowItem is valid and not empty
---
components/home/HomeItem.bs | 1 +
components/home/HomeRows.bs | 33 +++++++++----------
locale/en_US/translations.ts | 8 ++---
settings/settings.json | 6 ++--
.../constants}/ImageSizes.bs | 4 ++-
source/migrations.bs | 8 +++++
source/utils/session.bs | 6 ----
7 files changed, 35 insertions(+), 31 deletions(-)
rename {components => source/constants}/ImageSizes.bs (54%)
diff --git a/components/home/HomeItem.bs b/components/home/HomeItem.bs
index ff84644d2..882f6b5f5 100644
--- a/components/home/HomeItem.bs
+++ b/components/home/HomeItem.bs
@@ -28,6 +28,7 @@ end sub
sub itemContentChanged()
+ m.unplayedCount.visible = false
itemData = m.top.itemContent
if itemData = invalid then return
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index f5895e88c..a611ebcf1 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,5 +1,5 @@
import "pkg:/source/utils/misc.bs"
-import "pkg:/components/ImageSizes.bs"
+import "pkg:/source/constants/ImageSizes.bs"
' The maximum number of seconds we will show the loading spinner and delay the user from using the home view while the content loads
' We use this to wait for the rows to load so we can reset focus to the row/item once it loads
@@ -21,7 +21,6 @@ sub init()
m.loadingTimer = createObject("roSGNode", "Timer")
m.loadingTimer.duration = MAX_TIME_HOME_LOADING_SPINNER_SHOWN
- m.loadingTimer.repeat = true
m.loadingTimer.observeField("fire", "stopLoadingSpinner")
updateSize()
@@ -308,6 +307,7 @@ end sub
' Update home row data
sub updateHomeRows()
startMediaLoadingSpinner()
+ m.loadingTimer.control = "start"
content = processUserSections()
setRowItemSizes()
m.top.content = content
@@ -454,6 +454,7 @@ sub updateLatestItems(msg)
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 = imageSizes.MOVIE_POSTER[0]
@@ -524,21 +525,19 @@ end sub
' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
'
sub setFocusToPreviousFocusedItem()
- m.loadingTimer.control = "start"
-
- if isValid(m.selectedRowItem)
- ' Set focus to row if it exists
- itemRow = m.top.content.getChild(m.top.rowItemSelected[0])
- if isValid(itemRow)
- m.top.jumpToItem = m.top.rowItemSelected[0]
-
- ' Set focus to column if it exists
- itemColumn = itemRow.getChild(m.top.rowItemSelected[1])
- if isValid(itemColumn)
- m.top.jumpToRowItem = [m.selectedRowItem[0], m.selectedRowItem[1]]
- m.loadingTimer.control = "stop"
- stopLoadingSpinner()
- end if
+ if not isValidAndNotEmpty(m.selectedRowItem) then return
+
+ ' Set focus to row if it exists
+ itemRow = m.top.content.getChild(m.selectedRowItem[0])
+ if isValid(itemRow)
+ m.top.jumpToItem = m.selectedRowItem[0]
+
+ ' Set focus to column if it exists
+ itemColumn = itemRow.getChild(m.selectedRowItem[1])
+ if isValid(itemColumn)
+ m.top.jumpToRowItem = [m.selectedRowItem[0], m.selectedRowItem[1]]
+ m.loadingTimer.control = "stop"
+ stopLoadingSpinner()
end if
end if
end sub
diff --git a/locale/en_US/translations.ts b/locale/en_US/translations.ts
index 54af561bf..1fe478489 100644
--- a/locale/en_US/translations.ts
+++ b/locale/en_US/translations.ts
@@ -1232,13 +1232,13 @@
Message shown in OSD when no chapter data is returned by the API
-
- Use Web's Home Section Arrangement
+
+ Use Web Client's Home Section ArrangementUser Setting - Setting title
-
- Make the arrangement of the Roku home view sections match the web's home screen. Jellyfin will need to be closed and reopened for change to take effect.
+
+ Make the arrangement of the Roku home view sections match the web client's home screen. Jellyfin will need to be closed and reopened for change to take effect.User Setting - Setting description
diff --git a/settings/settings.json b/settings/settings.json
index bbe713860..9c33a6b01 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -233,11 +233,11 @@
"default": "false"
},
{
- "title": "Use Web's Home Section Arrangement",
- "description": "Make the arrangement of the Roku home view sections match the web's home screen. Jellyfin will need to be closed and reopened for change to take effect.",
+ "title": "Use Web Client's Home Section Arrangement",
+ "description": "Make the arrangement of the Roku home view sections match the web client's home screen. Jellyfin will need to be closed and reopened for change to take effect.",
"settingName": "ui.home.useWebSectionArrangement",
"type": "bool",
- "default": "false"
+ "default": "true"
}
]
},
diff --git a/components/ImageSizes.bs b/source/constants/ImageSizes.bs
similarity index 54%
rename from components/ImageSizes.bs
rename to source/constants/ImageSizes.bs
index 2371a30fc..2e3df0b77 100644
--- a/components/ImageSizes.bs
+++ b/source/constants/ImageSizes.bs
@@ -1,5 +1,7 @@
+' @fileoverview Constants for various image sizes.
+
namespace imageSizes
const WIDE_POSTER = [464, 331]
- const MOVIE_POSTER = [188, 331]
+ const MOVIE_POSTER = [180, 331]
const MUSIC_ALBUM = [261, 331]
end namespace
diff --git a/source/migrations.bs b/source/migrations.bs
index 70cec93f9..201ffc66c 100644
--- a/source/migrations.bs
+++ b/source/migrations.bs
@@ -72,6 +72,14 @@ sub runRegistryUserMigrations()
m.wasMigrated = true
print `Running Registry Migration for ${CLIENT_VERSION_REQUIRING_BASE_MIGRATION} for userid: ${section}`
+ ' If this is an existing user, set the useWebSectionArrangement setting to false
+ ' This way the home view for upgrading users is not changed without them opting in
+ useWebSectionArrangement = registry_read("ui.home.useWebSectionArrangement", section)
+
+ if not isValid(useWebSectionArrangement)
+ registry_write("ui.home.useWebSectionArrangement", "false", section)
+ end if
+
' no longer saving password to registry
registry_delete("password", section)
' av1 playback no longer hidden behind user setting
diff --git a/source/utils/session.bs b/source/utils/session.bs
index 14518d355..f6eee976d 100644
--- a/source/utils/session.bs
+++ b/source/utils/session.bs
@@ -226,12 +226,6 @@ namespace session
userPreferences = customPrefs
rowTypes = []
- ' If this is a first time user, set the useWebSectionArrangement setting to true
- ' This way the home view for upgrading users is not changed without them opting in
- if not isValid(m.global.app.lastRunVersion)
- set_user_setting("ui.home.useWebSectionArrangement", "true")
- end if
-
useWebSectionArrangement = m.global.session.user.settings["ui.home.useWebSectionArrangement"]
if isValid(useWebSectionArrangement)
From 47781b77d7c834217026646f24606c11b93eb5a3 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sun, 26 Nov 2023 15:48:50 -0500
Subject: [PATCH 09/20] Fix 1st run setting
---
source/migrations.bs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/source/migrations.bs b/source/migrations.bs
index 201ffc66c..19182e90e 100644
--- a/source/migrations.bs
+++ b/source/migrations.bs
@@ -74,9 +74,8 @@ sub runRegistryUserMigrations()
' If this is an existing user, set the useWebSectionArrangement setting to false
' This way the home view for upgrading users is not changed without them opting in
- useWebSectionArrangement = registry_read("ui.home.useWebSectionArrangement", section)
-
- if not isValid(useWebSectionArrangement)
+ if not hasUserVersion
+ print "useWebSectionArrangement set to false"
registry_write("ui.home.useWebSectionArrangement", "false", section)
end if
From f1da07ea6e47550c86a5c987c04d6abd199721bd Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Mon, 27 Nov 2023 17:14:19 -0500
Subject: [PATCH 10/20] Rename ImageSizes file to match actual use
---
components/home/HomeRows.bs | 36 +++++++++----------
.../{ImageSizes.bs => HomeRowItemSizes.bs} | 4 +--
2 files changed, 20 insertions(+), 20 deletions(-)
rename source/constants/{ImageSizes.bs => HomeRowItemSizes.bs} (58%)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index a611ebcf1..ff2abb236 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,5 +1,5 @@
import "pkg:/source/utils/misc.bs"
-import "pkg:/source/constants/ImageSizes.bs"
+import "pkg:/source/constants/HomeRowItemSizes.bs"
' The maximum number of seconds we will show the loading spinner and delay the user from using the home view while the content loads
' We use this to wait for the rows to load so we can reset focus to the row/item once it loads
@@ -199,7 +199,7 @@ sub createLibraryRow(content as dynamic)
mediaRow.title = tr("My Media")
m.homeSections.AddReplace("library", {
- imageSize: imageSizes.WIDE_POSTER,
+ imageSize: homeRowItemSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -221,12 +221,12 @@ sub createLatestInRows(content as dynamic)
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
- imagesize = imageSizes.WIDE_POSTER
+ imagesize = homeRowItemSizes.WIDE_POSTER
if LCase(lib.collectionType) = "movies"
- imagesize = imageSizes.MOVIE_POSTER
+ imagesize = homeRowItemSizes.MOVIE_POSTER
else if LCase(lib.collectionType) = "music"
- imagesize = imageSizes.MUSIC_ALBUM
+ imagesize = homeRowItemSizes.MUSIC_ALBUM
end if
m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
@@ -253,7 +253,7 @@ sub createLiveTVRow(content as dynamic)
contentRow = content.CreateChild("HomeRow")
contentRow.title = tr("On Now")
m.homeSections.AddReplace("livetv", {
- imageSize: imageSizes.WIDE_POSTER,
+ imageSize: homeRowItemSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -266,7 +266,7 @@ sub createContinueWatchingRow(content as dynamic)
continueWatchingRow = content.CreateChild("HomeRow")
continueWatchingRow.title = tr("Continue Watching")
m.homeSections.AddReplace("resume", {
- imageSize: imageSizes.WIDE_POSTER,
+ imageSize: homeRowItemSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -280,7 +280,7 @@ sub createNextUpRow(content as dynamic)
nextUpRow = content.CreateChild("HomeRow")
nextUpRow.title = tr("Next Up >")
m.homeSections.AddReplace("nextup", {
- imageSize: imageSizes.WIDE_POSTER,
+ imageSize: homeRowItemSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -295,7 +295,7 @@ sub createFavoritesRow(content as dynamic)
favoritesRow.title = tr("Favorites")
m.homeSections.AddReplace("favorites", {
- imageSize: imageSizes.WIDE_POSTER,
+ imageSize: homeRowItemSizes.WIDE_POSTER,
index: m.homeSections.count()
})
@@ -457,14 +457,14 @@ sub updateLatestItems(msg)
' Handle specific types with different item widths
if node.metadata.contentType = "movies"
- row.imageWidth = imageSizes.MOVIE_POSTER[0]
- itemSize = imageSizes.MOVIE_POSTER
+ row.imageWidth = homeRowItemSizes.MOVIE_POSTER[0]
+ itemSize = homeRowItemSizes.MOVIE_POSTER
else if node.metadata.contentType = "music"
- row.imageWidth = imageSizes.MUSIC_ALBUM[0]
- itemSize = imageSizes.MUSIC_ALBUM
+ row.imageWidth = homeRowItemSizes.MUSIC_ALBUM[0]
+ itemSize = homeRowItemSizes.MUSIC_ALBUM
else
- row.imageWidth = imageSizes.WIDE_POSTER[0]
- itemSize = imageSizes.WIDE_POSTER
+ row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
+ itemSize = homeRowItemSizes.WIDE_POSTER
end if
for each item in itemData
@@ -556,16 +556,16 @@ sub updateOnNowItems()
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
row.title = tr("On Now")
- row.imageWidth = imageSizes.WIDE_POSTER[0]
+ row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
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 = imageSizes.MOVIE_POSTER[0]
+ row.imageWidth = homeRowItemSizes.MOVIE_POSTER[0]
- m.homeSections.livetv.imageSize = imageSizes.MOVIE_POSTER
+ m.homeSections.livetv.imageSize = homeRowItemSizes.MOVIE_POSTER
end if
item.usePoster = row.usePoster
diff --git a/source/constants/ImageSizes.bs b/source/constants/HomeRowItemSizes.bs
similarity index 58%
rename from source/constants/ImageSizes.bs
rename to source/constants/HomeRowItemSizes.bs
index 2e3df0b77..9ee0690a3 100644
--- a/source/constants/ImageSizes.bs
+++ b/source/constants/HomeRowItemSizes.bs
@@ -1,6 +1,6 @@
-' @fileoverview Constants for various image sizes.
+' @fileoverview Constants for rowItemSize on the home view
-namespace imageSizes
+namespace homeRowItemSizes
const WIDE_POSTER = [464, 331]
const MOVIE_POSTER = [180, 331]
const MUSIC_ALBUM = [261, 331]
From b185c08c0cd45f8739c733d5454f493b79a58b51 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Mon, 27 Nov 2023 20:08:16 -0500
Subject: [PATCH 11/20] Fix 1st time setting bug
Fix by Cewert
---
source/migrations.bs | 5 -----
source/utils/session.bs | 5 ++++-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/source/migrations.bs b/source/migrations.bs
index 19182e90e..58660b813 100644
--- a/source/migrations.bs
+++ b/source/migrations.bs
@@ -84,11 +84,6 @@ sub runRegistryUserMigrations()
' av1 playback no longer hidden behind user setting
registry_delete("playback.av1", section)
end if
-
- ' update lastRunVersion if needed
- if hasUserVersion and lastRunVersion <> m.global.app.version
- registry_write("LastRunVersion", m.global.app.version, section)
- end if
end if
end for
end sub
diff --git a/source/utils/session.bs b/source/utils/session.bs
index f6eee976d..c87f3c496 100644
--- a/source/utils/session.bs
+++ b/source/utils/session.bs
@@ -156,8 +156,11 @@ namespace session
' grab lastRunVersion for this user
lastRunVersion = get_user_setting("LastRunVersion")
- if lastRunVersion <> invalid
+ if isValid(lastRunVersion) and lastRunVersion = m.global.app.version
+ ' Don't update the registry, only update the global session
session.user.Update("LastRunVersion", lastRunVersion)
+ else
+ set_user_setting("LastRunVersion", m.global.app.version)
end if
' update user session settings with values from registry
From d6b50440d4f6b1ba4817f7263012389dc9ec7c82 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Wed, 29 Nov 2023 16:06:54 -0500
Subject: [PATCH 12/20] Fix refresh delay
---
components/home/HomeRows.bs | 245 ++++++++++++++++--------------------
1 file changed, 109 insertions(+), 136 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index ff2abb236..f3a4aa2c8 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,10 +1,6 @@
import "pkg:/source/utils/misc.bs"
import "pkg:/source/constants/HomeRowItemSizes.bs"
-' The maximum number of seconds we will show the loading spinner and delay the user from using the home view while the content loads
-' We use this to wait for the rows to load so we can reset focus to the row/item once it loads
-const MAX_TIME_HOME_LOADING_SPINNER_SHOWN = 1
-
sub init()
m.top.itemComponentName = "HomeItem"
' how many rows are visible on the screen
@@ -19,10 +15,6 @@ sub init()
m.homeSections = {}
- m.loadingTimer = createObject("roSGNode", "Timer")
- m.loadingTimer.duration = MAX_TIME_HOME_LOADING_SPINNER_SHOWN
- m.loadingTimer.observeField("fire", "stopLoadingSpinner")
-
updateSize()
m.top.setfocus(true)
@@ -71,8 +63,6 @@ end sub
'
' @return {dynamic} content node filled with child nodes for each row
function processUserSections() as dynamic
- m.homeSections = {}
-
loadedSections = 0
content = CreateObject("roSGNode", "ContentNode")
@@ -124,13 +114,14 @@ sub removeHomeSection(sectionType as string)
if not isValid(removedSection) then return
if not isValid(removedSection.index) then return
+ m.homeSections.Delete(sectionName)
+
for each section in m.homeSections
if m.homeSections[section].index > removedSection.index
m.homeSections[section].index--
end if
end for
- m.homeSections.Delete(sectionName)
m.top.content.removeChildIndex(removedSection.index)
setRowItemSizes()
@@ -198,15 +189,31 @@ sub createLibraryRow(content as dynamic)
mediaRow = content.CreateChild("HomeRow")
mediaRow.title = tr("My Media")
+ sectionIndex = m.homeSections.count()
+
+ isUpdate = false
+
+ if m.homeSections.doesExist("library")
+ sectionIndex = m.homeSections.library.index
+ isUpdate = true
+ end if
+
m.homeSections.AddReplace("library", {
imageSize: homeRowItemSizes.WIDE_POSTER,
- index: m.homeSections.count()
+ index: sectionIndex
})
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
for each item in filteredMedia
mediaRow.appendChild(item)
end for
+
+ if isUpdate
+ m.top.content.replaceChild(mediaRow, m.homeSections.library.index)
+ return
+ end if
+
+ content.appendChild(mediaRow)
end sub
' Create a row displaying latest items in each of the user's libraries
@@ -218,8 +225,16 @@ sub createLatestInRows(content as dynamic)
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 + " >"
+
+ sectionName = "latestin" + LCase(lib.name).Replace(" ", "")
+
+ if not m.homeSections.doesExist(sectionName)
+ latestInRow = content.CreateChild("HomeRow")
+ latestInRow.title = tr("Latest in") + " " + lib.name + " >"
+ sectionIndex = m.homeSections.count()
+ else
+ sectionIndex = m.homeSections[sectionName].index
+ end if
imagesize = homeRowItemSizes.WIDE_POSTER
@@ -229,9 +244,9 @@ sub createLatestInRows(content as dynamic)
imagesize = homeRowItemSizes.MUSIC_ALBUM
end if
- m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
+ m.homeSections.AddReplace(sectionName, {
imageSize: imagesize,
- index: m.homeSections.count()
+ index: sectionIndex
})
loadLatest = createObject("roSGNode", "LoadItemsTask")
@@ -250,11 +265,20 @@ end sub
' Create a row displaying the live tv now on section
sub createLiveTVRow(content as dynamic)
- contentRow = content.CreateChild("HomeRow")
- contentRow.title = tr("On Now")
+ if not m.homeSections.doesExist("livetv")
+ contentRow = content.CreateChild("HomeRow")
+ contentRow.title = tr("On Now")
+ end if
+
+ sectionIndex = m.homeSections.count()
+
+ if m.homeSections.doesExist("livetv")
+ sectionIndex = m.homeSections.livetv.index
+ end if
+
m.homeSections.AddReplace("livetv", {
imageSize: homeRowItemSizes.WIDE_POSTER,
- index: m.homeSections.count()
+ index: sectionIndex
})
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
@@ -263,11 +287,19 @@ end sub
' Create a row displaying items the user can continue watching
sub createContinueWatchingRow(content as dynamic)
- continueWatchingRow = content.CreateChild("HomeRow")
- continueWatchingRow.title = tr("Continue Watching")
+ if not m.homeSections.doesExist("resume")
+ continueWatchingRow = content.CreateChild("HomeRow")
+ continueWatchingRow.title = tr("Continue Watching")
+ end if
+ sectionIndex = m.homeSections.count()
+
+ if m.homeSections.doesExist("resume")
+ sectionIndex = m.homeSections.resume.index
+ end if
+
m.homeSections.AddReplace("resume", {
imageSize: homeRowItemSizes.WIDE_POSTER,
- index: m.homeSections.count()
+ index: sectionIndex
})
' Load the Continue Watching Data
@@ -277,11 +309,19 @@ end sub
' Create a row displaying next episodes up to watch
sub createNextUpRow(content as dynamic)
- nextUpRow = content.CreateChild("HomeRow")
- nextUpRow.title = tr("Next Up >")
+ if not m.homeSections.doesExist("nextup")
+ nextUpRow = content.CreateChild("HomeRow")
+ nextUpRow.title = tr("Next Up >")
+ end if
+ sectionIndex = m.homeSections.count()
+
+ if m.homeSections.doesExist("nextup")
+ sectionIndex = m.homeSections.nextup.index
+ end if
+
m.homeSections.AddReplace("nextup", {
imageSize: homeRowItemSizes.WIDE_POSTER,
- index: m.homeSections.count()
+ index: sectionIndex
})
' Load the Next Up Data
@@ -291,12 +331,20 @@ end sub
' Create a row displaying items from the user's favorites list
sub createFavoritesRow(content as dynamic)
- favoritesRow = content.CreateChild("HomeRow")
- favoritesRow.title = tr("Favorites")
+ if not m.homeSections.doesExist("favorites")
+ favoritesRow = content.CreateChild("HomeRow")
+ favoritesRow.title = tr("Favorites")
+ end if
+
+ sectionIndex = m.homeSections.count()
+
+ if m.homeSections.doesExist("favorites")
+ sectionIndex = m.homeSections.favorites.index
+ end if
m.homeSections.AddReplace("favorites", {
imageSize: homeRowItemSizes.WIDE_POSTER,
- index: m.homeSections.count()
+ index: sectionIndex
})
' Load the Favorites Data
@@ -306,11 +354,8 @@ end sub
' Update home row data
sub updateHomeRows()
- startMediaLoadingSpinner()
- m.loadingTimer.control = "start"
- content = processUserSections()
+ processUserSections()
setRowItemSizes()
- m.top.content = content
end sub
sub updateFavoritesItems()
@@ -342,11 +387,19 @@ sub updateFavoritesItems()
row.appendChild(item)
end for
- ' replace the old row
- m.top.content.replaceChild(row, rowIndex)
- ' Set focus on previously focused item
- setFocusToPreviousFocusedItem()
+ if isValid(m.top.content.getChild(rowIndex))
+ m.top.content.replaceChild(row, rowIndex)
+ else
+ for each section in m.homeSections
+ if m.homeSections[section].index >= m.top.content.getChildCount()
+ m.homeSections[section].index++
+ end if
+ end for
+
+ m.homeSections.favorites.index = m.top.content.getChildCount()
+ m.top.content.insertChild(row, m.top.content.getChildCount())
+ end if
end if
end sub
@@ -378,8 +431,6 @@ sub updateContinueWatchingItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.resume.index)
- ' Set focus on previously focused item
- setFocusToPreviousFocusedItem()
end sub
sub updateNextUpItems()
@@ -405,36 +456,9 @@ sub updateNextUpItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.nextup.index)
- ' Set focus on previously focused item
- setFocusToPreviousFocusedItem()
end if
end sub
-' Iterate over user's libraries and update data for each Latest In section
-sub updateLatestInRows()
- ' Ensure we have data
- if not isValidAndNotEmpty(m.libraryData) then return
-
- ' Load new data 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"
- loadLatest = createObject("roSGNode", "LoadItemsTask")
- loadLatest.itemsToLoad = "latest"
- loadLatest.itemId = lib.id
-
- metadata = {
- "title": lib.name,
- "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()
@@ -455,90 +479,41 @@ sub updateLatestItems(msg)
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 = homeRowItemSizes.MOVIE_POSTER[0]
- itemSize = homeRowItemSizes.MOVIE_POSTER
- else if node.metadata.contentType = "music"
- row.imageWidth = homeRowItemSizes.MUSIC_ALBUM[0]
- itemSize = homeRowItemSizes.MUSIC_ALBUM
- else
- row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
- itemSize = homeRowItemSizes.WIDE_POSTER
- end if
-
for each item in itemData
item.usePoster = row.usePoster
- item.imageWidth = row.imageWidth
+ item.imageWidth = m.homeSections[sectionName].imageSize[0]
row.appendChild(item)
end for
- if isValid(m.homeSections[sectionName])
- rowIndex = m.homeSections[sectionName].index
+ rowIndex = m.homeSections[sectionName].index
+ if isValid(rowIndex) and isValid(m.top.content.getChild(rowIndex))
' Replace the old row
- if isValid(rowIndex)
- m.top.content.replaceChild(row, rowIndex)
-
- ' Set focus on previously focused item
- setFocusToPreviousFocusedItem()
-
- return
- end if
- end if
-
- ' Determine highest index of a Lastest In section so we can append the new section after it
- highestLatestHomeSectionIndex = 0
+ m.top.content.replaceChild(row, rowIndex)
+ else
+ firstLatestHomeSectionIndex = m.homeSections.count() - 1
- for each section in m.homeSections
- if LCase(Left(section, 6)) = "latest"
- if m.homeSections[section].index > highestLatestHomeSectionIndex
- highestLatestHomeSectionIndex = m.homeSections[section].index
+ for each section in m.homeSections
+ if LCase(Left(section, 6)) = "latest"
+ if m.homeSections[section].index < firstLatestHomeSectionIndex
+ firstLatestHomeSectionIndex = m.homeSections[section].index
+ end if
end if
- end if
- end for
-
- ' We have data for a section that doesn't currently exist
- rowIndex = highestLatestHomeSectionIndex + 1
+ end for
- ' Advance all the indexes greater than or equal than our new row
- for each section in m.homeSections
- if m.homeSections[section].index >= rowIndex
- m.homeSections[section].index++
- end if
- end for
-
- m.homeSections.AddReplace(sectionName, {
- imageSize: itemSize,
- index: rowIndex
- })
+ for each section in m.homeSections
+ if m.homeSections[section].index >= firstLatestHomeSectionIndex
+ m.homeSections[section].index++
+ end if
+ end for
- m.top.content.insertChild(row, rowIndex)
+ m.homeSections[sectionName].index = firstLatestHomeSectionIndex
+ m.top.content.insertChild(row, firstLatestHomeSectionIndex)
+ end if
- ' We've inserted a new row, we must set the row sizes again to ensure they're correct
setRowItemSizes()
- return
- end if
-end sub
-' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
-'
-sub setFocusToPreviousFocusedItem()
- if not isValidAndNotEmpty(m.selectedRowItem) then return
-
- ' Set focus to row if it exists
- itemRow = m.top.content.getChild(m.selectedRowItem[0])
- if isValid(itemRow)
- m.top.jumpToItem = m.selectedRowItem[0]
-
- ' Set focus to column if it exists
- itemColumn = itemRow.getChild(m.selectedRowItem[1])
- if isValid(itemColumn)
- m.top.jumpToRowItem = [m.selectedRowItem[0], m.selectedRowItem[1]]
- m.loadingTimer.control = "stop"
- stopLoadingSpinner()
- end if
end if
end sub
@@ -575,8 +550,6 @@ sub updateOnNowItems()
' replace the old row
m.top.content.replaceChild(row, m.homeSections.livetv.index)
- ' Set focus on previously focused item
- setFocusToPreviousFocusedItem()
' We may now have different poster sizes. Reset the row item sizes
setRowItemSizes()
From 383e61f230d9e5fb37b72d46b227f3712effde13 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Fri, 1 Dec 2023 23:05:15 -0500
Subject: [PATCH 13/20] Rewrite index tracking. Reduce/remove flicker.
---
components/home/Home.bs | 11 +-
components/home/Home.xml | 6 +-
components/home/HomeRow.xml | 1 +
components/home/HomeRows.bs | 590 ++++++++++++++++++++----------------
4 files changed, 343 insertions(+), 265 deletions(-)
diff --git a/components/home/Home.bs b/components/home/Home.bs
index 5c1f39f35..33b3c8606 100644
--- a/components/home/Home.bs
+++ b/components/home/Home.bs
@@ -9,6 +9,10 @@ sub init()
m.top.optionsAvailable = true
m.postTask = createObject("roSGNode", "PostTask")
+ m.homeRows = m.top.findNode("homeRows")
+
+ m.fadeInFocusBitmap = m.top.findNode("fadeInFocusBitmap")
+
if m.global.session.user.settings["ui.home.splashBackground"] = true
m.backdrop = m.top.findNode("backdrop")
m.backdrop.uri = buildURL("/Branding/Splashscreen?format=jpg&foregroundLayer=0.15&fillWidth=1280&width=1280&fillHeight=720&height=720&tag=splash")
@@ -16,11 +20,14 @@ sub init()
end sub
sub refresh()
- m.top.findNode("homeRows").callFunc("updateHomeRows")
+ m.homeRows.focusBitmapBlendColor = "0xFFFFFFFF"
+ m.homeRows.callFunc("updateHomeRows")
end sub
sub loadLibraries()
- m.top.findNode("homeRows").callFunc("loadLibraries")
+ m.homeRows.focusBitmapBlendColor = "0xFFFFFF00"
+ m.homeRows.callFunc("loadLibraries")
+ m.fadeInFocusBitmap.control = "start"
end sub
' JFScreen hook that gets ran as needed.
diff --git a/components/home/Home.xml b/components/home/Home.xml
index 9ce89fcf5..4e06e0013 100644
--- a/components/home/Home.xml
+++ b/components/home/Home.xml
@@ -2,8 +2,12 @@
-
+
+
+
+
+
diff --git a/components/home/HomeRow.xml b/components/home/HomeRow.xml
index c846e3f20..8d1db2cc4 100644
--- a/components/home/HomeRow.xml
+++ b/components/home/HomeRow.xml
@@ -2,6 +2,7 @@
+
\ No newline at end of file
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index f3a4aa2c8..d1b3be413 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,6 +1,8 @@
import "pkg:/source/utils/misc.bs"
import "pkg:/source/constants/HomeRowItemSizes.bs"
+const FOCUS_RESIZE_WAIT_TIME = 2
+
sub init()
m.top.itemComponentName = "HomeItem"
' how many rows are visible on the screen
@@ -11,9 +13,14 @@ sub init()
m.top.showRowLabel = [true]
m.top.rowLabelOffset = [0, 20]
- m.top.showRowCounter = [true]
+ ' 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")
- m.homeSections = {}
+ m.loadingTimer = createObject("roSGNode", "Timer")
+ m.loadingTimer.duration = FOCUS_RESIZE_WAIT_TIME
+ m.loadingTimer.observeField("fire", "loadingTimerComplete")
updateSize()
@@ -25,7 +32,7 @@ sub init()
m.LoadLibrariesTask = createObject("roSGNode", "LoadItemsTask")
m.LoadLibrariesTask.observeField("content", "onLibrariesLoaded")
- ' set up tesk nodes for other rows
+ ' set up task nodes for other rows
m.LoadContinueWatchingTask = createObject("roSGNode", "LoadItemsTask")
m.LoadContinueWatchingTask.itemsToLoad = "continue"
@@ -56,20 +63,21 @@ sub updateSize()
' spacing between items in a row
m.top.rowItemSpacing = [20, 0]
+ ' Default size to wide poster, the most used size
+ m.top.rowItemSize = homeRowItemSizes.WIDE_POSTER
+
m.top.visible = true
end sub
' processUserSections: Loop through user's chosen home section settings and generate the content for each row
'
-' @return {dynamic} content node filled with child nodes for each row
-function processUserSections() as dynamic
+sub processUserSections()
loadedSections = 0
- content = CreateObject("roSGNode", "ContentNode")
' Add sections in order based on user settings
for i = 0 to 6
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
- sectionLoaded = addHomeSection(content, sectionName)
+ sectionLoaded = addHomeSection(sectionName)
' Count how many sections with data are loaded
if sectionLoaded then loadedSections++
@@ -83,12 +91,12 @@ function processUserSections() as dynamic
end if
end for
- ' Favorites isn't an option on Web settings, so we must manually add it for now
- addHomeSection(content, "favorites")
-
- return content
-end function
+ ' 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
'
@@ -98,126 +106,159 @@ sub onLibrariesLoaded()
m.LoadLibrariesTask.unobserveField("content")
m.LoadLibrariesTask.content = []
- content = processUserSections()
-
- setRowItemSizes()
-
- m.top.content = content
+ processUserSections()
end sub
-' Removes a home section from the home rows
-sub removeHomeSection(sectionType as string)
- sectionName = LCase(sectionType)
-
- removedSection = m.homeSections[sectionName]
+' 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(" ", "")
- if not isValid(removedSection) then return
- if not isValid(removedSection.index) then return
+ sectionIndex = 0
+ indexLatestMediaSection = 0
- m.homeSections.Delete(sectionName)
+ for i = 0 to 6
+ settingSectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
+ if settingSectionName = "latestmedia"
+ indexLatestMediaSection = i
+ end if
- for each section in m.homeSections
- if m.homeSections[section].index > removedSection.index
- m.homeSections[section].index--
+ if settingSectionName = searchSectionName
+ sectionIndex = i
end if
end for
- m.top.content.removeChildIndex(removedSection.index)
+ ' 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)
- setRowItemSizes()
+ m.top.content.removeChildIndex(sectionIndexToRemove)
end sub
-' setRowItemSizes: Loops through all home sections and sets the correct item sizes per row
+' setRowItemSize: Loops through all home sections and sets the correct item sizes per row
'
-sub setRowItemSizes()
- newSizeArray = CreateObject("roArray", m.homeSections.count(), false)
+sub setRowItemSize()
+ if not isValid(m.top.content) then return
- for each section in m.homeSections
- newSizeArray[m.homeSections[section].index] = m.homeSections[section].imagesize
+ 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
end sub
-' Adds a new home section to the home rows.
-' Returns a boolean indicating whether the section was handled.
-function addHomeSection(content as dynamic, sectionName as string) as boolean
+' loadingTimerComplete: Event handler for when loading wait time has expired
+'
+sub loadingTimerComplete()
+ ' Show the row counter to prevent flicker
+ m.top.showRowCounter = [true]
+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
' Poster size library items
- if sectionName = "livetv"
- createLiveTVRow(content)
+ if sectionType = "livetv"
+ createLiveTVRow()
return true
end if
' Poster size library items
- if sectionName = "smalllibrarytiles"
- createLibraryRow(content)
+ if sectionType = "smalllibrarytiles"
+ createLibraryRow()
return true
end if
' Continue Watching items
- if sectionName = "resume"
- createContinueWatchingRow(content)
+ if sectionType = "resume"
+ createContinueWatchingRow()
return true
end if
' Next Up items
- if sectionName = "nextup"
- createNextUpRow(content)
+ if sectionType = "nextup"
+ createNextUpRow()
return true
end if
' Latest items in each library
- if sectionName = "latestmedia"
- createLatestInRows(content)
+ if sectionType = "latestmedia"
+ createLatestInRows()
return true
end if
' Favorite Items
- if sectionName = "favorites"
- createFavoritesRow(content)
+ if sectionType = "favorites"
+ createFavoritesRow()
return true
end if
return false
end function
-' Create a row displaying the user's libraries
-sub createLibraryRow(content as dynamic)
+' createLibraryRow: Creates a row displaying the user's libraries
+'
+sub createLibraryRow()
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
- mediaRow = content.CreateChild("HomeRow")
- mediaRow.title = tr("My Media")
-
- sectionIndex = m.homeSections.count()
-
- isUpdate = false
-
- if m.homeSections.doesExist("library")
- sectionIndex = m.homeSections.library.index
- isUpdate = true
- end if
+ sectionName = tr("My Media")
- m.homeSections.AddReplace("library", {
- imageSize: homeRowItemSizes.WIDE_POSTER,
- index: sectionIndex
- })
+ row = CreateObject("roSGNode", "HomeRow")
+ row.title = sectionName
+ row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
+ row.cursorSize = homeRowItemSizes.WIDE_POSTER
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
for each item in filteredMedia
- mediaRow.appendChild(item)
+ row.appendChild(item)
end for
- if isUpdate
- m.top.content.replaceChild(mediaRow, m.homeSections.library.index)
+ ' Row already exists, replace it with new content
+ if sectionExists(sectionName)
+ m.top.content.replaceChild(row, getSectionIndex(sectionName))
+ setRowItemSize()
return
end if
- content.appendChild(mediaRow)
+ ' Row does not exist, insert it into the home view
+ m.top.content.insertChild(row, getOriginalSectionIndex("smalllibrarytiles"))
+ setRowItemSize()
end sub
-' Create a row displaying latest items in each of the user's libraries
-sub createLatestInRows(content as dynamic)
+' createLatestInRows: Creates a row displaying latest items in each of the user's libraries
+'
+sub createLatestInRows()
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
@@ -226,29 +267,21 @@ sub createLatestInRows(content as dynamic)
for each lib in filteredLatest
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program"
- sectionName = "latestin" + LCase(lib.name).Replace(" ", "")
+ if not sectionExists(tr("Latest in") + " " + lib.name + " >")
+ imagesize = homeRowItemSizes.WIDE_POSTER
- if not m.homeSections.doesExist(sectionName)
- latestInRow = content.CreateChild("HomeRow")
- latestInRow.title = tr("Latest in") + " " + lib.name + " >"
- sectionIndex = m.homeSections.count()
- else
- sectionIndex = m.homeSections[sectionName].index
- end if
-
- imagesize = homeRowItemSizes.WIDE_POSTER
+ if LCase(lib.collectionType) = "movies"
+ imagesize = homeRowItemSizes.MOVIE_POSTER
+ else if LCase(lib.collectionType) = "music"
+ imagesize = homeRowItemSizes.MUSIC_ALBUM
+ end if
- if LCase(lib.collectionType) = "movies"
- imagesize = homeRowItemSizes.MOVIE_POSTER
- else if LCase(lib.collectionType) = "music"
- imagesize = homeRowItemSizes.MUSIC_ALBUM
+ row = CreateObject("roSGNode", "HomeRow")
+ row.title = tr("Latest in") + " " + lib.name + " >"
+ row.imageWidth = imagesize[0]
+ row.cursorSize = imagesize
end if
- m.homeSections.AddReplace(sectionName, {
- imageSize: imagesize,
- index: sectionIndex
- })
-
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
@@ -263,101 +296,105 @@ sub createLatestInRows(content as dynamic)
end for
end sub
-' Create a row displaying the live tv now on section
-sub createLiveTVRow(content as dynamic)
- if not m.homeSections.doesExist("livetv")
- contentRow = content.CreateChild("HomeRow")
- contentRow.title = tr("On Now")
- end if
+' 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
- sectionIndex = m.homeSections.count()
+ searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
- if m.homeSections.doesExist("livetv")
- sectionIndex = m.homeSections.livetv.index
- end if
+ homeSections = m.top.content.getChildren(-1, 0)
+
+ for each section in homeSections
+ if LCase(section.title).Replace(" ", "") = searchSectionTitle
+ return true
+ end if
+ end for
- m.homeSections.AddReplace("livetv", {
- imageSize: homeRowItemSizes.WIDE_POSTER,
- index: sectionIndex
- })
+ return false
+end function
- m.LoadOnNowTask.observeField("content", "updateOnNowItems")
- m.LoadOnNowTask.control = "RUN"
-end sub
+' 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
-' Create a row displaying items the user can continue watching
-sub createContinueWatchingRow(content as dynamic)
- if not m.homeSections.doesExist("resume")
- continueWatchingRow = content.CreateChild("HomeRow")
- continueWatchingRow.title = tr("Continue Watching")
- end if
- sectionIndex = m.homeSections.count()
+ searchSectionTitle = LCase(sectionTitle).Replace(" ", "")
- if m.homeSections.doesExist("resume")
- sectionIndex = m.homeSections.resume.index
- end if
+ homeSections = m.top.content.getChildren(-1, 0)
- m.homeSections.AddReplace("resume", {
- imageSize: homeRowItemSizes.WIDE_POSTER,
- index: sectionIndex
- })
+ 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()
' Load the Continue Watching Data
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
m.LoadContinueWatchingTask.control = "RUN"
end sub
-' Create a row displaying next episodes up to watch
-sub createNextUpRow(content as dynamic)
- if not m.homeSections.doesExist("nextup")
- nextUpRow = content.CreateChild("HomeRow")
- nextUpRow.title = tr("Next Up >")
- end if
- sectionIndex = m.homeSections.count()
-
- if m.homeSections.doesExist("nextup")
- sectionIndex = m.homeSections.nextup.index
+' 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
- m.homeSections.AddReplace("nextup", {
- imageSize: homeRowItemSizes.WIDE_POSTER,
- index: sectionIndex
- })
-
' Load the Next Up Data
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
m.LoadNextUpTask.control = "RUN"
end sub
-' Create a row displaying items from the user's favorites list
-sub createFavoritesRow(content as dynamic)
- if not m.homeSections.doesExist("favorites")
- favoritesRow = content.CreateChild("HomeRow")
- favoritesRow.title = tr("Favorites")
- end if
-
- sectionIndex = m.homeSections.count()
-
- if m.homeSections.doesExist("favorites")
- sectionIndex = m.homeSections.favorites.index
- end if
-
- m.homeSections.AddReplace("favorites", {
- imageSize: homeRowItemSizes.WIDE_POSTER,
- index: sectionIndex
- })
-
+' createFavoritesRow: Creates a row displaying items from the user's favorites list
+'
+sub createFavoritesRow()
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
end sub
-' Update home row data
+' updateHomeRows: Update function exposed to outside components
+'
sub updateHomeRows()
+ ' Hide the row counter to prevent flicker. We'll show it once loading timer fires
+ m.top.showRowCounter = [false]
processUserSections()
- setRowItemSizes()
end sub
+' updateFavoritesItems: Processes LoadFavoritesTask content. Removes, Creates, or Updates favorites row as needed
+'
sub updateFavoritesItems()
itemData = m.LoadFavoritesTask.content
m.LoadFavoritesTask.unobserveField("content")
@@ -365,44 +402,43 @@ sub updateFavoritesItems()
if itemData = invalid then return
- rowIndex = m.homeSections.favorites.index
+ sectionName = tr("Favorites")
if itemData.count() < 1
- removeHomeSection("favorites")
+ removeHomeSection(sectionName)
return
- else
- ' remake row using the new data
- row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("Favorites")
-
- for each item in itemData
- usePoster = true
+ end if
- if lcase(item.type) = "episode" or lcase(item.type) = "audio" or lcase(item.type) = "musicartist"
- usePoster = false
- end if
+ ' remake row using the new data
+ row = CreateObject("roSGNode", "HomeRow")
+ row.title = sectionName
+ row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
+ row.cursorSize = homeRowItemSizes.WIDE_POSTER
- item.usePoster = usePoster
- item.imageWidth = row.imageWidth
- row.appendChild(item)
- end for
+ for each item in itemData
+ usePoster = true
- if isValid(m.top.content.getChild(rowIndex))
- m.top.content.replaceChild(row, rowIndex)
- else
+ if lcase(item.type) = "episode" or lcase(item.type) = "audio" or lcase(item.type) = "musicartist"
+ usePoster = false
+ end if
- for each section in m.homeSections
- if m.homeSections[section].index >= m.top.content.getChildCount()
- m.homeSections[section].index++
- end if
- end for
+ item.usePoster = usePoster
+ item.imageWidth = row.imageWidth
+ row.appendChild(item)
+ end for
- m.homeSections.favorites.index = m.top.content.getChildCount()
- m.top.content.insertChild(row, m.top.content.getChildCount())
- end if
+ if sectionExists(sectionName)
+ m.top.content.replaceChild(row, getSectionIndex(sectionName))
+ setRowItemSize()
+ return
end if
+
+ m.top.content.insertChild(row, getSectionIndex(sectionName))
+ setRowItemSize()
end sub
+' updateContinueWatchingItems: Processes LoadContinueWatchingTask content. Removes, Creates, or Updates continue watching row as needed
+'
sub updateContinueWatchingItems()
itemData = m.LoadContinueWatchingTask.content
m.LoadContinueWatchingTask.unobserveField("content")
@@ -410,14 +446,20 @@ sub updateContinueWatchingItems()
if itemData = invalid then return
+ sectionName = tr("Continue Watching")
+
if itemData.count() < 1
- removeHomeSection("resume")
+ removeHomeSection(sectionName)
return
end if
+ sectionName = tr("Continue Watching")
+
' remake row using the new data
row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("Continue Watching")
+ row.title = sectionName
+ row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
+ row.cursorSize = homeRowItemSizes.WIDE_POSTER
for each item in itemData
if isValid(item.json) and isValid(item.json.UserData) and isValid(item.json.UserData.PlayedPercentage)
@@ -429,10 +471,20 @@ sub updateContinueWatchingItems()
row.appendChild(item)
end for
- ' replace the old row
- m.top.content.replaceChild(row, m.homeSections.resume.index)
+ ' 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()
end sub
+' updateNextUpItems: Processes LoadNextUpTask content. Removes, Creates, or Updates next up row as needed
+'
sub updateNextUpItems()
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
@@ -441,24 +493,40 @@ sub updateNextUpItems()
if itemData = invalid then return
+ sectionName = tr("Next Up") + " >"
+
if itemData.count() < 1
- removeHomeSection("nextup")
+ removeHomeSection(sectionName)
return
- else
- ' remake row using the new data
- row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("Next Up") + " >"
- for each item in itemData
- item.usePoster = row.usePoster
- item.imageWidth = row.imageWidth
- row.appendChild(item)
- end for
+ 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
- ' replace the old row
- m.top.content.replaceChild(row, m.homeSections.nextup.index)
+ for each item in itemData
+ 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
end if
+
+ ' Row does not exist, insert it into the home view
+ m.top.content.insertChild(row, getSectionIndex(sectionName))
+ setRowItemSize()
end sub
+' updateLatestItems: Processes LoadItemsTask content. Removes, Creates, or Updates latest in {library} row as needed
+'
+' @param {dynamic} msg - LoadItemsTask
sub updateLatestItems(msg)
itemData = msg.GetData()
@@ -468,55 +536,46 @@ sub updateLatestItems(msg)
if itemData = invalid then return
- sectionName = "latestin" + LCase(node.metadata.title).Replace(" ", "")
+ sectionName = tr("Latest in") + " " + node.metadata.title + " >"
if itemData.count() < 1
removeHomeSection(sectionName)
return
- else
- ' remake row using new data
- row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("Latest in") + " " + node.metadata.title + " >"
- row.usePoster = true
-
- for each item in itemData
- item.usePoster = row.usePoster
- item.imageWidth = m.homeSections[sectionName].imageSize[0]
- row.appendChild(item)
- end for
-
- rowIndex = m.homeSections[sectionName].index
-
- if isValid(rowIndex) and isValid(m.top.content.getChild(rowIndex))
- ' Replace the old row
- m.top.content.replaceChild(row, rowIndex)
- else
- firstLatestHomeSectionIndex = m.homeSections.count() - 1
-
- for each section in m.homeSections
- if LCase(Left(section, 6)) = "latest"
- if m.homeSections[section].index < firstLatestHomeSectionIndex
- firstLatestHomeSectionIndex = m.homeSections[section].index
- end if
- end if
- end for
+ end if
- for each section in m.homeSections
- if m.homeSections[section].index >= firstLatestHomeSectionIndex
- m.homeSections[section].index++
- end if
- end for
+ imagesize = homeRowItemSizes.WIDE_POSTER
- m.homeSections[sectionName].index = firstLatestHomeSectionIndex
- m.top.content.insertChild(row, firstLatestHomeSectionIndex)
- end if
+ if LCase(node.metadata.contentType) = "movies"
+ imagesize = homeRowItemSizes.MOVIE_POSTER
+ else if LCase(node.metadata.contentType) = "music"
+ imagesize = homeRowItemSizes.MUSIC_ALBUM
+ end if
- setRowItemSizes()
+ ' remake row using new data
+ row = CreateObject("roSGNode", "HomeRow")
+ row.title = sectionName
+ row.imageWidth = imagesize[0]
+ row.cursorSize = imagesize
+ for each item in itemData
+ item.usePoster = row.usePoster
+ item.imageWidth = row.imageWidth
+ row.appendChild(item)
+ end for
+ if sectionExists(sectionName)
+ ' Row already exists, replace it with new content
+ m.top.content.replaceChild(row, getSectionIndex(sectionName))
+ setRowItemSize()
+ return
end if
+
+ m.top.content.insertChild(row, getOriginalSectionIndex("latestmedia"))
+ setRowItemSize()
end sub
+' updateOnNowItems: Processes LoadOnNowTask content. Removes, Creates, or Updates latest in on now row as needed
+'
sub updateOnNowItems()
itemData = m.LoadOnNowTask.content
m.LoadOnNowTask.unobserveField("content")
@@ -524,37 +583,44 @@ sub updateOnNowItems()
if itemData = invalid then return
+ sectionName = tr("On Now")
+
if itemData.count() < 1
- removeHomeSection("livetv")
+ removeHomeSection(sectionName)
return
- else
- ' remake row using the new data
- row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("On Now")
- row.imageWidth = homeRowItemSizes.WIDE_POSTER[0]
- 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]
-
- m.homeSections.livetv.imageSize = homeRowItemSizes.MOVIE_POSTER
- end if
+ end if
- item.usePoster = row.usePoster
- item.imageWidth = row.imageWidth
- row.appendChild(item)
- end for
+ ' 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
- ' replace the old row
- m.top.content.replaceChild(row, m.homeSections.livetv.index)
+ for each item in itemData
+ row.usePoster = false
- ' We may now have different poster sizes. Reset the row item sizes
- setRowItemSizes()
+ 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
+ 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
end if
+
+ ' Row does not exist, insert it into the home view
+ m.top.content.insertChild(row, getOriginalSectionIndex("livetv"))
+ setRowItemSize()
end sub
sub itemSelected()
From 9cea33dbc7b13dc7d00f422a6ce7021f43bde474 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 08:29:42 -0500
Subject: [PATCH 14/20] Removed dead code. Fix Latest in TV Shows posters
---
components/home/HomeRows.bs | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index d1b3be413..a4f09e454 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -266,22 +266,6 @@ sub createLatestInRows()
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"
-
- if not sectionExists(tr("Latest in") + " " + lib.name + " >")
- imagesize = homeRowItemSizes.WIDE_POSTER
-
- if LCase(lib.collectionType) = "movies"
- imagesize = homeRowItemSizes.MOVIE_POSTER
- else if LCase(lib.collectionType) = "music"
- imagesize = homeRowItemSizes.MUSIC_ALBUM
- end if
-
- row = CreateObject("roSGNode", "HomeRow")
- row.title = tr("Latest in") + " " + lib.name + " >"
- row.imageWidth = imagesize[0]
- row.cursorSize = imagesize
- end if
-
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
@@ -556,6 +540,7 @@ sub updateLatestItems(msg)
row.title = sectionName
row.imageWidth = imagesize[0]
row.cursorSize = imagesize
+ row.usePoster = true
for each item in itemData
item.usePoster = row.usePoster
From 551df567e70282f21be864f3016dd5b86ad3ce6b Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 08:47:35 -0500
Subject: [PATCH 15/20] Rename loading timer const
---
components/home/HomeRows.bs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index a4f09e454..a672783dc 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -1,7 +1,7 @@
import "pkg:/source/utils/misc.bs"
import "pkg:/source/constants/HomeRowItemSizes.bs"
-const FOCUS_RESIZE_WAIT_TIME = 2
+const LOADING_WAIT_TIME = 2
sub init()
m.top.itemComponentName = "HomeItem"
@@ -19,7 +19,7 @@ sub init()
m.top.content = CreateObject("roSGNode", "ContentNode")
m.loadingTimer = createObject("roSGNode", "Timer")
- m.loadingTimer.duration = FOCUS_RESIZE_WAIT_TIME
+ m.loadingTimer.duration = LOADING_WAIT_TIME
m.loadingTimer.observeField("fire", "loadingTimerComplete")
updateSize()
From 685a623607807c2cce60a7b4ada5ec647b97e684 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 18:30:33 -0500
Subject: [PATCH 16/20] Add valid check to contentType
Value can be invalid for trailer libraries
---
components/home/HomeRows.bs | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index a672783dc..29cb6d986 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -529,10 +529,12 @@ sub updateLatestItems(msg)
imagesize = homeRowItemSizes.WIDE_POSTER
- if LCase(node.metadata.contentType) = "movies"
- imagesize = homeRowItemSizes.MOVIE_POSTER
- else if LCase(node.metadata.contentType) = "music"
- imagesize = homeRowItemSizes.MUSIC_ALBUM
+ 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
end if
' remake row using new data
From fe0f02bbcc50017e8486b0fad07b91ac4f9e0e75 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 19:31:09 -0500
Subject: [PATCH 17/20] Defensive code for if no custom prefs returned
---
source/utils/session.bs | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/source/utils/session.bs b/source/utils/session.bs
index e5604c02d..a468a5605 100644
--- a/source/utils/session.bs
+++ b/source/utils/session.bs
@@ -223,6 +223,17 @@ namespace session
unset_user_setting("display.livetv.landing")
end if
else
+ ' User has no custom prefs. Save default home section values.
+ session.user.SaveUserHomeSections({
+ homesection0: "smalllibrarytiles",
+ homesection1: "resume",
+ homesection2: "nextup",
+ homesection3: "latestmedia",
+ homesection4: "livetv",
+ homesection5: "none",
+ homesection6: "none"
+ })
+
unset_user_setting("display.livetv.landing")
end if
end sub
From 687d51892b5c09db8d45ade71e2603fc93e5d39c Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 19:34:46 -0500
Subject: [PATCH 18/20] Set row item size after removing row
---
components/home/HomeRows.bs | 1 +
1 file changed, 1 insertion(+)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 29cb6d986..dddaad6cd 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -158,6 +158,7 @@ sub removeHomeSection(sectionTitleToRemove as string)
sectionIndexToRemove = getSectionIndex(sectionTitle)
m.top.content.removeChildIndex(sectionIndexToRemove)
+ setRowItemSize()
end sub
' setRowItemSize: Loops through all home sections and sets the correct item sizes per row
From 2832799c82097f9a7dc3516353a000a7e96f3d9a Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Sat, 2 Dec 2023 22:10:25 -0500
Subject: [PATCH 19/20] Create short circuit if content loads faster than wait
time
---
components/home/HomeRows.bs | 51 ++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 7 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index dddaad6cd..894e5e47e 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -72,6 +72,7 @@ end sub
' processUserSections: Loop through user's chosen home section settings and generate the content for each row
'
sub processUserSections()
+ m.expectedRowCount = 0
loadedSections = 0
' Add sections in order based on user settings
@@ -174,13 +175,21 @@ sub setRowItemSize()
end for
m.top.rowItemSize = newSizeArray
+
+ ' If we have the expected number of content rows, stop the loading timer and run the complete function
+ if m.expectedRowCount = homeSections.count()
+ m.loadingTimer.control = "stop"
+ loadingTimerComplete()
+ end if
end sub
' loadingTimerComplete: Event handler for when loading wait time has expired
'
sub loadingTimerComplete()
- ' Show the row counter to prevent flicker
- m.top.showRowCounter = [true]
+ if not m.top.showRowCounter[0]
+ ' Show the row counter to prevent flicker
+ m.top.showRowCounter = [true]
+ end if
end sub
' addHomeSection: Adds a new home section to the home rows.
@@ -233,6 +242,8 @@ sub createLibraryRow()
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
+ m.expectedRowCount++
+
sectionName = tr("My Media")
row = CreateObject("roSGNode", "HomeRow")
@@ -271,6 +282,8 @@ sub createLatestInRows()
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
+ m.expectedRowCount++
+
metadata = { "title": lib.name }
metadata.Append({ "contentType": lib.json.CollectionType })
loadLatest.metadata = metadata
@@ -333,6 +346,7 @@ end function
' createLiveTVRow: Creates a row displaying the live tv now on section
'
sub createLiveTVRow()
+ m.expectedRowCount++
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end sub
@@ -340,6 +354,7 @@ end sub
' createContinueWatchingRow: Creates a row displaying items the user can continue watching
'
sub createContinueWatchingRow()
+ m.expectedRowCount++
' Load the Continue Watching Data
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
m.LoadContinueWatchingTask.control = "RUN"
@@ -348,6 +363,7 @@ end sub
' createNextUpRow: Creates a row displaying next episodes up to watch
'
sub createNextUpRow()
+ m.expectedRowCount++
sectionName = tr("Next Up") + ">"
if not sectionExists(sectionName)
@@ -365,6 +381,7 @@ end sub
' createFavoritesRow: Creates a row displaying items from the user's favorites list
'
sub createFavoritesRow()
+ m.expectedRowCount++
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
@@ -385,11 +402,15 @@ sub updateFavoritesItems()
m.LoadFavoritesTask.unobserveField("content")
m.LoadFavoritesTask.content = []
- if itemData = invalid then return
+ if itemData = invalid
+ m.expectedRowCount--
+ return
+ end if
sectionName = tr("Favorites")
if itemData.count() < 1
+ m.expectedRowCount--
removeHomeSection(sectionName)
return
end if
@@ -429,11 +450,15 @@ sub updateContinueWatchingItems()
m.LoadContinueWatchingTask.unobserveField("content")
m.LoadContinueWatchingTask.content = []
- if itemData = invalid then return
+ if not isValid(itemData)
+ m.expectedRowCount--
+ return
+ end if
sectionName = tr("Continue Watching")
if itemData.count() < 1
+ m.expectedRowCount--
removeHomeSection(sectionName)
return
end if
@@ -476,11 +501,15 @@ sub updateNextUpItems()
m.LoadNextUpTask.content = []
m.LoadNextUpTask.control = "STOP"
- if itemData = invalid then return
+ if itemData = invalid
+ m.expectedRowCount--
+ return
+ end if
sectionName = tr("Next Up") + " >"
if itemData.count() < 1
+ m.expectedRowCount--
removeHomeSection(sectionName)
return
end if
@@ -519,11 +548,15 @@ sub updateLatestItems(msg)
node.unobserveField("content")
node.content = []
- if itemData = invalid then return
+ if itemData = invalid
+ m.expectedRowCount--
+ return
+ end if
sectionName = tr("Latest in") + " " + node.metadata.title + " >"
if itemData.count() < 1
+ m.expectedRowCount--
removeHomeSection(sectionName)
return
end if
@@ -569,11 +602,15 @@ sub updateOnNowItems()
m.LoadOnNowTask.unobserveField("content")
m.LoadOnNowTask.content = []
- if itemData = invalid then return
+ if not isValid(itemData)
+ m.expectedRowCount--
+ return
+ end if
sectionName = tr("On Now")
if itemData.count() < 1
+ m.expectedRowCount--
removeHomeSection(sectionName)
return
end if
From 7e7ac107afcce46ecf3bfa56efb1891d0f263abd Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Mon, 4 Dec 2023 12:18:59 -0500
Subject: [PATCH 20/20] Create expected & processed counts. Hook short circuit
to their values
Code by cewert
---
components/home/HomeRows.bs | 93 ++++++++++++++++---------------------
1 file changed, 41 insertions(+), 52 deletions(-)
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index 894e5e47e..b888da392 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -72,13 +72,33 @@ end sub
' processUserSections: Loop through user's chosen home section settings and generate the content for each row
'
sub processUserSections()
- m.expectedRowCount = 0
- loadedSections = 0
+ 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
- ' Add sections in order based on user settings
+ ' Add home sections in order based on user settings
+ loadedSections = 0
for i = 0 to 6
sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()])
- sectionLoaded = addHomeSection(sectionName)
+ sectionLoaded = false
+ if sectionName <> "none"
+ sectionLoaded = addHomeSection(sectionName)
+ end if
' Count how many sections with data are loaded
if sectionLoaded then loadedSections++
@@ -173,11 +193,10 @@ sub setRowItemSize()
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 the expected number of content rows, stop the loading timer and run the complete function
- if m.expectedRowCount = homeSections.count()
+ ' 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
@@ -233,17 +252,19 @@ function addHomeSection(sectionType as string) as boolean
return true
end if
+ ' This section type isn't supported.
+ ' Count it as processed since we aren't going to do anything else with it
+ m.processedRowCount++
return false
end function
' createLibraryRow: Creates a row displaying the user's libraries
'
sub createLibraryRow()
+ m.processedRowCount++
' Ensure we have data
if not isValidAndNotEmpty(m.libraryData) then return
- m.expectedRowCount++
-
sectionName = tr("My Media")
row = CreateObject("roSGNode", "HomeRow")
@@ -275,15 +296,12 @@ sub createLatestInRows()
if not isValidAndNotEmpty(m.libraryData) then return
' create a "Latest In" row for each library
- filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes)
- for each lib in filteredLatest
+ for each lib in m.filteredLatest
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program"
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
- m.expectedRowCount++
-
metadata = { "title": lib.name }
metadata.Append({ "contentType": lib.json.CollectionType })
loadLatest.metadata = metadata
@@ -346,7 +364,6 @@ end function
' createLiveTVRow: Creates a row displaying the live tv now on section
'
sub createLiveTVRow()
- m.expectedRowCount++
m.LoadOnNowTask.observeField("content", "updateOnNowItems")
m.LoadOnNowTask.control = "RUN"
end sub
@@ -354,7 +371,6 @@ end sub
' createContinueWatchingRow: Creates a row displaying items the user can continue watching
'
sub createContinueWatchingRow()
- m.expectedRowCount++
' Load the Continue Watching Data
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")
m.LoadContinueWatchingTask.control = "RUN"
@@ -363,7 +379,6 @@ end sub
' createNextUpRow: Creates a row displaying next episodes up to watch
'
sub createNextUpRow()
- m.expectedRowCount++
sectionName = tr("Next Up") + ">"
if not sectionExists(sectionName)
@@ -381,7 +396,6 @@ end sub
' createFavoritesRow: Creates a row displaying items from the user's favorites list
'
sub createFavoritesRow()
- m.expectedRowCount++
' Load the Favorites Data
m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
m.LoadFavoritesTask.control = "RUN"
@@ -398,19 +412,14 @@ end sub
' updateFavoritesItems: Processes LoadFavoritesTask content. Removes, Creates, or Updates favorites row as needed
'
sub updateFavoritesItems()
+ m.processedRowCount++
itemData = m.LoadFavoritesTask.content
m.LoadFavoritesTask.unobserveField("content")
m.LoadFavoritesTask.content = []
- if itemData = invalid
- m.expectedRowCount--
- return
- end if
-
sectionName = tr("Favorites")
- if itemData.count() < 1
- m.expectedRowCount--
+ if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
return
end if
@@ -446,19 +455,14 @@ end sub
' updateContinueWatchingItems: Processes LoadContinueWatchingTask content. Removes, Creates, or Updates continue watching row as needed
'
sub updateContinueWatchingItems()
+ m.processedRowCount++
itemData = m.LoadContinueWatchingTask.content
m.LoadContinueWatchingTask.unobserveField("content")
m.LoadContinueWatchingTask.content = []
- if not isValid(itemData)
- m.expectedRowCount--
- return
- end if
-
sectionName = tr("Continue Watching")
- if itemData.count() < 1
- m.expectedRowCount--
+ if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
return
end if
@@ -496,20 +500,15 @@ end sub
' updateNextUpItems: Processes LoadNextUpTask content. Removes, Creates, or Updates next up row as needed
'
sub updateNextUpItems()
+ m.processedRowCount++
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
m.LoadNextUpTask.content = []
m.LoadNextUpTask.control = "STOP"
- if itemData = invalid
- m.expectedRowCount--
- return
- end if
-
sectionName = tr("Next Up") + " >"
- if itemData.count() < 1
- m.expectedRowCount--
+ if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
return
end if
@@ -542,21 +541,16 @@ end sub
'
' @param {dynamic} msg - LoadItemsTask
sub updateLatestItems(msg)
+ m.processedRowCount++
itemData = msg.GetData()
node = msg.getRoSGNode()
node.unobserveField("content")
node.content = []
- if itemData = invalid
- m.expectedRowCount--
- return
- end if
-
sectionName = tr("Latest in") + " " + node.metadata.title + " >"
- if itemData.count() < 1
- m.expectedRowCount--
+ if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
return
end if
@@ -598,19 +592,14 @@ end sub
' updateOnNowItems: Processes LoadOnNowTask content. Removes, Creates, or Updates latest in on now row as needed
'
sub updateOnNowItems()
+ m.processedRowCount++
itemData = m.LoadOnNowTask.content
m.LoadOnNowTask.unobserveField("content")
m.LoadOnNowTask.content = []
- if not isValid(itemData)
- m.expectedRowCount--
- return
- end if
-
sectionName = tr("On Now")
- if itemData.count() < 1
- m.expectedRowCount--
+ if not isValidAndNotEmpty(itemData)
removeHomeSection(sectionName)
return
end if