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
m.top.type = datum.type
if datum.CollectionType = invalid then
m.top.type = datum.type
else
m.top.type = datum.CollectionType
m.top.CollectionType = datum.type
else
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="HomeData.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" />
<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,71 +1,125 @@
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
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
if itemData.type = "Episode" then
itemText.text = itemData.json.SeriesName
extraPrefix = ""
if itemData.json.ParentIndexNumber <> invalid then
extraPrefix = "S" + StrI(itemData.json.ParentIndexNumber).trim()
end if
if itemData.json.IndexNumber <> invalid then
extraPrefix = extraPrefix + "E" + StrI(itemData.json.IndexNumber).trim()
end if
if extraPrefix.len() > 0 then
extraPrefix = extraPrefix + " - "
end if
itemTextExtra.text = extraPrefix + itemData.name
else if itemData.type = "Movie" then
itemText.text = itemData.name
textExtra = ""
if itemData.json.ProductionYear <> invalid then
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
if itemData.json.OfficialRating <> invalid then
if textExtra <> "" then
textExtra = textExtra + " - " + itemData.json.OfficialRating
else
textExtra = itemData.json.OfficialRating
end if
end if
itemTextExtra.text = textExtra
end if
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
end if
' Desired Image Width
imageWidth = 464
if m.top.GetParent().content.imageWidth <> invalid
imageWidth = m.top.GetParent().content.imageWidth
end if
end function
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.visible = true
itemTextExtra.font.size = 22
if itemData.type = "Episode" then
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()
end if
if itemData.json.IndexNumber <> invalid then
extraPrefix = extraPrefix + "E" + StrI(itemData.json.IndexNumber).trim()
end if
if extraPrefix.len() > 0 then
extraPrefix = extraPrefix + " - "
end if
itemTextExtra.text = extraPrefix + itemData.name
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()
end if
if itemData.json.OfficialRating <> invalid then
if textExtra <> "" then
textExtra = textExtra + " - " + itemData.json.OfficialRating
else
textExtra = itemData.json.OfficialRating
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
itemPoster.uri = itemData.thumbnailURL
end if
textExtra = ""
if itemData.json.ProductionYear <> invalid then
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
' 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>
</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,73 +1,175 @@
sub init()
m.top.itemComponentName = "HomeItem"
' My media row should always exist
m.top.numRows = 1
m.top.content = CreateObject("roSGNode", "ContentNode")
m.top.itemComponentName = "HomeItem"
' My media row should always exist
m.top.numRows = 2
m.top.rowFocusAnimationStyle = "fixedFocusWrap"
m.top.vertFocusAnimationStyle = "floatingFocus"
m.top.rowFocusAnimationStyle = "fixedFocusWrap"
m.top.vertFocusAnimationStyle = "floatingFocus"
m.top.showRowLabel = [true]
m.top.rowLabelOffset = [0, 20]
m.top.showRowCounter = [true]
m.top.showRowLabel = [true]
m.top.rowLabelOffset = [0, 20]
m.top.showRowCounter = [true]
updateSize()
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"
m.top.setfocus(true)
end sub
sub updateSize()
sideborder = 100
m.top.translation = [111, 155]
sideborder = 100
m.top.translation = [111, 155]
itemWidth = 480
itemHeight = 330
itemWidth = 480
itemHeight = 330
m.top.itemSize = [1920 - 111 - 27, itemHeight]
' spacing between rows
m.top.itemSpacing = [0, 105]
m.top.itemSize = [1920 - 111 - 27, itemHeight]
' 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]
' spacing between items in a row
m.top.rowItemSpacing = [20, 0]
m.top.visible = true
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)
end for
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
' 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"
m.top.content.appendChild(libraryRow)
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)
end for
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
' Load Next Up
m.LoadNextUpTask = createObject("roSGNode", "LoadItemsTask")
m.LoadNextUpTask.itemsToLoad = "nextUp"
m.LoadNextUpTask.observeField("content", "onNextUpItemsLoaded")
m.LoadNextUpTask.control = "RUN"
m.top.numRows++
m.top.content.appendChild(continueRow)
end if
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
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
if not press then return false
return false
end function
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