Merge pull request #1494 from cewert/fix-photos-itemgrid

This commit is contained in:
Charles Ewert 2023-11-14 19:21:57 -05:00 committed by GitHub
commit 6c759bca71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 254 additions and 35 deletions

View File

@ -801,20 +801,24 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.loadItemsTask.control = "stop"
return true
end if
else if key = "play"
else if key = "OK"
markupGrid = m.top.findNode("itemGrid")
itemToPlay = getItemFocused()
if itemToPlay <> invalid and itemToPlay.type = "Photo"
' Spawn photo player task
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.itemsNode = markupGrid
photoPlayer.itemIndex = markupGrid.itemFocused
m.global.sceneManager.callfunc("pushScene", photoPlayer)
return true
end if
else if key = "play"
itemToPlay = getItemFocused()
if itemToPlay <> invalid
m.top.quickPlayNode = itemToPlay
return true
else if itemToPlay <> invalid and itemToPlay.type = "Photo"
' Spawn photo player task
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.items = markupGrid
photoPlayer.itemIndex = markupGrid.itemFocused
m.global.sceneManager.callfunc("pushScene", photoPlayer)
return true
end if
else if key = "left" and topGrp.isinFocusChain()
m.top.alphaActive = true

View File

@ -72,7 +72,7 @@ sub setData()
m.top.widePosterUrl = ImageURL(datum.Id, "Backdrop", imgParams)
end if
else if datum.type = "Movie" or datum.type = "Video"
else if datum.type = "Movie"
m.top.isWatched = datum.UserData.Played
imgParams = {}
@ -96,6 +96,20 @@ sub setData()
imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
end if
else if datum.type = "Video"
m.top.isWatched = datum.UserData.Played
imgParams = {
"maxHeight": 261,
"maxWidth": 464
}
if datum.ImageTags <> invalid and datum.ImageTags.Primary <> invalid
imgParams.Append({ "Tag": datum.ImageTags.Primary })
end if
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
m.top.thumbnailUrl = m.top.posterURL
else if datum.type = "MusicAlbum"
params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 261 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
@ -106,5 +120,17 @@ sub setData()
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
else if datum.type = "Photo"
params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.posterUrl = m.top.thumbnailURL
else if datum.type = "PhotoAlbum"
params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
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

@ -32,7 +32,9 @@ sub OnScreenShown()
m.top.setFocus(true)
end if
refresh()
if not m.isFirstRun
refresh()
end if
' post the device profile the first time this screen is loaded
if m.isFirstRun

View File

@ -37,6 +37,7 @@ sub itemContentChanged()
m.itemText.maxWidth = itemData.imageWidth
m.itemTextExtra.width = itemData.imageWidth
m.itemTextExtra.visible = true
m.itemTextExtra.text = ""
m.backdrop.width = itemData.imageWidth
@ -179,6 +180,7 @@ sub itemContentChanged()
else
m.itemPoster.uri = itemData.thumbnailURL
end if
return
end if
@ -261,6 +263,38 @@ sub itemContentChanged()
return
end if
if itemData.type = "Photo"
m.itemText.text = itemData.name
m.itemPoster.uri = ImageURL(itemData.id)
' subtext
if isValidAndNotEmpty(itemData.json)
if isValid(itemData.json.ProductionYear)
m.itemTextExtra.text = itemData.json.ProductionYear.ToStr().trim()
end if
if isValidAndNotEmpty(itemData.json.Album)
if m.itemTextExtra.text = ""
m.itemTextExtra.text = tr("Album") + ": " + itemData.json.Album.trim()
else
m.itemTextExtra.text = m.itemTextExtra.text + " - " + tr("Album") + ": " + itemData.json.Album.trim()
end if
end if
end if
return
end if
if itemData.type = "PhotoAlbum"
m.itemText.text = itemData.name
m.itemPoster.uri = ImageURL(itemData.id)
' subtext
if isValid(itemData.json.ChildCount)
m.itemTextExtra.text = itemData.json.ChildCount.ToStr().trim() + " items"
end if
return
end if
m.log.warn("Unhandled Home Item Type", itemData.type)
end sub

View File

@ -258,13 +258,6 @@ end sub
' Update home row data
sub updateHomeRows()
if m.global.playstateTask.state = "run"
m.global.playstateTask.observeField("state", "updateHomeRows")
return
end if
m.global.playstateTask.unobserveField("state")
' If resume section exists, reload row's data
if m.homeSectionIndexes.doesExist("resume")
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")

View File

@ -1,20 +1,28 @@
import "pkg:/source/api/Image.bs"
import "pkg:/source/utils/config.bs"
import "pkg:/source/api/baserequest.bs"
import "pkg:/source/utils/misc.bs"
sub init()
m.top.functionName = "loadItems"
end sub
sub loadItems()
item = m.top.itemContent
if item <> invalid
params = {
maxHeight: 1080,
maxWidth: 1920
}
params = {
maxHeight: 1080,
maxWidth: 1920
}
if isValid(m.top.itemNodeContent)
item = m.top.itemNodeContent
m.top.results = ImageURL(item.Id, "Primary", params)
else if isValid(m.top.itemArrayContent)
item = m.top.itemArrayContent
m.top.results = ImageURL(item.Id, "Primary", params)
else
m.top.results = invalid
end if
end sub

