Merge branch 'master' into handle-missing-media-streams

This commit is contained in:
Neil Burrows 2022-04-29 08:03:28 +01:00 committed by GitHub
commit 4e7211750b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 219 additions and 33 deletions

View File

@ -121,6 +121,16 @@ telnet ${ROKU_DEV_TARGET} 8085
To exit telnet: `CTRL + ]` and then type `quit + ENTER`
### Committing
Before commiting your code, please run:
```bash
make prep_commit
```
This will format your code and run the CI checks locally to ensure you will pass the CI tests.
### (Optional) Update Images
This repo already contains all necessary images for the app. This script only needs to be run when the [official Jellyfin images](https://github.com/jellyfin/jellyfin-ux) are changed to allow us to update the repo images.

6
app.mk
View File

@ -169,6 +169,12 @@ prep_tests:
cp -r $(SOURCEREL)/tests/source/* $(STAGINGREL)/source/tests/;\
./node_modules/.bin/rooibos-cli i tests/.rooibosrc.json
prep_commit:
npm run format
npm ci
npm run validate
npm run check-formatting
install: prep_staging package home
@echo "Installing $(APPNAME)-$(BUILD) to host $(ROKU_DEV_TARGET)"
@$(CURLCMD) --user $(USERPASS) --digest -F "mysubmit=Install" -F "archive=@$(ZIPREL)/$(APPNAME)-$(BUILD).zip" -F "passwd=" http://$(ROKU_DEV_TARGET)/plugin_install | grep "<font color" | sed "s/<font color=\"red\">//" | sed "s[</font>[["

View File

@ -0,0 +1,28 @@
sub init()
m.top.visible = true
m.Alphamenu = m.top.findNode("Alphamenu")
m.Alphamenu.focusable = true
m.Alphatext = m.top.findNode("alphatext")
m.focusedChild = m.top.findNode("focusedChild")
m.Alphamenu.focusedFont.size = 25
m.Alphamenu.font.size = 25
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "OK"
child = m.Alphatext.getChild(m.Alphamenu.itemFocused)
if child.title = m.top.itemAlphaSelected
m.top.itemAlphaSelected = ""
m.Alphamenu.focusFootprintBitmapUri = ""
else
m.Alphamenu.focusFootprintBitmapUri = "pkg:/images/white.png"
m.top.itemAlphaSelected = child.title
end if
return true
end if
return false
end function

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="Alpha" extends = "Group">
<children>
<LabelList
translation="[1872, 185]"
vertFocusAnimationStyle="floatingFocus"
drawFocusFeedback="true"
id = "Alphamenu"
font="font:SmallestSystemFont"
itemSpacing="[0,2]"
itemSize="[28,28]"
numRows="27"
textHorizAlign="center"
focusBitmapUri = "pkg:/images/white.png"
focusBitmapBlendColor = "#FFFFFF"
focusFootprintBlendColor = "#666666"
>
<ContentNode id="alphatext" role = "content" >
<ContentNode title = "#" />
<ContentNode title = "A" />
<ContentNode title = "B" />
<ContentNode title = "C" />
<ContentNode title = "D" />
<ContentNode title = "E" />
<ContentNode title = "F" />
<ContentNode title = "G" />
<ContentNode title = "H" />
<ContentNode title = "I" />
<ContentNode title = "J" />
<ContentNode title = "K" />
<ContentNode title = "L" />
<ContentNode title = "M" />
<ContentNode title = "N" />
<ContentNode title = "O" />
<ContentNode title = "P" />
<ContentNode title = "Q" />
<ContentNode title = "R" />
<ContentNode title = "S" />
<ContentNode title = "T" />
<ContentNode title = "U" />
<ContentNode title = "V" />
<ContentNode title = "W" />
<ContentNode title = "X" />
<ContentNode title = "Y" />
<ContentNode title = "Z" />
</ContentNode>
</LabelList>
</children>
<interface>
<field id="selectedItem" type="node" alwaysNotify="true" />
<field id="focusedChild" type="node" onChange="focusChanged" />
<field id="itemAlphaSelected" type="string" />
</interface>
<script type="text/brightscript" uri="Alpha.brs" />
</component>

View File

@ -21,6 +21,7 @@ sub init()
m.itemGrid.observeField("itemFocused", "onItemFocused")
m.itemGrid.observeField("itemSelected", "onItemSelected")
m.itemGrid.observeField("AlphaSelected", "onItemAlphaSelected")
m.newBackdrop.observeField("loadStatus", "newBGLoaded")
'Background Image Queued for loading
@ -34,6 +35,8 @@ sub init()
m.loadItemsTask = createObject("roSGNode", "LoadItemsTask2")
m.Alpha = m.top.findNode("AlphaMenu")
m.AlphaSelected = m.top.findNode("AlphaSelected")
end sub
'
@ -72,6 +75,9 @@ sub loadInitialItems()
m.sortAscending = false
end if
m.loadItemsTask.nameStartsWith = m.top.AlphaSelected
m.emptyText.visible = false
updateTitle()
m.loadItemsTask.itemId = m.top.parentItem.Id
@ -339,6 +345,14 @@ sub onItemSelected()
m.top.selectedItem = m.itemGrid.content.getChild(m.itemGrid.itemSelected)
end sub
sub onItemAlphaSelected()
m.loadedRows = 0
m.loadedItems = 0
m.data = CreateObject("roSGNode", "ContentNode")
m.itemGrid.content = m.data
loadInitialItems()
end sub
'
'Check if options updated and any reloading required
@ -440,9 +454,8 @@ sub onChannelSelected(msg)
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
topGrp = m.top.findNode("itemGrid")
if key = "options"
if m.options.visible = true
m.options.visible = false
@ -463,6 +476,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
else if key = "play" or key = "OK"
markupGrid = m.top.getChild(2)
itemToPlay = markupGrid.content.getChild(markupGrid.itemFocused)
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
m.top.quickPlayNode = itemToPlay
return true
@ -473,6 +487,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
photoPlayer.control = "RUN"
return true
end if
else if key = "right" and topGrp.isinFocusChain()
topGrp.setFocus(false)
alpha = m.Alpha.getChild(0).findNode("Alphamenu")
alpha.setFocus(true)
return true
else if key = "left" and m.Alpha.isinFocusChain()
m.Alpha.setFocus(false)
m.Alpha.visible = true
topGrp.setFocus(true)
return true
end if
return false
end function
@ -481,8 +505,11 @@ sub updateTitle()
if m.filter = "All"
m.top.overhangTitle = m.top.parentItem.title
else if m.filter = "Favorites"
m.top.overhangTitle = m.top.parentItem.title + " (Favorites)"
m.top.overhangTitle = m.top.parentItem.title + tr(" (Favorites)")
else
m.top.overhangTitle = m.top.parentItem.title + " (Filtered)"
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered)")
end if
if m.top.AlphaSelected <> ""
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered)")
end if
end sub

View File

@ -29,12 +29,14 @@
<FloatFieldInterpolator id = "fadeinLoading" key="[0.0, 1.0]" keyValue="[ 0.00, 0.25 ]" fieldToInterp="backdropTransition.opacity" />
<FloatFieldInterpolator id = "fadeoutLoaded" key="[0.0, 1.0]" keyValue="[ 0.25, 0.00 ]" fieldToInterp="backdrop.opacity" />
</Animation>
<Alpha id="AlphaMenu" />
</children>
<interface>
<field id="parentItem" type="node" onChange="loadInitialItems" />
<field id="selectedItem" type="node" alwaysNotify="true" />
<field id="quickPlayNode" type="node" alwaysNotify="true" />
<field id="imageDisplayMode" type="string" value="scaleToZoom" />
<field id="AlphaSelected" type="string" alias="AlphaMenu.itemAlphaSelected" alwaysNotify="true" onChange="onItemAlphaSelected" />
</interface>
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />

View File

@ -25,6 +25,15 @@ sub loadItems()
Fields: "Overview"
}
' Handle special case when getting names starting with numeral
if m.top.NameStartsWith <> ""
if m.top.NameStartsWith = "#"
params.NameLessThan = "A"
else
params.NameStartsWith = m.top.nameStartsWith
end if
end if
filter = m.top.filter
if filter = "All" or filter = "all"
' do nothing

View File

@ -9,6 +9,7 @@
<field id="metadata" type="assocarray" />
<field id="sortField" type="string" value="SortName" />
<field id="sortAscending" type="boolean" value="true" />
<field id="nameStartsWith" type="string" value="" />
<field id="recursive" type="boolean" value="true" />
<field id="filter" type="string" value="All" />

View File

@ -5,6 +5,8 @@ sub init()
m.backdrop = m.top.findNode("backdrop")
m.deviceInfo = CreateObject("roDeviceInfo")
' Randmomise the background colors
posterBackgrounds = m.global.constants.poster_bg_pallet
m.backdrop.color = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
@ -68,6 +70,13 @@ sub focusChanged()
m.staticTitle.visible = false
m.title.visible = true
' text to speech for accessibility
if m.deviceInfo.IsAudioGuideEnabled() = true
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.title.text)
end if
else
m.title.repeatCount = 0
m.staticTitle.visible = true

View File

@ -0,0 +1,31 @@
sub init()
m.posterImg = m.top.findNode("posterImg")
m.name = m.top.findNode("pLabel")
m.role = m.top.findNode("subTitle")
m.deviceInfo = CreateObject("roDeviceInfo")
end sub
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 = tr("Unknown")
m.posterImg.uri = "pkg:/images/baseline_person_white_48dp.png"
end if
end sub
sub focusChanged()
if m.deviceInfo.IsAudioGuideEnabled() = true
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.name.text)
txt2Speech.Say(m.role.text)
end if
end sub

View File

@ -2,31 +2,9 @@
<component name="ExtrasItem" extends="JFGroup">
<interface>
<field id="itemContent" type="node" onChange="showContent" />
<field id="itemHasFocus" type="boolean" onChange="focusChanged" />
</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>
<script type="text/brightscript" uri="ExtrasItem.brs" />
<children>
<LayoutGroup layoutDirection="vert" >
<Poster id="posterImg" width="234" height="300" translation="[8,243]" failedBitmapUri="pkg:/images/baseline_person_white_48dp.png" />

View File

@ -1,6 +1,9 @@
sub init()
m.title = m.top.findNode("title")
m.title.text = tr("Loading...")
m.overview = m.top.findNode("overview")
m.deviceInfo = CreateObject("roDeviceInfo")
end sub
sub itemContentChanged()
@ -11,9 +14,9 @@ sub itemContentChanged()
else
indexNumber = ""
end if
m.top.findNode("title").text = indexNumber + item.title
m.title.text = indexNumber + item.title
m.top.findNode("poster").uri = item.posterURL
m.top.findNode("overview").text = item.overview
m.overview.text = item.overview
if type(itemData.RunTimeTicks) = "LongInteger"
m.top.findNode("runtime").text = stri(getRuntime()).trim() + " mins"
@ -63,3 +66,15 @@ function getEndTime() as string
return formatTime(date)
end function
sub focusChanged()
if m.top.itemHasFocus = true
' text to speech for accessibility
if m.deviceInfo.IsAudioGuideEnabled() = true
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.title.text)
txt2Speech.Say(m.overview.text)
end if
end if
end sub

View File

@ -27,6 +27,7 @@
</children>
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged"/>
<field id="itemHasFocus" type="boolean" onChange="focusChanged" />
</interface>
<script type="text/brightscript" uri="TVListDetails.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />

View File

@ -135,17 +135,22 @@ function round(f as float) as integer
end function
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
overview = m.top.findNode("overview")
topGrp = m.top.findNode("seasons")
bottomGrp = m.top.findNode("extrasGrid")
if key = "down" and topGrp.isinFocusChain()
if key = "down" and overview.hasFocus()
topGrp.setFocus(true)
return true
else if key = "down" and topGrp.hasFocus()
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()
else if key = "up" and bottomGrp.hasFocus()
if bottomGrp.itemFocused = 0
m.top.findNode("VertSlider").reverse = true
m.top.findNode("extrasFader").reverse = true
@ -153,6 +158,10 @@ function onKeyEvent(key as string, press as boolean) as boolean
topGrp.setFocus(true)
return true
end if
else if key = "up" and topGrp.hasFocus()
overview.setFocus(true)
return true
end if
return false
end function

BIN
images/white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

View File

@ -431,6 +431,11 @@
<translation>Not found</translation>
<extracomment>Title of message box when the requested content is not found on the server</extracomment>
</message>
<message>
<source>Unknown</source>
<translation>Unknown</translation>
<extracomment>Title for a cast member for which we have no information for</extracomment>
</message>
<message>
<source>The requested content does not exist on the server</source>
<translation>The requested content does not exist on the server</translation>