Movie extras (#520)

This commit is contained in:
debmint 2022-03-13 08:46:03 +00:00 committed by GitHub
parent 0e2e2052e1
commit 0f18add523
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 7040 additions and 536 deletions

View File

@ -17,7 +17,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.top.focusButton = target
return true
else if key = "up" or key = "down"
m.top.escape = true
m.top.escape = key
return true
end if

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="ButtonGroupHoriz" extends="ButtonGroup">
<interface>
<field id="escape" type="boolean" alwaysNotify="true" />
<field id="escape" type="string" alwaysNotify="true" />
</interface>
<script type="text/brightscript" uri="ButtonGroupHoriz.brs" />

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="OverviewDialog" extends="StandardDialog">
<interface>
<field id="Title" type="string" onchange="setTitle" />
<field id="Overview" type="string" onChange="setOverview" />
</interface>
<script type="text/brightscript">
<![CDATA[
sub setTitle()
m.top.findNode("titleArea").primaryTitle = m.top.title
end sub
sub setOverview()
m.top.findNode("description").text = m.top.overview
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if press = false then return false
if key = "OK" and m.top.findNode("contentArea").isInFocusChain()
m.top.close = true
end if
return false
end function
]]>
</script>
<children>
<StdDlgTitleArea id="titleArea" />
<StdDlgContentArea id="contentArea">
<StdDlgTextItem id="description"
namedTextStyle="secondary" />
</StdDlgContentArea>
</children>
</component>

View File

@ -0,0 +1,164 @@
sub init()
m.dscr = m.top.findNode("description")
m.vidsList = m.top.findNode("extrasGrid")
m.btnGrp = m.top.findNode("buttons")
m.btnGrp.observeField("escape", "onButtonGroupEscaped")
m.favBtn = m.top.findNode("favorite-button")
m.extrasGrp = m.top.findNode("extrasGrp")
m.top.findNode("VertSlider").keyValue = "[[30, 998], [30, 789], [30, 580], [30,371 ], [30, 162]]"
m.extrasGrp.opacity = 1.0
m.extrasGrp.translation = "[30, 998]"
m.dscr.observeField("isTextEllipsized", "onEllipsisChanged")
createDialogPallete()
m.top.optionsAvailable = false
end sub
sub loadPerson()
item = m.top.itemContent
itemData = item.json
m.top.Id = itemData.id
m.top.findNode("Name").Text = itemData.Name
if itemData.PremiereDate <> invalid and itemData.PremiereDate <> ""
birthDate = CreateObject("roDateTime")
birthDate.FromISO8601String(itemData.PremiereDate)
deathDate = CreateObject("roDatetime")
lifeString = tr("Born") + ": " + birthDate.AsDateString("short-month-no-weekday")
if itemData.EndDate <> invalid and itemData.EndDate <> ""
deathDate.FromISO8601String(itemData.EndDate)
lifeString = lifeString + " * " + tr("Died") + ": " + deathDate.AsDateString("short-month-no-weekday")
end if
' Calculate age
age = deathDate.getYear() - birthDate.getYear()
if deathDate.getMonth() < birthDate.getMonth()
age--
else if deathDate.getMonth() = birthDate.getMonth()
if deathDate.getDayOfMonth() < birthDate.getDayOfMonth()
age--
end if
end if
lifeString = lifeString + " * " + tr("Age") + ": " + stri(age)
m.top.findNode("premierDate").Text = lifeString
end if
m.dscr.text = itemData.Overview
if item.posterURL <> invalid and item.posterURL <> ""
m.top.findnode("personImage").uri = item.posterURL
else
m.top.findnode("personImage").uri = "pkg:/images/baseline_person_white_48dp.png"
end if
m.vidsList.callFunc("loadPersonVideos", m.top.Id)
setFavoriteColor()
m.favBtn.setFocus(true)
end sub
sub onEllipsisChanged()
if m.dscr.isTextEllipsized
dscrShowFocus()
end if
end sub
sub dscrShowFocus()
if m.dscr.isTextEllipsized
m.dscr.setFocus(true)
m.dscr.opacity = 1.0
m.top.findNode("dscrBorder").color = "#d0d0d0ff"
end if
end sub
sub onButtonGroupEscaped()
key = m.btnGrp.escape
if key = "down"
m.vidsList.setFocus(true)
m.top.findNode("VertSlider").reverse = false
m.top.findNode("pplAnime").control = "start"
else if key = "up" and m.dscr.isTextEllipsized
dscrShowFocus()
end if
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "OK"
if m.dscr.hasFocus() and m.dscr.isTextEllipsized
createFullDscrDlg()
return true
end if
return false
end if
if key = "back"
m.global.sceneManager.callfunc("popScene")
return true
end if
if key = "down"
if m.dscr.hasFocus()
m.favBtn.setFocus(true)
m.dscr.opacity = 0.6
m.top.findNode("dscrBorder").color = "#data202020ff"
return true
end if
else if key = "up"
if m.vidsList.isInFocusChain() and m.vidsList.itemFocused = 0
m.top.findNode("VertSlider").reverse = true
m.top.findNode("pplAnime").control = "start"
m.favBtn.setFocus(true)
return true
end if
end if
return false
end function
sub setFavoriteColor()
fave = m.top.itemContent.favorite
fave_button = m.top.findNode("favorite-button")
if fave <> invalid and fave
fave_button.textColor = "#00ff00ff"
fave_button.focusedTextColor = "#269926ff"
else
fave_button.textColor = "0xddddddff"
fave_button.focusedTextColor = "#262626ff"
end if
end sub
sub createFullDscrDlg()
dlg = CreateObject("roSGNode", "OverviewDialog")
dlg.Title = tr("Press 'OK' to Close")
dlg.width = 1290
dlg.palette = m.dlgPalette
dlg.overview = [m.dscr.text]
m.fullDscrDlg = dlg
m.top.getScene().dialog = dlg
border = createObject("roSGNode", "Poster")
border.uri = "pkg:/images/hd_focul_9.png"
border.blendColor = "#c9c9c9ff"
border.width = dlg.width + 6
border.height = dlg.height + 6
border.translation = [dlg.translation[0] - 3, dlg.translation[1] - 3]
border.visible = true
end sub
sub createDialogPallete()
m.dlgPalette = createObject("roSGNode", "RSGPalette")
m.dlgPalette.colors = {
DialogBackgroundColor: "0x262828FF",
DialogItemColor: "0x00EF00FF",
DialogTextColor: "0xb0b0b0FF",
DialogFocusColor: "0xcececeFF",
DialogFocusItemColor: "0x202020FF",
DialogSecondaryTextColor: "0xf8f8f8ff",
DialogSecondaryItemColor: "0xcc7ecc4D",
DialogInputFieldColor: "0x80FF8080",
DialogKeyboardColor: "0x80FF804D",
DialogFootprintColor: "0x80FF804D"
}
end sub
function shortDate(isoDate) as string
myDate = CreateObject("roDateTime")
myDate.FromISO8601String(isoDate)
return myDate.AsDateString("short-month-no-weekday")
end function

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="PersonDetails" extends="JFGroup">
<interface>
<field id="itemContent" type="node" onChange="loadPerson" />
<field id="image" type="node" />
<field id="selectedItem" type="node" alias="extrasGrid.selectedItem" alwaysNotify="true" />
</interface>
<children>
<LayoutGroup id="main_group"
layoutdirection="vert" translation="[60, 180]" itemSpacings="[36]">
<LayoutGroup id="personInfoGroup"
layoutDirection="horiz" itemSpacings="[36]">
<Poster id="personImage"
width="300" height="450" />
<LayoutGroup id="vertSpacer" layoutDirection="vert" itemSpacings="[24]">
<LayoutGroup id="dataGroup>" layoutDirection="vert"
translation="[450,180]">
<Label id="name" font="font:MediumBoldSystemFont" height="45" width="1200" />
<label id="premierDate" font="font:SmallestBoldSystemFont" height="48" vertAlign="top" />
<Rectangle id="dscrBorder"
height="360" width="1422"
color="0x202020ff">
<Rectangle id='dscrRect' translation="[3, 3]"
height="354" width="1416"
color="0x202020ff">
<Label id="description"
height="342" width="1380" wrap="true" translation="[18, 15]"
font="font:SmallestSystemFont" color="#e4e4e4ff" ellipsisText=" ... (-OK- for More)" />
</Rectangle>
</Rectangle>
</LayoutGroup>
<ButtonGroupHoriz id="buttons" >
<Button id="favorite-button" text="Favorite"
iconUri="" focusedIconUri="" />
</ButtonGroupHoriz>
</LayoutGroup>
</LayoutGroup>
</LayoutGroup>
<extrasSlider id="personVideos" />
</children>
<script type="text/brightscript" uri="PersonDetails.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- The "ContentNode" for displaying the actual Extras Item -->
<component name="ExtrasData" extends="ContentNode">
<script type="text/brightscript">
<![CDATA[
sub setfields()
datum = m.top.json
m.top.id = datum.id
m.top.subTitle = datum
m.top.labelText = datum.Name
end sub
sub setPoster()
end sub
]]>
</script>
<interface>
<field id="image" type="node" />
<field id="Type" type="string" />
<field id="subTitle" type="string" />
<field id="labelText" type="string" />
<field id="posterUrl" type="string" />
<field id="imageWidth" type="integer" value="234" />
<field id="json" type="assocarray" />
</interface>
</component>

View File

@ -0,0 +1,32 @@
sub setFields()
json = m.top.json
m.top.id = json.id
m.top.favorite = json.UserData.isFavorite
m.top.Type = "Person"
setPoster()
end sub
sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags[0] <> invalid
imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.ParentThumbItemId, "Thumb", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags[0] <> invalid
imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
end if
end sub

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="PersonData" extends="JFContentItem">
<interface>
<field id="image" type="node" onChange="setPoster" />
<field id="movieID" type="string" />
<field id="overview" type="string" />
</interface>
<script type="text/brightscript" uri="PersonData.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="ExtrasItem" extends="JFGroup">
<interface>
<field id="itemContent" type="node" onChange="showContent" />
</interface>
<script type="text/brightscript">
<![CDATA[
function init() as void
m.posterImg = m.top.findNode("posterImg")
m.name = m.top.findNode("pLabel")
m.role = m.top.findNode("subTitle")
end function
sub showContent()
if m.top.itemContent <> Invalid
cont = m.top.itemContent
m.name.text = cont.labelText
m.name.maxWidth = cont.imageWidth
m.role.Width = cont.imageWidth
m.posterImg.uri = cont.posterUrl
m.posterImg.width = cont.imageWidth
m.role.Text = cont.subTitle
else
m.role.text = "Who??"
m.posterImg.uri = "pkg:/images/baseline_person_white_48dp.png"
end if
end sub
]]>
</script>
<children>
<LayoutGroup layoutDirection="vert" >
<Poster id="posterImg" width="234" height="300" translation="[8,243]" failedBitmapUri="pkg:/images/baseline_person_white_48dp.png" />
<ScrollingLabel id="pLabel" horizAlign="center" vertAlign="bottom" maxWidth="266" font="font:SmallestBoldSystemFont" height="48" />
<Label id="SubTitle" horizAlign="center" vertAlign="center" font="font:SmallestBoldSystemFont" height="32" color="#A7A7A7FF" />
</LayoutGroup>
</children>
</component>

View File

@ -0,0 +1,187 @@
sub init()
m.top.visible = true
updateSize()
m.top.rowFocusAnimationStyle = "fixedFocus"
m.top.observeField("rowItemSelected", "onRowItemSelected")
' Set up all Tasks
m.LoadPeopleTask = CreateObject("roSGNode", "LoadItemsTask")
m.LoadPeopleTask.itemsToLoad = "people"
m.LoadPeopleTask.observeField("content", "onPeopleLoaded")
m.LikeThisTask = CreateObject("roSGNode", "LoadItemsTask")
m.LikeThisTask.itemsToLoad = "likethis"
m.LikeThisTask.observeField("content", "onLikeThisLoaded")
m.SpecialFeaturesTask = CreateObject("roSGNode", "LoadItemsTask")
m.SpecialFeaturesTask.itemsToLoad = "specialfeatures"
m.SpecialFeaturesTask.observeField("content", "onSpecialFeaturesLoaded")
m.LoadMoviesTask = CreateObject("roSGNode", "LoadItemsTask")
m.LoadMoviesTask.itemsToLoad = "personMovies"
m.LoadShowsTask = CreateObject("roSGNode", "LoadItemsTask")
m.LoadShowsTask.itemsToLoad = "personTVShows"
m.LoadSeriesTask = CreateObject("roSGNode", "LoadItemsTask")
m.LoadSeriesTask.itemsToLoad = "personSeries"
end sub
sub updateSize()
itemHeight = 396
m.top.itemSize = [1710, itemHeight]
m.top.rowItemSpacing = [36, 36]
end sub
sub loadPeople(data as object)
m.top.parentId = data.id
m.LoadPeopleTask.peopleList = data.People
m.LoadPeopleTask.control = "RUN"
end sub
sub loadPersonVideos(personId)
m.personId = personId
m.LoadMoviesTask.itemId = m.personId
m.LoadMoviesTask.observeField("content", "onMoviesLoaded")
m.LoadMoviesTask.control = "RUN"
end sub
sub onPeopleLoaded()
people = m.LoadPeopleTask.content
m.loadPeopleTask.unobserveField("content")
data = CreateObject("roSGNode", "ContentNode") ' The row Node
if people <> invalid and people.count() > 0
row = data.createChild("ContentNode")
row.Title = tr("Cast & Crew")
for each person in people
if person.json.type = "Actor"
person.subTitle = "as " + person.json.Role
else
person.subTitle = person.json.Type
end if
person.Type = "Person"
row.appendChild(person)
end for
end if
m.top.content = data
m.top.rowItemSize = [[234, 396]]
m.LikeThisTask.itemId = m.top.parentId
m.LikeThisTask.control = "RUN"
end sub
sub onLikeThisLoaded()
data = m.LikeThisTask.content
m.LikeThisTask.unobserveField("content")
if data <> invalid and data.count() > 0
row = m.top.content.createChild("ContentNode")
row.Title = tr("More Like This")
for each item in data
item.Id = item.json.Id
item.labelText = item.json.Name
if item.json.ProductionYear <> invalid
item.subTitle = stri(item.json.ProductionYear)
else
premierYear = CreateObject("roDateTime")
premierYear.FromISO8601String(item.json.PremiereDate)
item.subTitle = stri(premierYear.GetYear())
end if
item.Type = item.json.Type
row.appendChild(item)
end for
addRowSize([234, 396])
end if
m.SpecialFeaturesTask.itemId = m.top.parentId
m.SpecialFeaturesTask.control = "RUN"
end sub
function onSpecialFeaturesLoaded()
data = m.SpecialFeaturesTask.content
m.SpecialFeaturesTask.unobserveField("content")
if data <> invalid and data.count() > 0
row = m.top.content.createChild("ContentNode")
row.Title = tr("Special Features")
for each item in data
m.top.visible = true
item.Id = item.json.Id
item.labelText = item.json.Name
item.subTitle = ""
item.Type = item.json.Type
item.imageWidth = 450
row.appendChild(item)
end for
addRowSize([462, 372])
end if
return m.top.content
end function
sub onMoviesLoaded()
data = m.LoadMoviesTask.content
m.LoadMoviesTask.unobserveField("content")
rlContent = CreateObject("roSGNode", "ContentNode")
if data <> invalid and data.count() > 0
row = rlContent.createChild("ContentNode")
row.title = tr("Movies")
for each mov in data
mov.Id = mov.json.Id
mov.labelText = mov.json.Name
mov.subTitle = mov.json.ProductionYear
mov.Type = mov.json.Type
row.appendChild(mov)
end for
m.top.rowItemSize = [[234, 396]]
end if
m.top.content = rlContent
m.LoadShowsTask.itemId = m.personId
m.LoadShowsTask.observeField("content", "onShowsLoaded")
m.LoadShowsTask.control = "RUN"
end sub
sub onShowsLoaded()
data = m.LoadShowsTask.content
m.LoadShowsTask.unobserveField("content")
if data <> invalid and data.count() > 0
row = buildRow("TV Shows", data, 502)
addRowSize([502, 396])
m.top.content.appendChild(row)
end if
m.LoadSeriesTask.itemId = m.personId
m.LoadSeriesTask.observeField("content", "onSeriesLoaded")
m.LoadSeriesTask.control = "RUN"
end sub
sub onSeriesLoaded()
data = m.LoadSeriesTask.content
m.LoadSeriesTask.unobserveField("content")
if data <> invalid and data.count() > 0
row = buildRow("Series", data)
addRowSize([234, 396])
m.top.content.appendChild(row)
end if
m.top.visible = true
end sub
function buildRow(rowTitle as string, items, imgWdth = 0)
row = CreateObject("roSGNode", "ContentNode")
row.Title = tr(rowTitle)
for each mov in items
mov.Id = mov.json.Id
mov.labelText = mov.json.Name
mov.subTitle = mov.json.ProductionYear
mov.Type = mov.json.Type
if imgWdth > 0
mov.imageWidth = imgWdth
end if
row.appendChild(mov)
end for
return row
end function
sub addRowSize(newRow)
sizeArray = m.top.rowItemSize
newSizeArray = []
for each size in sizeArray
newSizeArray.push(size)
end for
newSizeArray.push(newRow)
m.top.rowItemSize = newSizeArray
end sub
sub onRowItemSelected()
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
end sub

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- The top-Level RowList for the Extras rows -->
<component name="ExtrasRowList" extends="RowList">
<interface>
<field id="type" type="string" />
<field id="parentId" type="string" />
<field id="selectedItem" type="node" alwaysNotify="true" />
<function name="loadPeople" />
<function name="loadPersonVideos" />
</interface>
<script type="text/brightscript" uri="ExtrasRowList.brs" />
</component>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="ExtrasSlider" extends="JFGroup">
<children>
<Rectangle id="extrasGrp" color="#0A0010" opacity="0.3" width="1860" height="900" translation="[30, 1014]" >
<ExtrasRowList id="extrasGrid"
itemSpacing="[ 60, 132]"
rowLabelOffset="[ [9, 24] ]"
numRows="2"
showRowLabel="true"
showRowCounter="true"
visible="true"
translation="[12,18]"
itemComponentName="ExtrasItem" />
<Animation id="pplAnime" duration=".4" repeat="false" >
<Vector2DFieldInterpolator
id="VertSlider"
key="[0.0, 0.25, 0.50, 75.0, 1.0]"
keyValue="[[30, 1014], [30, 804], [30, 588], [30,375 ], [30, 162]]"
fieldToInterp="extrasGrp.translation" />
<FloatFieldInterpolator
id="extrasFader"
key="[0.0, 0.25, 0.50, 75.0, 1.0]"
keyValue="[0.2, 0.4, 0.6, 0.8, 1.0]"
fieldToInterp="extrasGrp.opacity" />
</Animation>
</Rectangle>
</children>
</component>

View File

@ -100,8 +100,74 @@ sub loadItems()
tmp.json = item
results.push(tmp)
end for
' Extract array of persons from Views and download full metadata for each
else if m.top.itemsToLoad = "people"
for each person in m.top.peopleList
tmp = CreateObject("roSGNode", "ExtrasData")
tmp.Id = person.Id
tmp.labelText = person.Name
params = {}
params["Tags"] = person.PrimaryImageTag
params["MaxWidth"] = 234
params["MaxHeight"] = 330
tmp.posterURL = ImageUrl(person.Id, "Primary", params)
tmp.json = person
results.push(tmp)
end for
else if m.top.itemsToLoad = "specialfeatures"
params = {}
url = Substitute("Users/{0}/Items/{1}/SpecialFeatures", get_setting("active_user"), m.top.itemId)
resp = APIRequest(url, params)
data = getJson(resp)
if data <> invalid and data.count() > 0
for each specfeat in data
tmp = CreateObject("roSGNode", "ExtrasData")
results.push(tmp)
params = {}
params["Tags"] = specfeat.ImageTags.Primary
params["MaxWidth"] = 450
params["MaxHeight"] = 402
tmp.posterURL = ImageUrl(specfeat.Id, "Primary", params)
tmp.json = specfeat
end for
end if
else if m.top.itemsToLoad = "likethis"
params = { "userId": get_setting("active_user"), "limit": 16 }
url = Substitute("Items/{0}/Similar", m.top.itemId)
resp = APIRequest(url, params)
data = getJson(resp)
for each item in data.items
tmp = CreateObject("roSGNode", "ExtrasData")
tmp.posterURL = ImageUrl(item.Id, "Primary", { "Tags": item.PrimaryImageTag })
tmp.json = item
results.push(tmp)
end for
else if m.top.itemsToLoad = "personMovies"
getPersonVideos("Movie", results, {})
else if m.top.itemsToLoad = "personTVShows"
getPersonVideos("Episode", results, { MaxWidth: 502, MaxHeight: 300 })
else if m.top.itemsToLoad = "personSeries"
getPersonVideos("Series", results, {})
end if
m.top.content = results
end sub
sub getPersonVideos(videoType, dest, dimens)
params = { personIds: m.top.itemId, recursive: true, includeItemTypes: videoType, Limit: 50, SortBy: "Random" }
url = Substitute("Users/{0}/Items", get_setting("active_user"))
resp = APIRequest(url, params)
data = getJson(resp)
if data <> invalid and data.count() > 0
for each item in data.items
tmp = CreateObject("roSGNode", "ExtrasData")
imgParms = { "Tags": item.ImageTags.Primary }
imgParms.append(dimens)
tmp.posterURL = ImageUrl(item.Id, "Primary", imgParms)
tmp.json = item
dest.push(tmp)
end for
end if
end sub

View File

@ -5,6 +5,7 @@
<field id="itemsToLoad" type="string" value="libraries" />
<field id="itemId" type="string" />
<field id="metadata" type="assocarray" />
<field id="peopleList" type="array" />
<field id="content" type="array" />
</interface>
<script type="text/brightscript" uri="LoadItemsTask.brs" />

View File

@ -1,14 +1,15 @@
sub init()
m.extrasGrp = m.top.findnode("extrasGrp")
m.extrasGrid = m.top.findNode("extrasGrid")
m.top.optionsAvailable = false
m.main_group = m.top.findNode("main_group")
m.options = m.top.findNode("options")
main = m.top.findNode("main_group")
main.translation = [96, 175]
overview = m.top.findNode("overview")
overview.width = 1920 - 96 - 300 - 96 - 30
m.top.findNode("buttons").setFocus(true)
m.buttonGrp = m.top.findNode("buttons")
m.buttonGrp.setFocus(true)
end sub
sub itemContentChanged()
@ -85,6 +86,7 @@ sub itemContentChanged()
if itemData.taglines.count() > 0
setFieldText("tagline", itemData.taglines[0])
end if
setFavoriteColor()
setWatchedColor()
SetUpOptions(itemData.mediaStreams)
@ -125,6 +127,7 @@ sub setFieldText(field, value)
end sub
function getRuntime() as integer
itemData = m.top.itemContent.json
' A tick is .1ms, so 1/10,000,000 for ticks to seconds,
@ -201,6 +204,24 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.options.setFocus(true)
end if
if key = "down" and m.buttonGrp.isInFocusChain()
m.extrasGrid.setFocus(true)
m.top.findNode("VertSlider").reverse = false
m.top.findNode("extrasFader").reverse = false
m.top.findNode("pplAnime").control = "start"
return true
end if
if key = "up" and m.top.findNode("extrasGrid").isInFocusChain()
if m.extrasGrid.itemFocused = 0
m.top.findNode("VertSlider").reverse = true
m.top.findNode("extrasFader").reverse = true
m.top.findNode("pplAnime").control = "start"
m.buttonGrp.setFocus(true)
return true
end if
end if
if not press then return false
if key = "options"

View File

@ -32,9 +32,11 @@
</ButtonGroupHoriz>
<Label id="tagline" />
<Label id="overview" wrap="true" maxLines="8" />
</LayoutGroup>
</LayoutGroup>
</LayoutGroup>
</LayoutGroup>
<!-- "Cast and Crew" row -->
<extrasSlider id="movieExtras" />
<MovieOptions id="options" visible="false" />
</children>
<interface>

View File

@ -2,6 +2,9 @@ sub init()
m.top.optionsAvailable = false
main = m.top.findNode("toplevel")
main.translation = [96, 175]
m.extrasSlider = m.top.findNode("tvSeasonExtras")
'm.extrasSlider.translation = [30,1014]
m.extrasSlider.visible = true
end sub
sub itemContentChanged()
@ -130,3 +133,26 @@ function round(f as float) as integer
return n
end if
end function
function onKeyEvent(key as string, press as boolean) as boolean
topGrp = m.top.findNode("seasons")
bottomGrp = m.top.findNode("extrasGrid")
if key = "down" and topGrp.isinFocusChain()
bottomGrp.setFocus(true)
m.top.findNode("VertSlider").reverse = false
m.top.findNode("extrasFader").reverse = false
m.top.findNode("pplAnime").control = "start"
return true
else if key = "up" and bottomGrp.isinFocusChain()
if bottomGrp.itemFocused = 0
m.top.findNode("VertSlider").reverse = true
m.top.findNode("extrasFader").reverse = true
m.top.findNode("pplAnime").control = "start"
topGrp.setFocus(true)
return true
end if
end if
return false
end function

View File

@ -21,6 +21,7 @@
</LayoutGroup>
<TVSeasonRow id="seasons" />
</LayoutGroup>
<ExtrasSlider id="tvSeasonExtras" />
</children>
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged" />

View File

@ -261,6 +261,42 @@
<source>TAB_FILTER</source>
<translation>Filter</translation>
</message>
<message>
<source>Born</source>
<translation>Born</translation>
</message>
<message>
<source>Died</source>
<translation>Died</translation>
</message>
<message>
<source>Age</source>
<translation>Age</translation>
</message>
<message>
<source>Cast &amp; Crew</source>
<translation>Cast &amp; Crew</translation>
</message>
<message>
<source>More Like This</source>
<translation>More Like This</translation>
</message>
<message>
<source>Special Features</source>
<translation>Special Features</translation>
<message>
<source>Press 'OK' to Close</source>
<translation>Press 'OK' to Close</translation>
</message>
</message>
<message>
<source>Movies</source>
<translation>Movies</translation>
</message>
<message>
<source>TV Shows</source>
<translation>TV Shows</translation>
</message>
<message>
<source>today</source>
<translation>today</translation>
@ -381,6 +417,10 @@
<source>Cancel Series Recording</source>
<translation>Cancel Series Recording</translation>
</message>
<message>
<source>Close</source>
<translation>Close</translation>
</message>
<message>
<source>Connecting to Server</source>
<translation>Connecting to Server</translation>

6761
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,6 @@
"devDependencies": {
"@rokucommunity/bslint": "^0.4.0",
"brighterscript": "^0.39.4",
"brighterscript-formatter": "^1.6.1",
"rooibos-cli": "^1.0.1"
},
"scripts": {
@ -32,5 +31,8 @@
"bugs": {
"url": "https://github.com/jellyfin/jellyfin-roku/issues"
},
"homepage": "https://github.com/jellyfin/jellyfin-roku#readme"
"homepage": "https://github.com/jellyfin/jellyfin-roku#readme",
"dependencies": {
"brighterscript-formatter": "^1.6.8"
}
}

View File

@ -112,6 +112,8 @@ sub Main (args as dynamic) as void
else if selectedItem.type = "Movie"
' open movie detail page
group = CreateMovieDetailsGroup(selectedItem)
else if selectedItem.type = "Person"
CreatePersonView(selectedItem)
else if selectedItem.type = "TvChannel" or selectedItem.type = "Video" or selectedItem.type = "Program"
' play channel feed
video_id = selectedItem.id
@ -283,6 +285,12 @@ sub Main (args as dynamic) as void
autoPlayNextEpisode(node.id, node.showID)
end if
end if
'else if isNodeEvent(msg, "selectedExtra")
'rl = msg.getData()
'sel = rl.rowItemSelected
'? "msg.getfield():" + msg.getField()
'stop
'CreatePersonView(msg.getData())
else if type(msg) = "roDeviceInfoEvent"
event = msg.GetInfo()
group = sceneManager.callFunc("getActiveScene")

View File

@ -306,6 +306,10 @@ function CreateMovieDetailsGroup(movie)
b.observeField("buttonSelected", m.port)
end for
extras = group.findNode("extrasGrid")
extras.observeField("selectedItem", m.port)
extras.callFunc("loadPeople", movie.json)
return group
end function
@ -320,6 +324,10 @@ function CreateSeriesDetailsGroup(series)
group.observeField("seasonSelected", m.port)
extras = group.findNode("extrasGrid")
extras.observeField("selectedItem", m.port)
extras.callFunc("loadPeople", group.itemcontent.json)
return group
end function
@ -375,6 +383,31 @@ function CreateVideoPlayerGroup(video_id, audio_stream_idx = 1)
return video
end function
function CreatePersonView(personData as object) as object
person = CreateObject("roSGNode", "PersonDetails")
m.global.SceneManager.callFunc("pushScene", person)
info = ItemMetaData(personData.id)
person.itemContent = info
person.setFocus(true)
person.observeField("selectedItem", m.port)
person.findNode("favorite-button").observeField("buttonSelected", m.port)
return person
end function
function CreatePhotoPage(photo)
group = CreateObject("roSGNode", "PhotoDetails")
group.optionsAvailable = true
m.global.sceneManager.callFunc("pushScene", group)
group.itemContent = photo
return group
end function
sub UpdateSavedServerList()
server = get_setting("server")
username = get_setting("username")

View File

@ -112,6 +112,11 @@ function ItemMetaData(id as string)
tmp.image = PosterImage(data.id)
tmp.json = data
return tmp
else if data.type = "Person"
tmp = CreateObject("roSGNode", "PersonData")
tmp.image = PosterImage(data.id, { "MaxWidth": 300, "MaxHeight": 450 })
tmp.json = data
return tmp
else
print "Items.brs::ItemMetaData processed unhandled type: " data.type
' Return json if we don't know what it is