Reworked Home Screen

- Using Task for loading
- Showing Up Next & Newest Library data
- Trying to make more modular
This commit is contained in:
Neil Burrows 2020-03-12 18:33:45 +00:00
parent 0b56a7547e
commit 3741cbc912
13 changed files with 493 additions and 139 deletions

View File

@ -5,9 +5,101 @@ sub setData()
m.top.id = datum.id
m.top.name = datum.name
if datum.CollectionType = invalid then
m.top.type = datum.type
if datum.CollectionType = invalid then
m.top.CollectionType = datum.type
else
m.top.type = datum.CollectionType
m.top.CollectionType = datum.CollectionType
end if
' Set appropriate Images for Wide and Tall based on type
if datum.type = "CollectionFolder" then
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
else if datum.type = "Episode" then
imgParams = { "AddPlayedIndicator": datum.UserData.Played }
if datum.UserData.PlayedPercentage <> invalid then
imgParams.Append({ "PercentPlayed": datum.UserData.PlayedPercentage })
end if
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 464 })
if datum.ImageTags.Primary <> invalid then
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
m.top.thumbnailURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ParentThumbImageTag <> invalid then
imgParams["Tag"] = datum.ParentThumbImageTag
m.top.widePosterUrl = ImageURL(datum.ParentThumbItemId, "Thumb", imgParams)
else if datum.ParentBackdropImageTags <> invalid then
imgParams["Tag"] = datum.ParentBackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.ParentBackdropItemId, "Backdrop", imgParams)
else if datum.ImageTags.Primary <> invalid then
imgParams["Tag"] = datum.SeriesPrimaryImageTag
m.top.widePosterUrl = ImageURL(datum.id, "Primary", imgParams)
end if
else if datum.type = "Series" then
imgParams = { "maxHeight": 261 }
imgParams.Append({ "maxWidth": 464 })
if datum.ImageTags.Primary <> invalid then
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid then
imgParams["Tag"] = datum.imageTags.Thumb
m.top.widePosterUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags <> invalid then
imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.Id, "Backdrop", imgParams)
end if
else if datum.type = "Movie" then
imgParams = { AddPlayedIndicator: datum.UserData.Played }
if datum.UserData.PlayedPercentage <> invalid then
imgParams.Append({ "PercentPlayed": datum.UserData.PlayedPercentage })
end if
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 175 })
if datum.ImageTags.Primary <> invalid then
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' For wide image, use backdrop
imgParams["maxWidth"] = 464
if datum.BackdropImageTags[0] <> invalid then
imgParams["Tag"] = datum.BackdropImageTags[0]
end if
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
else if datum.type = "MusicAlbum" then
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 261 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.posterUrl = m.top.thumbnailURL
end if
end sub

View File

@ -3,9 +3,15 @@
<interface>
<field id="id" type="string" />
<field id="name" type="string" />
<field id="imageURL" type="string" />
<field id="thumbnailURL" type="string" />
<field id="posterURL" type="string" />
<field id="widePosterURL" type="string" />
<field id="type" type="string" />
<field id="json" type="associativearray" onChange="setData" />
<field id="collectionType" type="string" />
</interface>
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
<script type="text/brightscript" uri="HomeData.brs" />
</component>

View File

@ -5,9 +5,7 @@
<OptionsSlider id="options" />
</children>
<interface>
<field id="libraries" alias="homeRows.libList" />
<field id="continueWatching" alias="homeRows.continueList" />
<field id="homeSelection" alias="homeRows.itemSelected" />
<field id="selectedItem" alias="homeRows.selectedItem" />
</interface>
<script type="text/brightscript" uri="Home.brs" />
</component>

View File

