Improved interface for TV episodes

This commit is contained in:
thomabx 2020-02-22 20:47:00 -08:00
parent 76fc41c23b
commit fb757570c3
9 changed files with 153 additions and 69 deletions

View File

@ -0,0 +1,54 @@
sub init()
m.title = m.top.findNode("title")
m.title.text = "Loading..."
end sub
function itemContentChanged() as void
item = m.top.itemContent
itemData = item.json
m.top.findNode("title").text = item.title
m.top.findNode("poster").uri = item.posterURL
m.top.findNode("overview").text = item.overview
if type(itemData.RunTimeTicks) = "LongInteger"
m.top.findNode("runtime").text = stri(getRuntime()) + " mins"
m.top.findNode("endtime").text = "Ends at " + getEndTime()
end if
if itemData.communityRating <> invalid then
m.top.findNode("communityRating").text = str(int(itemData.communityRating*10)/10)
end if
end function
function getRuntime() as integer
itemData = m.top.itemContent.json
' A tick is .1ms, so 1/10,000,000 for ticks to seconds,
' then 1/60 for seconds to minutess... 1/600,000,000
return int(itemData.RunTimeTicks / 600000000.0)
end function
function getEndTime() as string
itemData = m.top.itemContent.json
date = CreateObject("roDateTime")
duration_s = int(itemData.RunTimeTicks / 10000000.0)
date.fromSeconds(date.asSeconds() + duration_s)
date.toLocalTime()
hours = date.getHours()
meridian = "AM"
if hours = 0
hours = 12
meridian = "AM"
else if hours = 12
hours = 12
meridian = "PM"
else if hours > 12
hours = hours - 12
meridian = "PM"
end if
minutes = stri(date.getMinutes()).trim()
if val(minutes) > 10
minutes= "0" + minutes
end if
return Substitute("{0}:{1} {2}", stri(hours).trim(), stri(date.getMinutes()).trim(), meridian)
end function

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="TVListDetails" extends="Group">
<children>
<LayoutGroup id="toplevel" layoutDirection="vert" itemSpacings="[40]">
<LayoutGroup id="main_group" layoutDirection="horiz" itemSpacings="[30]">
<Poster id="poster" width="534" height="300" />
<LayoutGroup id="text" layoutDirection="vert" itemSpacings="[15]">
<!-- Using poster of 1 length to get spacing. Not successful with adding translation to title -->
<Poster id="null" height="1" />
<ScrollingLabel id="title" font="font:LargeBoldSystemFont" maxWidth="1200" />
<LayoutGroup layoutDirection="horiz" itemSpacings="[20]">
<Label id="runtime" font="font:SmallestSystemFont" />
<Label id="communityRating" font="font:SmallestSystemFont" />
<Label id="endtime" font="font:SmallestSystemFont" />
</LayoutGroup>
<Label id="overview" wrap="true" height="170" width="1200" maxLines="4" ellipsizeOnBoundary="true"/>
</LayoutGroup>
</LayoutGroup>
</LayoutGroup>
</children>
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged"/>
</interface>
<script type="text/brightscript" uri="details-list.brs" />
</component>

View File

@ -1,7 +0,0 @@
sub init()
m.top.overhangTitle = "Season"
end sub
sub setSeason()
m.top.overhangTitle = m.top.seasonData.name
end sub

View File

@ -0,0 +1,7 @@
sub init()
m.top.overhangTitle = "Season"
end sub
sub setSeason()
m.top.overhangTitle = m.top.seasonData.SeriesName + " - " + m.top.seasonData.name
end sub

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<component name="TVEpisodes" extends="JFGroup"> <component name="TVEpisodes" extends="JFGroup">
<children> <children>
<ItemGrid id="picker" visible="true" itemsPerRow="10" /> <TVEpisodeRow id="picker" visible="true" />
</children> </children>
<interface> <interface>
<field id="episodeSelected" alias="picker.itemSelected" /> <field id="episodeSelected" alias="picker.itemSelected" />
<field id="seasonData" type="node" onChange="setSeason" /> <field id="seasonData" type="associativearray" onChange="setSeason" />
<field id="objects" alias="picker.objects" /> <field id="objects" alias="picker.objects" />
</interface> </interface>
<script type="text/brightscript" uri="episode.brs" /> <script type="text/brightscript" uri="episodes.brs" />
</component> </component>

View File

