Merge branch 'jump-to-1st-item' of https://github.com/candry7731/jellyfin-roku into jump-to-1st-item

This commit is contained in:
candry7731 2022-06-11 19:16:08 -05:00
commit 18888acc7f
12 changed files with 149 additions and 52 deletions

View File

@ -72,6 +72,11 @@ sub loadInitialItems()
m.sortField = get_user_setting("display.livetv.sortField")
sortAscendingStr = get_user_setting("display.livetv.sortAscending")
m.filter = get_user_setting("display.livetv.filter")
else if m.top.parentItem.collectionType = "music"
m.view = get_user_setting("display.music.view")
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
else
m.view = invalid
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
@ -104,9 +109,20 @@ sub loadInitialItems()
else if m.top.parentItem.collectionType = "tvshows"
m.loadItemsTask.itemType = "Series"
else if m.top.parentItem.collectionType = "music"
m.loadItemsTask.itemType = "MusicArtist,MusicAlbum"
m.loadItemsTask.fallbackType = "MusicAlbum"
' Default Settings
m.loadItemsTask.recursive = false
m.loadItemsTask.itemType = "MusicArtist,MusicAlbum"
m.view = get_user_setting("display.music.view")
if m.view = "music-artist"
m.loadItemsTask.recursive = true
m.loadItemsTask.itemType = "MusicArtist"
else if m.view = "music-album"
m.loadItemsTask.itemType = "MusicAlbum"
m.loadItemsTask.recursive = true
end if
else if m.top.parentItem.collectionType = "livetv"
m.loadItemsTask.itemType = "LiveTV"
@ -217,7 +233,11 @@ sub SetUpOptions()
options.filter = []
'Music
else if m.top.parentItem.collectionType = "music"
options.views = [{ "Title": tr("Music"), "Name": "music" }]
options.views = [
{ "Title": tr("Default"), "Name": "music-default" },
{ "Title": tr("Artists"), "Name": "music-artist" },
{ "Title": tr("Albums"), "Name": "music-album" },
]
options.sort = [
{ "Title": tr("TITLE"), "Name": "SortName" },
{ "Title": tr("DATE_ADDED"), "Name": "DateCreated" },
@ -417,7 +437,6 @@ sub optionsClosed()
m.top.removeChild(m.tvGuide)
end if
end if
end if
if m.top.parentItem.Type = "CollectionFolder" or m.top.parentItem.CollectionType = "CollectionFolder"
@ -432,6 +451,21 @@ sub optionsClosed()
end if
reload = false
if m.top.parentItem.collectionType = "music"
if m.options.view <> m.view
if m.options.view = "music-artist"
m.view = "music-artist"
else if m.options.view = "music-album"
m.view = "music-album"
else
m.view = "music-default"
end if
set_user_setting("display.music.view", m.view)
reload = true
end if
end if
if m.options.sortField <> m.sortField or m.options.sortAscending <> m.sortAscending
m.sortField = m.options.sortField
m.sortAscending = m.options.sortAscending

View File

@ -59,17 +59,6 @@ sub loadItems()
if data.TotalRecordCount <> invalid then m.top.totalRecordCount = data.TotalRecordCount
' When loading a collection, if no results are found, try searching by fallback type
if data.TotalRecordCount = 0
if m.top.FallbackType <> ""
' Ensure we didn't just search by the fallback type - prevent infinite loop
if m.top.ItemType <> m.top.FallbackType
m.top.ItemType = m.top.FallbackType
loadItems()
end if
end if
end if
for each item in data.Items
tmp = invalid
if item.Type = "Movie"

View File

@ -5,7 +5,6 @@
<field id="itemId" type="string" />
<field id="startIndex" type="integer" value="0" />
<field id="itemType" type="string" value="" />
<field id="fallbackType" type="string" value="" />
<field id="limit" type="integer" value="60" />
<field id="metadata" type="assocarray" />
<field id="sortField" type="string" value="SortName" />

View File

@ -3,6 +3,7 @@ sub init()
setupMainNode()
m.playAlbum = m.top.findNode("playAlbum")
m.instantMix = m.top.findNode("instantMix")
m.albumCover = m.top.findNode("albumCover")
m.songList = m.top.findNode("songList")
m.infoGroup = m.top.FindNode("infoGroup")
@ -12,7 +13,6 @@ sub init()
m.spinner.visible = true
m.dscr = m.top.findNode("overview")
m.dscr.observeField("isTextEllipsized", "onEllipsisChanged")
createDialogPallete()
end sub
@ -99,11 +99,6 @@ function onKeyEvent(key as string, press as boolean) as boolean
if m.spinner.visible then return false
' Play Album is hidden, so there are no navigation needs here
if m.top.pageContent.json.ChildCount = 1
return false
end if
if key = "options"
if m.dscr.isTextEllipsized
createFullDscrDlg()
@ -112,10 +107,24 @@ function onKeyEvent(key as string, press as boolean) as boolean
return false
end if
if key = "right" and m.playAlbum.hasFocus()
m.songList.setFocus(true)
return true
if key = "right"
if m.playAlbum.hasFocus() or m.instantMix.hasFocus()
m.songList.setFocus(true)
return true
end if
else if key = "left" and m.songList.hasFocus()
if m.playAlbum.visible
m.playAlbum.setFocus(true)
else if m.instantMix.visible
m.instantMix.setFocus(true)
else
return false
end if
return true
else if key = "down" and m.playAlbum.hasFocus()
m.instantMix.setFocus(true)
return true
else if key = "up" and m.instantMix.hasFocus()
m.playAlbum.setFocus(true)
return true
end if
@ -123,19 +132,6 @@ function onKeyEvent(key as string, press as boolean) as boolean
return false
end function
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
end if
end sub
sub createFullDscrDlg()
dlg = CreateObject("roSGNode", "OverviewDialog")
dlg.Title = tr("Press 'Back' to Close")

View File

@ -10,6 +10,7 @@
<Label id="runtime" width="450" height="25" />
<Label id="released" width="450" height="25" />
<JFButton id="playAlbum" minChars="8" text="Play Album"></JFButton>
<JFButton id="instantMix" minChars="8" text="Instant Mix"></JFButton>
</LayoutGroup>
<LayoutGroup id="infoGroup" layoutDirection="vert" itemSpacings="[15]">
<Label id="overview" wrap="true" height="310" width="1250" ellipsisText=" ... (Press * to read more)" />
@ -26,6 +27,7 @@
<field id="albumData" type="assocarray" alias="songList.MusicArtistAlbumData" />
<field id="playSong" alias="songList.itemSelected" />
<field id="playAllSelected" alias="playAlbum.buttonSelected" />
<field id="instantMixSelected" alias="instantMix.buttonSelected" />
</interface>
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
<script type="text/brightscript" uri="MusicAlbumDetails.brs" />

View File

@ -12,18 +12,16 @@ sub init()
end sub
sub updateSize()
dimensions = m.top.getScene().currentDesignResolution
m.top.translation = [450, 180]
border = 96
m.top.translation = [border, 75 + 115]
itemWidth = (dimensions["width"] - border * 2)
itemHeight = 400
itemWidth = 1360
itemHeight = 300
m.top.visible = true
' Size of the individual rows
m.top.itemSize = [dimensions["width"] - border * 2, itemHeight]
m.top.itemSize = [itemWidth, itemHeight]
' Spacing between Rows
m.top.itemSpacing = [0, 40]

View File

@ -2,6 +2,11 @@ sub init()
m.top.optionsAvailable = false
m.rows = m.top.findNode("picker")
m.poster = m.top.findNode("seasonPoster")
m.Random = m.top.findNode("Random")
m.tvEpisodeRow = m.top.findNode("tvEpisodeRow")
m.rows.observeField("doneLoading", "updateSeason")
end sub
@ -10,12 +15,35 @@ sub setSeasonLoading()
end sub
sub updateSeason()
imgParams = { "maxHeight": 450, "maxWidth": 300 }
m.poster.uri = ImageURL(m.top.seasonData.Id, "Primary", imgParams)
m.Random.visible = true
m.top.overhangTitle = m.top.seasonData.SeriesName + " - " + m.top.seasonData.name
end sub
function onKeyEvent(key as string, press as boolean) as boolean
handled = false
if key = "left" and not m.Random.hasFocus()
m.Random.setFocus(true)
return true
end if
if key = "right" and not m.tvEpisodeRow.hasFocus()
m.tvEpisodeRow.setFocus(true)
return true
end if
if key = "OK" or key = "play"
if m.Random.hasFocus()
randomEpisode = Rnd(m.rows.getChild(0).objects.items.count()) - 1
m.top.quickPlayNode = m.rows.getChild(0).objects.items[randomEpisode]
return true
end if
end if
focusedChild = m.top.focusedChild.focusedChild
if focusedChild.content = invalid then return handled

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="TVEpisodes" extends="JFGroup">
<children>
<Poster id="seasonPoster" width="300" height="450" translation="[95,175]" />
<JFButton id="Random" text="Play Random" translation="[90, 640]" visible="false"></JFButton>
<TVEpisodeRowWithOptions id="picker" visible="true" />
</children>
<interface>
@ -10,4 +12,7 @@
<field id="objects" alias="picker.objects" />
</interface>
<script type="text/brightscript" uri="TVEpisodes.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

@ -3,11 +3,11 @@
<children>
<LayoutGroup id="toplevel" layoutDirection="vert" itemSpacings="[40]">
<LayoutGroup id="main_group" layoutDirection="horiz" itemSpacings="[30]">
<Poster id="poster" width="534" height="400" />
<Poster id="poster" width="350" 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" />
<ScrollingLabel id="title" font="font:MediumBoldSystemFont" maxWidth="950" />
<LayoutGroup layoutDirection="horiz" itemSpacings="[20]">
<Label id="runtime" font="font:SmallestSystemFont" />
<LayoutGroup layoutDirection="horiz" itemSpacings="[-5]">
@ -16,10 +16,10 @@
</LayoutGroup>
<Label id="endtime" font="font:SmallestSystemFont" />
</LayoutGroup>
<Label id="overview" wrap="true" height="170" width="1200" maxLines="4" ellipsizeOnBoundary="true"/>
<Label id="overview" font="font:SmallestSystemFont" wrap="true" height="130" width="950" maxLines="3" ellipsizeOnBoundary="true"/>
<LayoutGroup layoutDirection="horiz" itemSpacings="[15]">
<Label id="video_codec" />
<ScrollingLabel id="audio_codec" />
<Label id="video_codec" font="font:SmallestSystemFont" />
<ScrollingLabel id="audio_codec" font="font:SmallestSystemFont" />
<label id="audio_codec_count" font="font:smallestSystemFont" vertAlign="top" color="#ceffff" />
</LayoutGroup>
</LayoutGroup>

View File

@ -201,6 +201,13 @@ sub Main (args as dynamic) as void
m.spinner = screenContent.findNode("spinner")
m.spinner.visible = true
group = CreateAudioPlayerGroup(screenContent.albumData.items)
else if isNodeEvent(msg, "instantMixSelected")
' User has selected instant mix
' User has selected playlist of of audio they want us to play
screenContent = msg.getRoSGNode()
m.spinner = screenContent.findNode("spinner")
m.spinner.visible = true
group = CreateInstantMixGroup(screenContent.albumData.items)
else if isNodeEvent(msg, "episodeSelected")
' If you select a TV Episode from ANYWHERE, follow this flow
node = getMsgPicker(msg, "picker")

View File

@ -380,6 +380,7 @@ function CreateMusicArtistDetailsGroup(musicartist)
group.albumData = MusicSongList(musicartist.id)
group.observeField("playSong", m.port)
group.observeField("playAllSelected", m.port)
group.observeField("instantMixSelected", m.port)
else
' User has albums under artists
group = CreateObject("roSGNode", "MusicArtistDetails")
@ -407,6 +408,9 @@ function CreateMusicAlbumDetailsGroup(album)
' Watch for user click on Play button on album
group.observeField("playAllSelected", m.port)
' Watch for user click on Instant Mix button on album
group.observeField("instantMixSelected", m.port)
return group
end function
@ -481,6 +485,30 @@ function CreateAudioPlayerGroup(audiodata)
return group
end function
' Play Instant Mix
function CreateInstantMixGroup(audiodata)
songList = CreateInstantMix(audiodata[0].id)
group = CreateObject("roSGNode", "NowPlaying")
group.observeField("state", m.port)
songIDArray = CreateObject("roArray", 0, true)
' All we need is an array of Song IDs the user selected to play.
for each song in songList.items
songIDArray.push(song.id)
end for
songIDArray.shift()
group.pageContent = songIDArray
group.musicArtistAlbumData = songList.items
m.global.sceneManager.callFunc("pushScene", group)
return group
end function
function CreatePersonView(personData as object) as object
person = CreateObject("roSGNode", "PersonDetails")
m.global.SceneManager.callFunc("pushScene", person)

View File

@ -209,6 +209,17 @@ function AudioItem(id as string)
return getJson(resp)
end function
' Get Instant Mix based on item
function CreateInstantMix(id as string)
url = Substitute("/Items/{0}/InstantMix", id)
resp = APIRequest(url, {
"UserId": get_setting("active_user"),
"Limit": 201
})
return getJson(resp)
end function
function AudioStream(id as string)
songData = AudioItem(id)
@ -264,7 +275,7 @@ function TVEpisodes(show_id as string, season_id as string)
data = getJson(resp)
results = []
for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played, "maxWidth": 712, "maxheight": 400 }
imgParams = { "AddPlayedIndicator": item.UserData.Played, "maxWidth": 400, "maxheight": 250 }
if item.UserData.PlayedPercentage <> invalid
param = { "PercentPlayed": item.UserData.PlayedPercentage }
imgParams.Append(param)
@ -272,7 +283,7 @@ function TVEpisodes(show_id as string, season_id as string)
tmp = CreateObject("roSGNode", "TVEpisodeData")
tmp.image = PosterImage(item.id, imgParams)
if tmp.image <> invalid
tmp.image.posterDisplayMode = "scaleToFit"
tmp.image.posterDisplayMode = "scaleToZoom"
end if
tmp.json = item
tmp.overview = ItemMetaData(item.id).overview