@ -1,28 +1,51 @@
sub init()
end sub
function itemContentChanged() as void
sub itemContentChanged()
itemData = m.top.itemContent
if itemData = invalid then return
itemText = m.top.findNode("itemText")
itemPoster = m.top.findNode("itemPoster")
itemTextExtra = m.top.findNode("itemTextExtra")
if itemData.json.CollectionType = invalid then
itemPoster.uri = itemData.imageURL
' Desired Image Width
imageWidth = 464
if m.top.GetParent().content.imageWidth <> invalid
imageWidth = m.top.GetParent().content.imageWidth
end if
itemPoster.width = imageWidth
itemText.width = imageWidth
itemTextExtra.width = imageWidth
' Whether to use WidePoster or Thumbnail in this row
usePoster = m.top.GetParent().content.usePoster
' Format the Data based on the type of Home Data
if itemData.type = "CollectionFolder" then
itemText.text = itemData.name
itemPoster.uri = itemData.widePosterURL
return
end if
itemText.height = 34
itemText.font.size = 25
itemText.horizAlign = "left"
itemText.vertAlign = "bottom"
itemTextExtra = m.top.findNode("itemTextExtra")
itemTextExtra.font.size = 24
itemTextExtra.visible = true
itemTextExtra.font.size = 22
if itemData.type = "Episode" then
itemText.text = itemData.json.SeriesName
itemText.text = itemData.name
if usePoster = true then
itemPoster.uri = itemData.widePosterURL
else
itemPoster.uri = itemData.thumbnailURL
end if
' Set Series and Episode Number for Extra Text
extraPrefix = ""
if itemData.json.ParentIndexNumber <> invalid then
extraPrefix = "S" + StrI(itemData.json.ParentIndexNumber).trim()
@ -33,9 +56,21 @@ function itemContentChanged() as void
if extraPrefix.len() > 0 then
extraPrefix = extraPrefix + " - "
end if
itemTextExtra.text = extraPrefix + itemData.name
else if itemData.type = "Movie" then
return
end if
if itemData.type = "Movie" then
itemText.text = itemData.name
if imageWidth = 180
itemPoster.uri = itemData.posterURL
else
itemPoster.uri = itemData.thumbnailURL
end if
' Set Release Year and Age Rating for Extra Text
textExtra = ""
if itemData.json.ProductionYear <> invalid then
textExtra = StrI(itemData.json.ProductionYear).trim()
@ -48,24 +83,43 @@ function itemContentChanged() as void
end if
end if
itemTextExtra.text = textExtra
return
end if
if itemData.type = "Series" then
itemText.text = itemData.name
if usePoster = true then
itemPoster.uri = itemData.widePosterURL
else
' handle libraries with no picture
if itemData.type = "livetv" then
itemPoster.width = "96"
itemPoster.height = "96"
itemPoster.translation = "[192, 88]"
itemPoster.uri = "pkg:/images/baseline_live_tv_white_48dp.png"
itemText.text = itemData.name
else if itemData.type = "music" then
itemPoster.width = "96"
itemPoster.height = "96"
itemPoster.translation = "[192, 88]"
itemPoster.uri = "pkg:/images/baseline_library_music_white_48dp.png"
itemText.text = itemData.name
else
itemPoster.uri = itemData.imageURL
itemText.text = itemData.name
itemPoster.uri = itemData.thumbnailURL
end if
textExtra = ""
if itemData.json.ProductionYear <> invalid then
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
end function
' Set Years Run for Extra Text
if itemData.json.Status = "Continuing" then
textExtra = textExtra + " - Present"
else if itemData.json.Status = "Ended" and itemData.json.EndDate <> invalid
textExtra = textExtra + " - " + LEFT(itemData.json.EndDate, 4)
end if
itemTextExtra.text = textExtra
return
end if
if itemData.type = "MusicAlbum" then
itemText.text = itemData.name
itemTextExtra.text = itemData.json.AlbumArtist
itemPoster.uri = itemData.posterURL
return
end if
print "Unhandled Item Type: " + itemData.type
end sub

View File

@ -3,10 +3,10 @@
<children>
<Poster id="itemPoster" width="464" height="261" translation="[8,5]" />
<Label id="itemText" horizAlign="center" vertAlign="center" font="font:SmallBoldSystemFont" height="64" width="456" translation="[8,267]" />
<Label id="itemTextExtra" horizAlign="left" vertAlign="center" font="font:SmallBoldSystemFont" height="32" width="456" translation="[8,300]" visible="false" />
<Label id="itemTextExtra" horizAlign="left" vertAlign="center" font="font:SmallBoldSystemFont" height="32" width="456" translation="[8,300]" visible="false" color="#777777FF" />
</children>
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged"/>
<field id="itemContent" type="node" onChange="itemContentChanged" />
</interface>
<script type="text/brightscript" uri="HomeItem.brs" />
</component>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="HomeRow" extends="ContentNode">
<interface>
<field id="imageWidth" type="integer" value="464" />
<field id="usePoster" type="bool" value="false" />
</interface>
</component>

View File