@ -1,67 +1,66 @@
sub init() sub init()
m.top.itemComponentName = "ListPoster" m.top.itemComponentName = "TVListDetails"
m.top.content = setData()
m.top.rowFocusAnimationStyle = "floatingFocus" m.top.rowFocusAnimationStyle = "floatingFocus"
updateSize() m.top.showRowLabel = [false]
m.top.setFocus(true) updateSize()
m.top.setFocus(true)
end sub end sub
sub updateSize() sub updateSize()
m.top.numRows = 1 m.top.numRows = 1
m.top.rowSize = 3 m.top.itemsPerRow = 1
dimensions = m.top.getScene().currentDesignResolution dimensions = m.top.getScene().currentDesignResolution
border = 75 border = 75
m.top.translation = [border, border + 115] m.top.translation = [border, border + 115]
textHeight = 80 textHeight = 80
itemWidth = (dimensions["width"] - border*2) / m.top.rowSize itemWidth = (dimensions["width"] - border*2)
itemHeight = itemWidth * dimensions["height"]/ dimensions["width"] + textHeight itemHeight = 300
m.top.visible = true m.top.visible = true
m.top.itemSize = [dimensions["width"] - border*2, itemHeight] ' Size of the individual rows
m.top.itemSpacing = [ 0, 10 ] m.top.itemSize = [dimensions["width"] - border*2, itemHeight]
' Spacing between Rows
m.top.itemSpacing = [ 0, 40]
m.top.rowItemSize = [ itemWidth, itemHeight ] ' Size of items in the row
m.top.rowItemSpacing = [ 0, 0 ] m.top.rowItemSize = [ itemWidth, itemHeight ]
' Spacing between items in the row
m.top.rowItemSpacing = [ 20, 0 ]
episodeData = m.top.TVEpisodeData
if episodeData = invalid then return
rowsize = m.top.rowSize
n = episodeData.items.count()
' Test for no remainder
if int(n/rowsize) = n/rowsize then
m.top.numRows = n/rowsize
else
m.top.numRows = n/rowsize + 1
end if
end sub end sub
function getData() function setupRows()
if m.top.TVEpisodeData = invalid then updateSize()
data = CreateObject("roSGNode", "ContentNode") objects = m.top.objects
return data m.top.numRows = objects.items.count()
end if m.top.content = setData()
end function
updateSize()
function setData()
episodeData = m.top.TVEpisodeData data = CreateObject("roSGNode", "ContentNode")
rowsize = m.top.rowSize if m.top.objects = invalid then
data = CreateObject("roSGNode", "ContentNode") ' Return an empty node just to return something; we'll update once we have data
row = data.CreateChild("ContentNode") return data
row.title = "Episodes" end if
for each item in episodeData.items
row.appendChild(item) for each item in m.top.objects.items
end for row = data.CreateChild("ContentNode")
m.top.content = data row.appendChild(item)
return data end for
return data
end function
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
return false
end function end function

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<component name="TVEpisodeRow" extends="RowList"> <component name="TVEpisodeRow" extends="RowList">
<interface> <interface>
<field id="rowSize" type="int" /> <field id="itemsPerRow" type="int" />
<field id="TVEpisodeData" type="associativearray" onChange="getData" /> <field id="objects" type="associativearray" onChange="setupRows" />
<field id="escapeButton" type="string" alwaysNotify="true" />
</interface> </interface>
<script type="text/brightscript" uri="rowlist-episode.brs" /> <script type="text/brightscript" uri="rowlist-episode.brs" />
</component> </component>

View File

@ -198,7 +198,6 @@ end function
function CreateMovieDetailsGroup(movie) function CreateMovieDetailsGroup(movie)
group = CreateObject("roSGNode", "MovieDetails") group = CreateObject("roSGNode", "MovieDetails")
movie = ItemMetaData(movie.id) movie = ItemMetaData(movie.id)
group.itemContent = movie group.itemContent = movie
@ -243,7 +242,7 @@ end function
function CreateSeasonDetailsGroup(series, season) function CreateSeasonDetailsGroup(series, season)
group = CreateObject("roSGNode", "TVEpisodes") group = CreateObject("roSGNode", "TVEpisodes")
group.seasonData = TVSeasons(series.id) group.seasonData = ItemMetaData(season.id)
group.objects = TVEpisodes(series.id, season.id) group.objects = TVEpisodes(series.id, season.id)
group.observeField("episodeSelected", m.port) group.observeField("episodeSelected", m.port)

View File

@ -131,7 +131,7 @@ function ItemList(library_id = invalid as string, params = {})
tmp.json = item tmp.json = item
results.push(tmp) results.push(tmp)
else else
print item.type print "Items.brs::ItemList received unhandled type: " item.type
' Otherwise we just stick with the JSON ' Otherwise we just stick with the JSON
results.push(item) results.push(item)
end if end if
@ -165,8 +165,13 @@ function ItemMetaData(id as string)
tmp.image = PosterImage(data.id) tmp.image = PosterImage(data.id)
tmp.json = item tmp.json = item
return tmp return tmp
else if data.type = "Season"
tmp = CreateObject("roSGNode", "TVSeasonData")
tmp.image = PosterImage(data.id)
tmp.json = data
return tmp
else else
print data.type print "Items.brs::ItemMetaData processed unhandled type: " data.type
' Return json if we don't know what it is ' Return json if we don't know what it is
return data return data
end if end if
@ -202,13 +207,14 @@ function TVEpisodes(show_id as string, season_id as string)
data = getJson(resp) data = getJson(resp)
results = [] results = []
for each item in data.Items for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played } imgParams = { "AddPlayedIndicator": item.UserData.Played, "maxWidth": 712, "maxheight": 400 }
tmp = CreateObject("roSGNode", "TVEpisodeData") tmp = CreateObject("roSGNode", "TVEpisodeData")
tmp.image = PosterImage(item.id, imgParams) tmp.image = PosterImage(item.id, imgParams)
if tmp.image <> invalid if tmp.image <> invalid
tmp.image.posterDisplayMode = "scaleToFit" tmp.image.posterDisplayMode = "scaleToFit"
end if end if
tmp.json = item tmp.json = item
tmp.overview = ItemMetaData(item.id).overview
results.push(tmp) results.push(tmp)
end for end for
data.Items = results data.Items = results