Add setting to match web's home sections
This commit is contained in:
parent
06af8b2030
commit
867667f516
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -18,4 +18,4 @@
|
||||||
"docs/api/**": true
|
"docs/api/**": true
|
||||||
},
|
},
|
||||||
"brightscriptcomment.addExtraAtStartAndEnd": false
|
"brightscriptcomment.addExtraAtStartAndEnd": false
|
||||||
}
|
}
|
5
components/ImageSizes.bs
Normal file
5
components/ImageSizes.bs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
namespace imageSizes
|
||||||
|
const WIDE_POSTER = [464, 331]
|
||||||
|
const MOVIE_POSTER = [188, 331]
|
||||||
|
const MUSIC_ALBUM = [261, 331]
|
||||||
|
end namespace
|
|
@ -1,4 +1,9 @@
|
||||||
import "pkg:/source/utils/misc.bs"
|
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()
|
sub init()
|
||||||
m.top.itemComponentName = "HomeItem"
|
m.top.itemComponentName = "HomeItem"
|
||||||
|
@ -14,6 +19,11 @@ sub init()
|
||||||
|
|
||||||
m.homeSections = {}
|
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()
|
updateSize()
|
||||||
|
|
||||||
m.top.setfocus(true)
|
m.top.setfocus(true)
|
||||||
|
@ -190,7 +200,7 @@ sub createLibraryRow(content as dynamic)
|
||||||
mediaRow.title = tr("My Media")
|
mediaRow.title = tr("My Media")
|
||||||
|
|
||||||
m.homeSections.AddReplace("library", {
|
m.homeSections.AddReplace("library", {
|
||||||
imageSize: [464, 331],
|
imageSize: imageSizes.WIDE_POSTER,
|
||||||
index: m.homeSections.count()
|
index: m.homeSections.count()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -212,12 +222,12 @@ sub createLatestInRows(content as dynamic)
|
||||||
latestInRow = content.CreateChild("HomeRow")
|
latestInRow = content.CreateChild("HomeRow")
|
||||||
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
|
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
|
||||||
|
|
||||||
imagesize = [464, 331]
|
imagesize = imageSizes.WIDE_POSTER
|
||||||
|
|
||||||
if LCase(lib.collectionType) = "movies"
|
if LCase(lib.collectionType) = "movies"
|
||||||
imagesize = [188, 331]
|
imagesize = imageSizes.MOVIE_POSTER
|
||||||
else if LCase(lib.collectionType) = "music"
|
else if LCase(lib.collectionType) = "music"
|
||||||
imagesize = [261, 331]
|
imagesize = imageSizes.MUSIC_ALBUM
|
||||||
end if
|
end if
|
||||||
|
|
||||||
m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
|
m.homeSections.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), {
|
||||||
|
@ -244,7 +254,7 @@ sub createLiveTVRow(content as dynamic)
|
||||||
contentRow = content.CreateChild("HomeRow")
|
contentRow = content.CreateChild("HomeRow")
|
||||||
contentRow.title = tr("On Now")
|
contentRow.title = tr("On Now")
|
||||||
m.homeSections.AddReplace("livetv", {
|
m.homeSections.AddReplace("livetv", {
|
||||||
imageSize: [464, 331],
|
imageSize: imageSizes.WIDE_POSTER,
|
||||||
index: m.homeSections.count()
|
index: m.homeSections.count()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -257,7 +267,7 @@ sub createContinueWatchingRow(content as dynamic)
|
||||||
continueWatchingRow = content.CreateChild("HomeRow")
|
continueWatchingRow = content.CreateChild("HomeRow")
|
||||||
continueWatchingRow.title = tr("Continue Watching")
|
continueWatchingRow.title = tr("Continue Watching")
|
||||||
m.homeSections.AddReplace("resume", {
|
m.homeSections.AddReplace("resume", {
|
||||||
imageSize: [464, 331],
|
imageSize: imageSizes.WIDE_POSTER,
|
||||||
index: m.homeSections.count()
|
index: m.homeSections.count()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -271,7 +281,7 @@ sub createNextUpRow(content as dynamic)
|
||||||
nextUpRow = content.CreateChild("HomeRow")
|
nextUpRow = content.CreateChild("HomeRow")
|
||||||
nextUpRow.title = tr("Next Up >")
|
nextUpRow.title = tr("Next Up >")
|
||||||
m.homeSections.AddReplace("nextup", {
|
m.homeSections.AddReplace("nextup", {
|
||||||
imageSize: [464, 331],
|
imageSize: imageSizes.WIDE_POSTER,
|
||||||
index: m.homeSections.count()
|
index: m.homeSections.count()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -286,7 +296,7 @@ sub createFavoritesRow(content as dynamic)
|
||||||
favoritesRow.title = tr("Favorites")
|
favoritesRow.title = tr("Favorites")
|
||||||
|
|
||||||
m.homeSections.AddReplace("favorites", {
|
m.homeSections.AddReplace("favorites", {
|
||||||
imageSize: [464, 331],
|
imageSize: imageSizes.WIDE_POSTER,
|
||||||
index: m.homeSections.count()
|
index: m.homeSections.count()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -297,6 +307,7 @@ end sub
|
||||||
|
|
||||||
' Update home row data
|
' Update home row data
|
||||||
sub updateHomeRows()
|
sub updateHomeRows()
|
||||||
|
startMediaLoadingSpinner()
|
||||||
content = processUserSections()
|
content = processUserSections()
|
||||||
setRowItemSizes()
|
setRowItemSizes()
|
||||||
m.top.content = content
|
m.top.content = content
|
||||||
|
@ -375,6 +386,7 @@ sub updateNextUpItems()
|
||||||
itemData = m.LoadNextUpTask.content
|
itemData = m.LoadNextUpTask.content
|
||||||
m.LoadNextUpTask.unobserveField("content")
|
m.LoadNextUpTask.unobserveField("content")
|
||||||
m.LoadNextUpTask.content = []
|
m.LoadNextUpTask.content = []
|
||||||
|
m.LoadNextUpTask.control = "STOP"
|
||||||
|
|
||||||
if itemData = invalid then return
|
if itemData = invalid then return
|
||||||
|
|
||||||
|
@ -444,14 +456,14 @@ sub updateLatestItems(msg)
|
||||||
row.usePoster = true
|
row.usePoster = true
|
||||||
' Handle specific types with different item widths
|
' Handle specific types with different item widths
|
||||||
if node.metadata.contentType = "movies"
|
if node.metadata.contentType = "movies"
|
||||||
row.imageWidth = 180
|
row.imageWidth = imageSizes.MOVIE_POSTER[0]
|
||||||
itemSize = [188, 331]
|
itemSize = imageSizes.MOVIE_POSTER
|
||||||
else if node.metadata.contentType = "music"
|
else if node.metadata.contentType = "music"
|
||||||
row.imageWidth = 261
|
row.imageWidth = imageSizes.MUSIC_ALBUM[0]
|
||||||
itemSize = [261, 331]
|
itemSize = imageSizes.MUSIC_ALBUM
|
||||||
else
|
else
|
||||||
row.imageWidth = 464
|
row.imageWidth = imageSizes.WIDE_POSTER[0]
|
||||||
itemSize = [464, 331]
|
itemSize = imageSizes.WIDE_POSTER
|
||||||
end if
|
end if
|
||||||
|
|
||||||
for each item in itemData
|
for each item in itemData
|
||||||
|
@ -512,9 +524,21 @@ end sub
|
||||||
' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
|
' setFocusToPreviousFocusedItem: Sets the cursor focus to the row and item previously selected
|
||||||
'
|
'
|
||||||
sub setFocusToPreviousFocusedItem()
|
sub setFocusToPreviousFocusedItem()
|
||||||
|
m.loadingTimer.control = "start"
|
||||||
|
|
||||||
if isValid(m.selectedRowItem)
|
if isValid(m.selectedRowItem)
|
||||||
if isValid(m.homeSections[m.selectedRowItem[0]])
|
' Set focus to row if it exists
|
||||||
m.top.jumpToRowItem = [m.homeSections[m.selectedRowItem[0]].index, m.selectedRowItem[1]]
|
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 if
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
@ -533,16 +557,18 @@ sub updateOnNowItems()
|
||||||
' remake row using the new data
|
' remake row using the new data
|
||||||
row = CreateObject("roSGNode", "HomeRow")
|
row = CreateObject("roSGNode", "HomeRow")
|
||||||
row.title = tr("On Now")
|
row.title = tr("On Now")
|
||||||
'itemSize = [464, 331]
|
row.imageWidth = imageSizes.WIDE_POSTER[0]
|
||||||
row.imageWidth = 464
|
|
||||||
for each item in itemData
|
for each item in itemData
|
||||||
row.usePoster = false
|
row.usePoster = false
|
||||||
|
|
||||||
if (not isValid(item.thumbnailURL) or item.thumbnailURL = "") and isValid(item.json) and isValid(item.json.imageURL)
|
if (not isValid(item.thumbnailURL) or item.thumbnailURL = "") and isValid(item.json) and isValid(item.json.imageURL)
|
||||||
item.thumbnailURL = item.json.imageURL
|
item.thumbnailURL = item.json.imageURL
|
||||||
row.usePoster = true
|
row.usePoster = true
|
||||||
row.imageWidth = 180
|
row.imageWidth = imageSizes.MOVIE_POSTER[0]
|
||||||
'itemSize = [188, 331]
|
|
||||||
|
m.homeSections.livetv.imageSize = imageSizes.MOVIE_POSTER
|
||||||
end if
|
end if
|
||||||
|
|
||||||
item.usePoster = row.usePoster
|
item.usePoster = row.usePoster
|
||||||
item.imageWidth = row.imageWidth
|
item.imageWidth = row.imageWidth
|
||||||
row.appendChild(item)
|
row.appendChild(item)
|
||||||
|
@ -553,15 +579,14 @@ sub updateOnNowItems()
|
||||||
' Set focus on previously focused item
|
' Set focus on previously focused item
|
||||||
setFocusToPreviousFocusedItem()
|
setFocusToPreviousFocusedItem()
|
||||||
|
|
||||||
|
' We may now have different poster sizes. Reset the row item sizes
|
||||||
|
setRowItemSizes()
|
||||||
|
|
||||||
end if
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub itemSelected()
|
sub itemSelected()
|
||||||
for each section in m.homeSections
|
m.selectedRowItem = m.top.rowItemSelected
|
||||||
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])
|
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
|
||||||
|
|
||||||
|
|
|
@ -1231,5 +1231,15 @@
|
||||||
<translation>No Chapter Data Found</translation>
|
<translation>No Chapter Data Found</translation>
|
||||||
<extracomment>Message shown in OSD when no chapter data is returned by the API</extracomment>
|
<extracomment>Message shown in OSD when no chapter data is returned by the API</extracomment>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Use Web's Home Section Arrangement</source>
|
||||||
|
<translation>Use Web's Home Section Arrangement</translation>
|
||||||
|
<extracomment>User Setting - Setting title</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>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.</source>
|
||||||
|
<translation>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.</translation>
|
||||||
|
<extracomment>User Setting - Setting description</extracomment>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
|
@ -231,6 +231,13 @@
|
||||||
"settingName": "ui.home.splashBackground",
|
"settingName": "ui.home.splashBackground",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default": "false"
|
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -459,6 +459,9 @@ sub startLoadingSpinner()
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub startMediaLoadingSpinner()
|
sub startMediaLoadingSpinner()
|
||||||
|
if not isValid(m.scene)
|
||||||
|
m.scene = m.top.getScene()
|
||||||
|
end if
|
||||||
dialog = createObject("roSGNode", "ProgressDialog")
|
dialog = createObject("roSGNode", "ProgressDialog")
|
||||||
dialog.id = "invisibiledialog"
|
dialog.id = "invisibiledialog"
|
||||||
dialog.visible = false
|
dialog.visible = false
|
||||||
|
|
|
@ -226,6 +226,20 @@ namespace session
|
||||||
userPreferences = customPrefs
|
userPreferences = customPrefs
|
||||||
rowTypes = []
|
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 user has no section preferences, use default settings
|
||||||
if not userPreferences.doesExist("homesection0")
|
if not userPreferences.doesExist("homesection0")
|
||||||
userPreferences = {
|
userPreferences = {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user