@ -1,8 +1,7 @@
sub init()
m.top.itemComponentName = "HomeItem"
' My media row should always exist
m.top.numRows = 1
m.top.content = CreateObject("roSGNode", "ContentNode")
m.top.numRows = 2
m.top.rowFocusAnimationStyle = "fixedFocusWrap"
m.top.vertFocusAnimationStyle = "floatingFocus"
@ -14,8 +13,15 @@ sub init()
updateSize()
m.top.setfocus(true)
' Load the Libraries from API via task
m.LoadItemsTask = createObject("roSGNode", "LoadItemsTask")
m.LoadItemsTask.observeField("content", "onLibrariesLoaded")
m.LoadItemsTask.control = "RUN"
end sub
sub updateSize()
sideborder = 100
m.top.translation = [111, 155]
@ -27,47 +33,143 @@ sub updateSize()
' spacing between rows
m.top.itemSpacing = [0, 105]
' size of the item in the row
m.top.rowItemSize = [itemWidth, itemHeight]
' spacing between items in a row
m.top.rowItemSpacing = [20, 0]
m.top.visible = true
end sub
sub showLibraryRow()
libs = m.top.libList
libraryRow = CreateObject("roSGNode", "ContentNode")
libraryRow.title = "My Media"
sub onLibrariesLoaded()
for i = 1 to libs.TotalRecordCount
item = libs.Items[i - 1]
libraryRow.appendChild(item)
m.libraryData = m.LoadItemsTask.content
m.sizeArray = [[464, 261]]
m.top.rowItemSize = m.sizeArray
m.LoadItemsTask.unobserveField("content")
'Add the Libraries Row
m.data = CreateObject("roSGNode", "ContentNode")
row = m.data.CreateChild("HomeRow")
row.title = "My Media"
for each item in m.libraryData
row.appendChild(item)
end for
m.top.content.appendChild(libraryRow)
' Load the Continue Watching Data
m.top.content = m.data
m.LoadContinueTask = createObject("roSGNode", "LoadItemsTask")
m.LoadContinueTask.itemsToLoad = "continue"
m.LoadContinueTask.observeField("content", "onContinueItemsLoaded")
m.LoadContinueTask.control = "RUN"
end sub
sub showContinueRow()
continueItems = m.top.continueList
if continueItems.TotalRecordCount > 0 then
continueRow = CreateObject("roSGNode", "ContentNode")
continueRow.title = "Continue Watching"
sub onContinueItemsLoaded()
for i = 1 to continueItems.TotalRecordCount
item = continueItems.Items[i - 1]
continueRow.appendChild(item)
m.LoadContinueTask.unobserveField("content")
itemData = m.LoadContinueTask.content
'Add the Row
row = m.top.content.CreateChild("HomeRow")
row.title = "Continue Watching"
m.sizeArray.Push([464, 261])
m.top.rowItemSize = m.sizeArray
for each item in itemData
row.appendChild(item)
end for
m.top.numRows++
m.top.content.appendChild(continueRow)
' Load Next Up
m.LoadNextUpTask = createObject("roSGNode", "LoadItemsTask")
m.LoadNextUpTask.itemsToLoad = "nextUp"
m.LoadNextUpTask.observeField("content", "onNextUpItemsLoaded")
m.LoadNextUpTask.control = "RUN"
end sub
sub onNextUpItemsLoaded()
m.LoadNextUpTask.unobserveField("content")
itemData = m.LoadNextUpTask.content
'Add the Libraries Row
row = m.top.content.CreateChild("HomeRow")
row.title = "Next Up >"
row.usePoster = true
m.sizeArray.Push([464, 261])
m.top.rowItemSize = m.sizeArray
for each item in itemData
row.appendChild(item)
end for
' Now load latest in all libraries
for each lib in m.libraryData
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
metadata = { "title" : lib.name}
metadata.Append({"contentType" : lib.json.CollectionType})
loadLatest.metadata = metadata
loadLatest.observeField("content", "onLatestLoaded")
loadLatest.control = "RUN"
end for
end sub
function onLatestLoaded(msg)
itemData = msg.GetData()
data = msg.getField()
node = msg.getRoSGNode()
node.unobserveField("content")
'Add the Libraries Row
row = m.top.content.CreateChild("HomeRow")
row.title = "Latest in " + node.metadata.title + " >"
row.usePoster = true
' Handle specific types with different item widths
if node.metadata.contentType = "movies" then
row.imageWidth = 180
m.sizeArray.Push([188, 261])
else if node.metadata.contentType = "music" then
row.imageWidth = 261
m.sizeArray.Push([261, 261])
else
row.imageWidth = 464
m.sizeArray.Push([464, 261])
end if
end sub
m.top.rowItemSize = m.sizeArray
for each item in itemData
row.appendChild(item)
end for
end function
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
return false
if key <> "OK" then return false
' Set the selected item
m.top.selectedItem = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
return true
end function

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="HomeRows" extends="RowList">
<interface>
<field id="libList" type="associativearray" onChange="showLibraryRow" />
<field id="continueList" type="associativearray" onChange="showContinueRow" />
<field id="selectedItem" type="node" />
</interface>
<script type="text/brightscript" uri="HomeRows.brs"/>
</component>