View File

@ -2,7 +2,8 @@
<component name="LoadPhotoTask" extends="Task">
<interface>
<field id="itemContent" type="node" />
<field id="itemNodeContent" type="node" />
<field id="itemArrayContent" type="assocarray" />
<field id="results" type="string" />
</interface>
</component>

View File

@ -22,8 +22,19 @@ end sub
sub itemContentChanged()
if isValidToContinue(m.top.itemIndex)
m.LoadLibrariesTask = createObject("roSGNode", "LoadPhotoTask")
itemContent = m.top.items.content.getChild(m.top.itemIndex)
m.LoadLibrariesTask.itemContent = itemContent
if isValid(m.top.itemsNode)
if isValid(m.top.itemsNode.content)
m.LoadLibrariesTask.itemNodeContent = m.top.itemsNode.content.getChild(m.top.itemIndex)
else if isValidAndNotEmpty(m.top.itemsNode.id)
m.LoadLibrariesTask.itemNodeContent = m.top.itemsNode
end if
else if isValid(m.top.itemsArray)
itemContent = m.top.itemsArray[m.top.itemIndex]
m.LoadLibrariesTask.itemArrayContent = itemContent
else
return
end if
m.LoadLibrariesTask.observeField("results", "onPhotoLoaded")
m.LoadLibrariesTask.control = "RUN"
end if
@ -53,8 +64,22 @@ sub nextSlide()
m.slideshowTimer.control = "start"
end if
else if m.random = true
index = rnd(m.top.items.content.getChildCount() - 1)
if isValidToContinue(index)
index = invalid
if isValid(m.top.itemsNode)
if isValidAndNotEmpty(m.top.itemsNode.content)
index = rnd(m.top.itemsNode.content.getChildCount() - 1)
else
' we're dealing with a single photo
return
end if
else if isValid(m.top.itemsArray)
if m.top.itemsArray.count() > 0
index = rnd(m.top.itemsArray.count() - 1)
end if
end if
if isValid(index) and isValidToContinue(index)
m.top.itemIndex = index
m.slideshowTimer.control = "start"
end if
@ -66,6 +91,23 @@ sub statusUpdate()
m.hideStatusAnimation.control = "start"
end sub
' JFScreen hook.
' Used to ensure tasks are stopped
sub OnScreenHidden()
m.slideshowTimer.control = "stop"
m.statusTimer.control = "stop"
end sub
' isSlideshow component field has changed
sub isSlideshowChanged()
m.slideshow = m.top.isSlideshow
end sub
' isRandom component field has changed
sub isRandomChanged()
m.random = m.top.isRandom
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
@ -116,8 +158,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
end function
function isValidToContinue(index as integer)
if isValid(m.top.items) and isValid(m.top.items.content)
if index >= 0 and index < m.top.items.content.getChildCount()
if isValid(m.top.itemsNode)
if isValidAndNotEmpty(m.top.itemsNode.content)
if index >= 0 and index < m.top.itemsNode.content.getChildCount()
return true
end if
else if isValidAndNotEmpty(m.top.itemsNode) and index = 0
return true
end if
else if isValidAndNotEmpty(m.top.itemsArray)
if index >= 0 and index < m.top.itemsArray.count()
return true
end if
end if

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<component name="PhotoDetails" extends="JFGroup">
<component name="PhotoDetails" extends="JFScreen">
<children>
<Poster id="photo" width="1920" height="1080" loadDisplayMode="scaleToFit" />
<Rectangle id="background" color="0x101010EE" height="120" width="500" Translation="[700, -150]" opacity="0">
@ -19,7 +19,10 @@
</children>
<interface>
<field id="items" type="node" />
<field id="itemsNode" type="node" />
<field id="itemsArray" type="roArray" />
<field id="isSlideshow" type="bool" onChange="isSlideshowChanged" />
<field id="isRandom" type="bool" onChange="isRandomChanged" />
<field id="itemIndex" type="integer" value="-1" onChange="itemContentChanged" />
</interface>
</component>

View File

