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" m.loadItemsTask.control = "stop"
return true return true
end if end if
else if key = "play" else if key = "OK"
markupGrid = m.top.findNode("itemGrid") markupGrid = m.top.findNode("itemGrid")
itemToPlay = getItemFocused() 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 if itemToPlay <> invalid
m.top.quickPlayNode = itemToPlay m.top.quickPlayNode = itemToPlay
return true 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 end if
else if key = "left" and topGrp.isinFocusChain() else if key = "left" and topGrp.isinFocusChain()
m.top.alphaActive = true m.top.alphaActive = true

View File

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

View File

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

View File

@ -37,6 +37,7 @@ sub itemContentChanged()
m.itemText.maxWidth = itemData.imageWidth m.itemText.maxWidth = itemData.imageWidth
m.itemTextExtra.width = itemData.imageWidth m.itemTextExtra.width = itemData.imageWidth
m.itemTextExtra.visible = true m.itemTextExtra.visible = true
m.itemTextExtra.text = ""
m.backdrop.width = itemData.imageWidth m.backdrop.width = itemData.imageWidth
@ -179,6 +180,7 @@ sub itemContentChanged()
else else
m.itemPoster.uri = itemData.thumbnailURL m.itemPoster.uri = itemData.thumbnailURL
end if end if
return return
end if end if
@ -261,6 +263,38 @@ sub itemContentChanged()
return return
end if 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) m.log.warn("Unhandled Home Item Type", itemData.type)
end sub end sub

View File

@ -258,13 +258,6 @@ end sub
' Update home row data ' Update home row data
sub updateHomeRows() 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 resume section exists, reload row's data
if m.homeSectionIndexes.doesExist("resume") if m.homeSectionIndexes.doesExist("resume")
m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems") m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems")

View File

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

View File

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

View File

@ -22,8 +22,19 @@ end sub
sub itemContentChanged() sub itemContentChanged()
if isValidToContinue(m.top.itemIndex) if isValidToContinue(m.top.itemIndex)
m.LoadLibrariesTask = createObject("roSGNode", "LoadPhotoTask") m.LoadLibrariesTask = createObject("roSGNode", "LoadPhotoTask")
itemContent = m.top.items.content.getChild(m.top.itemIndex) if isValid(m.top.itemsNode)
m.LoadLibrariesTask.itemContent = itemContent 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.observeField("results", "onPhotoLoaded")
m.LoadLibrariesTask.control = "RUN" m.LoadLibrariesTask.control = "RUN"
end if end if
@ -53,8 +64,22 @@ sub nextSlide()
m.slideshowTimer.control = "start" m.slideshowTimer.control = "start"
end if end if
else if m.random = true else if m.random = true
index = rnd(m.top.items.content.getChildCount() - 1) index = invalid
if isValidToContinue(index)
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.top.itemIndex = index
m.slideshowTimer.control = "start" m.slideshowTimer.control = "start"
end if end if
@ -66,6 +91,23 @@ sub statusUpdate()
m.hideStatusAnimation.control = "start" m.hideStatusAnimation.control = "start"
end sub 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 function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false if not press then return false
@ -116,8 +158,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
end function end function
function isValidToContinue(index as integer) function isValidToContinue(index as integer)
if isValid(m.top.items) and isValid(m.top.items.content) if isValid(m.top.itemsNode)
if index >= 0 and index < m.top.items.content.getChildCount() 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 return true
end if end if
end if end if

View File

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

View File

@ -201,6 +201,10 @@ sub Main (args as dynamic) as void
quickplay.tvChannel(itemNode) quickplay.tvChannel(itemNode)
else if itemType = "program" else if itemType = "program"
quickplay.program(itemNode) quickplay.program(itemNode)
else if itemType = "photo"
quickplay.photo(itemNode)
else if itemType = "photoalbum"
quickplay.photoAlbum(itemNode)
end if end if
m.global.queueManager.callFunc("playQueue") m.global.queueManager.callFunc("playQueue")
@ -293,7 +297,31 @@ sub Main (args as dynamic) as void
end if end if
else if selectedItemType = "Photo" 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" else if selectedItemType = "MusicArtist"
group = CreateArtistView(selectedItem.json) group = CreateArtistView(selectedItem.json)
if not isValid(group) if not isValid(group)

View File

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

View File

@ -54,6 +54,39 @@ namespace quickplay
m.global.queueManager.callFunc("push", itemNode) m.global.queueManager.callFunc("push", itemNode)
end sub 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. ' A music album.
' Play the entire album starting with track 1. ' Play the entire album starting with track 1.
sub album(itemNode as object) sub album(itemNode as object)
@ -370,6 +403,7 @@ namespace quickplay
} }
' modify api query based on folder type ' modify api query based on folder type
folderType = Lcase(itemNode.json.type) folderType = Lcase(itemNode.json.type)
print "folderType=", folderType
if folderType = "studio" if folderType = "studio"
paramArray["studioIds"] = itemNode.id paramArray["studioIds"] = itemNode.id
else if folderType = "genre" else if folderType = "genre"
@ -381,6 +415,11 @@ namespace quickplay
paramArray["genreIds"] = itemNode.id paramArray["genreIds"] = itemNode.id
paramArray.delete("videoTypes") paramArray.delete("videoTypes")
paramArray["includeItemTypes"] = "Audio" paramArray["includeItemTypes"] = "Audio"
else if folderType = "photoalbum"
paramArray["parentId"] = itemNode.id
paramArray["includeItemTypes"] = "Photo"
paramArray.delete("videoTypes")
paramArray.delete("Recursive")
else else
paramArray["parentId"] = itemNode.id paramArray["parentId"] = itemNode.id
end if end if
@ -401,7 +440,16 @@ namespace quickplay
quickplay.multipleSeries(folderData.items) quickplay.multipleSeries(folderData.items)
end if end if
else 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 if end if
end sub end sub
@ -515,7 +563,26 @@ namespace quickplay
if isValid(data) and isValidAndNotEmpty(data.items) if isValid(data) and isValidAndNotEmpty(data.items)
quickplay.pushToQueue(data.Items) quickplay.pushToQueue(data.Items)
end if 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 else
print "Quick Play WARNING: Unknown collection type" print "Quick Play WARNING: Unknown collection type"
end if end if