View File

@ -0,0 +1,86 @@
sub init()
m.top.functionName = "loadItems"
end sub
sub loadItems()
results = []
' Load Libraries
if m.top.itemsToLoad = "libraries"
url = Substitute("Users/{0}/Views/", get_setting("active_user"))
resp = APIRequest(url)
data = getJson(resp)
for each item in data.Items
if item.Type = "CollectionFolder" then
tmp = CreateObject("roSGNode", "HomeData")
tmp.json = item
results.push(tmp)
else
print "Warning: Un-expected Item Type " + item.Type
end if
end for
' Load Latest Additions to Libraries
else if m.top.itemsToLoad = "latest"
url = Substitute("Users/{0}/Items/Latest", get_setting("active_user"))
params = {}
params["Limit"] = 16
params["ParentId"] = m.top.itemId
params["EnableImageTypes"] = "Primary,Backdrop,Thumb"
params["ImageTypeLimit"] = 1
resp = APIRequest(url, params)
data = getJson(resp)
for each item in data
tmp = CreateObject("roSGNode", "HomeData")
tmp.json = item
results.push(tmp)
end for
' Load Next Up
else if m.top.itemsToLoad = "nextUp"
url = "Shows/NextUp"
params = {}
params["recursive"] = true
params["SortBy"] = "DatePlayed"
params["SortOrder"] = "Descending"
params["ImageTypeLimit"] = 1
params["UserId"] = get_setting("active_user")
resp = APIRequest(url, params)
data = getJson(resp)
for each item in data.Items
tmp = CreateObject("roSGNode", "HomeData")
tmp.json = item
results.push(tmp)
end for
' Load Continue Watching
else if m.top.itemsToLoad = "continue"
url = Substitute("Users/{0}/Items/Resume", get_setting("active_user"))
params = {}
params["recursive"] = true
params["SortBy"] = "DatePlayed"
params["SortOrder"] = "Descending"
params["Filters"] = "IsResumable"
resp = APIRequest(url, params)
data = getJson(resp)
for each item in data.Items
tmp = CreateObject("roSGNode", "HomeData")
tmp.json = item
results.push(tmp)
end for
end if
m.top.content = results
end sub

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="LoadItemsTask" extends="Task">
<interface>
<field id="itemsToLoad" type="string" value="libraries" />
<field id="itemId" type="string" />
<field id="metadata" type="associativearray" />
<field id="content" type="array" />
</interface>
<script type="text/brightscript" uri="LoadItemsTask.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
</component>

View File

@ -82,33 +82,33 @@ sub Main()
else
group.setFocus(true)
end if
else if isNodeEvent(msg, "homeSelection")
else if isNodeEvent(msg, "selectedItem")
' If you select a library from ANYWHERE, follow this flow
node = getMsgPicker(msg, "homeRows")
if node.type = "movies"
node = msg.getData()
if node.type = "CollectionFolder" AND node.collectionType = "movies"
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
m.overhang.title = node.name
group = CreateMovieListGroup(node)
group = CreateMovieListGroup(node.json)
group.overhangTitle = node.name
m.scene.appendChild(group)
else if node.type = "tvshows"
else if node.type = "CollectionFolder" AND node.collectionType = "tvshows"
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
m.overhang.title = node.name
group = CreateSeriesListGroup(node)
group = CreateSeriesListGroup(node.json)
group.overhangTitle = node.name
m.scene.appendChild(group)
else if node.type = "boxsets"
else if node.type = "CollectionFolder" AND node.collectionType = "boxsets"
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
m.overhang.title = node.name
group = CreateCollectionsList(node)
group = CreateCollectionsList(node.json)
group.overhangTitle = node.name
m.scene.appendChild(group)
else if node.type = "Episode" then

View File

@ -101,12 +101,7 @@ function CreateHomeGroup()
' Main screen after logging in. Shows the user's libraries
group = CreateObject("roSGNode", "Home")
libs = LibraryList()
group.libraries = libs
con = HomeItemList("continue")
group.continueWatching = con
group.observeField("homeSelection", m.port)
group.observeField("selectedItem", m.port)
sidepanel = group.findNode("options")
sidepanel.observeField("closeSidePanel", m.port)

View File

@ -140,7 +140,7 @@ function ItemList(library_id = invalid as string, params = {})
return data
end function
' Return items for use on home screen (homeRows)
' Return items for use on home screen (HomeRows)
function HomeItemList(row = "" as string, params = {})
if params["limit"] = invalid
params["limit"] = 20