@ -201,6 +201,10 @@ sub Main (args as dynamic) as void
quickplay.tvChannel(itemNode)
else if itemType = "program"
quickplay.program(itemNode)
else if itemType = "photo"
quickplay.photo(itemNode)
else if itemType = "photoalbum"
quickplay.photoAlbum(itemNode)
end if
m.global.queueManager.callFunc("playQueue")
@ -293,7 +297,31 @@ sub Main (args as dynamic) as void
end if
else if selectedItemType = "Photo"
' Nothing to do here, handled in ItemGrid
' only handle selection if it's from the home screen
if selectedItem.isSubType("HomeData")
print "a photo was selected from the home screen"
print "selectedItem=", selectedItem
quickplay.photo(selectedItem)
end if
else if selectedItemType = "PhotoAlbum"
print "a photo album was selected"
print "selectedItem=", selectedItem
' grab all photos inside photo album
photoAlbumData = api.users.GetItemsByQuery(m.global.session.user.id, {
"parentId": selectedItem.id,
"includeItemTypes": "Photo",
"Recursive": true
})
print "photoAlbumData=", photoAlbumData
if isValid(photoAlbumData) and isValidAndNotEmpty(photoAlbumData.items)
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.itemsArray = photoAlbumData.items
photoPlayer.itemIndex = 0
m.global.sceneManager.callfunc("pushScene", photoPlayer)
end if
else if selectedItemType = "MusicArtist"
group = CreateArtistView(selectedItem.json)
if not isValid(group)

View File

@ -309,6 +309,9 @@ function isValidAndNotEmpty(input as dynamic) as boolean
if inputType = "string" or inputType = "rostring"
trimmedInput = input.trim()
return trimmedInput <> ""
else if inputType = "rosgnode"
inputId = input.id
return inputId <> invalid
else if countableTypes.doesExist(inputType)
return input.count() > 0
else

View File

@ -54,6 +54,39 @@ namespace quickplay
m.global.queueManager.callFunc("push", itemNode)
end sub
' A single photo.
sub photo(itemNode as object)
if not isValid(itemNode) or not isValid(itemNode.id) then return
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.itemsNode = itemNode
photoPlayer.itemIndex = 0
m.global.sceneManager.callfunc("pushScene", photoPlayer)
end sub
' A photo album.
sub photoAlbum(itemNode as object)
if not isValid(itemNode) or not isValid(itemNode.id) then return
' grab all photos inside photo album
photoAlbumData = api.users.GetItemsByQuery(m.global.session.user.id, {
"parentId": itemNode.id,
"includeItemTypes": "Photo",
"sortBy": "Random",
"Recursive": true
})
print "photoAlbumData=", photoAlbumData
if isValid(photoAlbumData) and isValidAndNotEmpty(photoAlbumData.items)
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.isSlideshow = true
photoPlayer.isRandom = false
photoPlayer.itemsArray = photoAlbumData.items
photoPlayer.itemIndex = 0
m.global.sceneManager.callfunc("pushScene", photoPlayer)
end if
end sub
' A music album.
' Play the entire album starting with track 1.
sub album(itemNode as object)
@ -370,6 +403,7 @@ namespace quickplay
}
' modify api query based on folder type
folderType = Lcase(itemNode.json.type)
print "folderType=", folderType
if folderType = "studio"
paramArray["studioIds"] = itemNode.id
else if folderType = "genre"
@ -381,6 +415,11 @@ namespace quickplay
paramArray["genreIds"] = itemNode.id
paramArray.delete("videoTypes")
paramArray["includeItemTypes"] = "Audio"
else if folderType = "photoalbum"
paramArray["parentId"] = itemNode.id
paramArray["includeItemTypes"] = "Photo"
paramArray.delete("videoTypes")
paramArray.delete("Recursive")
else
paramArray["parentId"] = itemNode.id
end if
@ -401,7 +440,16 @@ namespace quickplay
quickplay.multipleSeries(folderData.items)
end if
else
quickplay.pushToQueue(folderData.items, true)
if folderType = "photoalbum"
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.isSlideshow = true
photoPlayer.isRandom = false
photoPlayer.itemsArray = folderData.items
photoPlayer.itemIndex = 0
m.global.sceneManager.callfunc("pushScene", photoPlayer)
else
quickplay.pushToQueue(folderData.items, true)
end if
end if
end if
end sub
@ -515,7 +563,26 @@ namespace quickplay
if isValid(data) and isValidAndNotEmpty(data.items)
quickplay.pushToQueue(data.Items)
end if
' else if collectionType = "homevideos" ' also used for a "Photo" library
else if collectionType = "homevideos"
' Photo library - items can be type video, photo, or photoAlbum
' grab all photos inside library
folderData = api.users.GetItemsByQuery(m.global.session.user.id, {
"parentId": itemNode.id,
"includeItemTypes": "Photo",
"sortBy": "Random",
"Recursive": true
})
print "folderData=", folderData
if isValid(folderData) and isValidAndNotEmpty(folderData.items)
photoPlayer = CreateObject("roSgNode", "PhotoDetails")
photoPlayer.isSlideshow = true
photoPlayer.isRandom = false
photoPlayer.itemsArray = folderData.items
photoPlayer.itemIndex = 0
m.global.sceneManager.callfunc("pushScene", photoPlayer)
end if
else
print "Quick Play WARNING: Unknown collection type"
end if