Redesign movie detail view
This commit is contained in:
parent
32382e3330
commit
e07e050446
15 changed files with 299 additions and 120 deletions
|
|
@ -13,6 +13,7 @@ sub init()
|
|||
m.top.observeField("width", "onWidthChanged")
|
||||
m.top.observeField("padding", "onPaddingChanged")
|
||||
m.top.observeField("focus", "onFocusChanged")
|
||||
m.top.observeField("iconBlendColor", "onIconBlendColorChanged")
|
||||
end sub
|
||||
|
||||
sub onTextColorChanged()
|
||||
|
|
@ -35,7 +36,7 @@ sub onFocusChanged()
|
|||
if m.top.focus
|
||||
m.buttonText.color = m.top.focusTextColor
|
||||
m.buttonBackground.blendColor = m.top.focusBackground
|
||||
m.buttonIcon.uri = m.top.focusIcon
|
||||
m.buttonIcon.uri = m.top.focusIcon <> "" ? m.top.focusIcon : m.top.icon
|
||||
else
|
||||
m.buttonText.color = m.top.textColor
|
||||
m.buttonBackground.blendColor = m.top.background
|
||||
|
|
@ -53,6 +54,10 @@ sub onIconChanged()
|
|||
m.buttonIcon.uri = m.top.icon
|
||||
end sub
|
||||
|
||||
sub onIconBlendColorChanged()
|
||||
m.buttonIcon.blendcolor = m.top.iconBlendColor
|
||||
end sub
|
||||
|
||||
sub onTextChanged()
|
||||
m.buttonText.text = m.top.text
|
||||
end sub
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<interface>
|
||||
<field id="background" type="color" value="" />
|
||||
<field id="focusBackground" type="color" value="" />
|
||||
<field id="iconBlendColor" type="color" value="" />
|
||||
<field id="textColor" type="color" value="" />
|
||||
<field id="focusTextColor" type="color" value="" />
|
||||
<field id="text" type="string" value="" />
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
import "pkg:/source/utils/misc.bs"
|
||||
import "pkg:/source/utils/config.bs"
|
||||
import "pkg:/source/api/Image.bs"
|
||||
|
||||
import "pkg:/source/enums/AnimationControl.bs"
|
||||
import "pkg:/source/enums/AnimationState.bs"
|
||||
import "pkg:/source/enums/PosterLoadStatus.bs"
|
||||
import "pkg:/source/enums/KeyCode.bs"
|
||||
import "pkg:/source/enums/ViewLoadStatus.bs"
|
||||
import "pkg:/source/enums/ColorPalette.bs"
|
||||
import "pkg:/source/enums/ImageType.bs"
|
||||
|
||||
sub init()
|
||||
m.container = m.top.findnode("container")
|
||||
m.extrasGrp = m.top.findnode("extrasGrp")
|
||||
m.extrasGrid = m.top.findNode("extrasGrid")
|
||||
m.top.optionsAvailable = false
|
||||
|
|
@ -13,18 +18,16 @@ sub init()
|
|||
m.options = m.top.findNode("movieOptions")
|
||||
m.infoGroup = m.top.findNode("infoGroup")
|
||||
|
||||
main = m.top.findNode("main_group")
|
||||
main.translation = [96, 175]
|
||||
overview = m.top.findNode("overview")
|
||||
overview.width = 1920 - 96 - 300 - 96 - 30
|
||||
|
||||
m.details = m.top.findNode("details")
|
||||
m.tagline = m.top.findNode("tagline")
|
||||
|
||||
m.buttonGrp = m.top.findNode("buttons")
|
||||
m.buttonGrp.setFocus(true)
|
||||
m.top.lastFocus = m.buttonGrp
|
||||
|
||||
setButtonColors()
|
||||
|
||||
m.loadStatus = ViewLoadStatus.INIT
|
||||
|
||||
' Only allow Admins to see Edit Subtitles button
|
||||
if not m.global.session.user.policy.EnableSubtitleManagement
|
||||
editSubtitleButton = m.top.findNode("editSubtitlesButton")
|
||||
|
|
@ -34,6 +37,21 @@ sub init()
|
|||
m.top.observeField("itemContent", "itemContentChanged")
|
||||
end sub
|
||||
|
||||
sub setButtonColors()
|
||||
buttonList = ["play-button", "options-button", "watched-button", "favorite-button", "editSubtitlesButton", "trailer-button"]
|
||||
|
||||
for each button in buttonList
|
||||
buttonNode = m.top.findNode(button)
|
||||
buttonNode.background = ColorPalette.TRANSPARENT
|
||||
buttonNode.textColor = ColorPalette.WHITE
|
||||
buttonNode.focusBackground = ColorPalette.HIGHLIGHT
|
||||
buttonNode.focusTextColor = ColorPalette.WHITE
|
||||
end for
|
||||
|
||||
firstButton = m.top.findNode(buttonList[0])
|
||||
firstButton.setFocus(true)
|
||||
firstButton.focus = true
|
||||
end sub
|
||||
|
||||
' OnScreenShown: Callback function when view is presented on screen
|
||||
'
|
||||
|
|
@ -44,6 +62,15 @@ sub OnScreenShown()
|
|||
else
|
||||
m.buttonGrp.setFocus(true)
|
||||
end if
|
||||
|
||||
if m.loadStatus = ViewLoadStatus.INIT
|
||||
m.loadStatus = ViewLoadStatus.FIRSTLOAD
|
||||
return
|
||||
end if
|
||||
|
||||
m.loadStatus = ViewLoadStatus.RELOAD
|
||||
|
||||
m.top.refreshMovieDetailsData = not m.top.refreshMovieDetailsData
|
||||
end sub
|
||||
|
||||
sub trailerAvailableChanged()
|
||||
|
|
@ -51,23 +78,63 @@ sub trailerAvailableChanged()
|
|||
m.buttonGrp.removeChild(m.top.findNode("trailer-button"))
|
||||
return
|
||||
end if
|
||||
end sub
|
||||
|
||||
' add trailor button to button group
|
||||
trailerButton = CreateObject("roSGNode", "Button")
|
||||
trailerButton.id = "trailer-button"
|
||||
trailerButton.text = tr("Play Trailer")
|
||||
trailerButton.iconUri = ""
|
||||
trailerButton.focusedIconUri = ""
|
||||
trailerButton.maxWidth = "300"
|
||||
trailerButton.minWidth = "280"
|
||||
m.buttonGrp.appendChild(trailerButton)
|
||||
' setBackdropImage: If item has a backdrop image, use it as the background for the view
|
||||
'
|
||||
' @param {object} itemData - meta data for current item
|
||||
sub setBackdropImage(itemData as object)
|
||||
if isValidAndNotEmpty(itemData.BackdropImageTags)
|
||||
imageVersion = ImageType.BACKDROP
|
||||
imageTag = itemData.BackdropImageTags[0]
|
||||
else
|
||||
imageVersion = ImageType.PRIMARY
|
||||
imageTag = itemData.ImageTags.Primary
|
||||
end if
|
||||
|
||||
movieBackdrop = createObject("roSGNode", "Poster")
|
||||
movieBackdrop.loadDisplayMode = "scaleToZoom"
|
||||
movieBackdrop.translation = "[0,0]"
|
||||
movieBackdrop.width = "1920"
|
||||
movieBackdrop.height = "1080"
|
||||
movieBackdrop.opacity = .3
|
||||
movieBackdrop.uri = ImageURL(m.top.id, imageVersion, {
|
||||
"maxWidth": 1920,
|
||||
"Tag": imageTag
|
||||
})
|
||||
m.top.insertChild(movieBackdrop, 0)
|
||||
end sub
|
||||
|
||||
' setLogoImage: If item has a logo image, add it to the view
|
||||
'
|
||||
' @param {object} itemData - meta data for current item
|
||||
sub setLogoImage(itemData as object)
|
||||
' No logo found
|
||||
if not isChainValid(itemData, "ImageTags.Logo")
|
||||
m.container.translation = "[100, 300]"
|
||||
return
|
||||
end if
|
||||
|
||||
m.top.overhangTitle = ""
|
||||
|
||||
movieLogo = createObject("roSGNode", "Poster")
|
||||
movieLogo.loadDisplayMode = "scaleToFit"
|
||||
movieLogo.width = "300"
|
||||
movieLogo.height = "300"
|
||||
movieLogo.uri = ImageURL(m.top.id, ImageType.LOGO, {
|
||||
"maxHeight": 300,
|
||||
"maxWidth": 300,
|
||||
"Tag": itemData.ImageTags.Logo
|
||||
})
|
||||
|
||||
m.container.insertChild(movieLogo, 0)
|
||||
end sub
|
||||
|
||||
sub itemContentChanged()
|
||||
' Updates video metadata
|
||||
item = m.top.itemContent
|
||||
|
||||
if not isValid(item) or not isValid(item.json)
|
||||
if not isChainValid(item, "json")
|
||||
m.buttonGrp.visible = true
|
||||
stopLoadingSpinner()
|
||||
return
|
||||
|
|
@ -75,7 +142,21 @@ sub itemContentChanged()
|
|||
|
||||
itemData = item.json
|
||||
m.top.id = itemData.id
|
||||
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
|
||||
|
||||
if itemData.UserData.PlaybackPositionTicks > 0
|
||||
playButton = m.top.findNode("play-button")
|
||||
playButton.text = `Play / Resume from ${ticksToHuman(itemData.UserData.PlaybackPositionTicks)}`
|
||||
end if
|
||||
setWatchedColor()
|
||||
setFavoriteColor()
|
||||
|
||||
' We don't need to update everything if this is a reload
|
||||
if m.loadStatus = ViewLoadStatus.RELOAD then return
|
||||
|
||||
m.top.overhangTitle = itemData.name
|
||||
|
||||
setBackdropImage(itemData)
|
||||
setLogoImage(itemData)
|
||||
|
||||
' Set default video source if user hasn't selected one yet
|
||||
if m.top.selectedVideoStreamId = "" and isValid(itemData.MediaSources)
|
||||
|
|
@ -86,7 +167,6 @@ sub itemContentChanged()
|
|||
SetDefaultAudioTrack(itemData)
|
||||
|
||||
' Handle all "As Is" fields
|
||||
m.top.overhangTitle = itemData.name
|
||||
setFieldText("releaseYear", itemData.productionYear)
|
||||
setFieldText("overview", itemData.overview)
|
||||
|
||||
|
|
@ -126,37 +206,25 @@ sub itemContentChanged()
|
|||
end if
|
||||
end if
|
||||
|
||||
if itemData.genres.count() > 0
|
||||
setFieldText("genres", tr("Genres") + ": " + itemData.genres.join(", "))
|
||||
if isValidAndNotEmpty(itemData.genres)
|
||||
setFieldText("genres", itemData.genres[0])
|
||||
else
|
||||
m.top.findNode("details").removeChild(m.top.findNode("genres"))
|
||||
end if
|
||||
|
||||
' show tags if there are no genres to display
|
||||
if itemData.genres.count() = 0 and isValid(itemData.tags) and itemData.tags.count() > 0
|
||||
setFieldText("genres", tr("Tags") + ": " + itemData.tags.join(", "))
|
||||
end if
|
||||
|
||||
directors = []
|
||||
for each person in itemData.people
|
||||
if person.type = "Director"
|
||||
if LCase(person.type) = "director"
|
||||
directors.push(person.name)
|
||||
end if
|
||||
end for
|
||||
if directors.count() > 0
|
||||
|
||||
if isValidAndNotEmpty(directors)
|
||||
setFieldText("director", tr("Director") + ": " + directors.join(", "))
|
||||
else
|
||||
m.top.findNode("details").removeChild(m.top.findNode("director"))
|
||||
end if
|
||||
|
||||
if m.global.session.user.settings["ui.details.hidetagline"] = false
|
||||
if itemData.taglines.count() > 0
|
||||
setFieldText("tagline", itemData.taglines[0])
|
||||
end if
|
||||
else
|
||||
m.details.removeChild(m.tagline)
|
||||
end if
|
||||
|
||||
'set aired date if type is Episode
|
||||
if isValid(itemData.PremiereDate) and itemData.Type = "Episode"
|
||||
airDate = CreateObject("roDateTime")
|
||||
|
|
@ -166,8 +234,6 @@ sub itemContentChanged()
|
|||
m.infoGroup.removeChild(m.top.findNode("releaseYear"))
|
||||
end if
|
||||
|
||||
setFavoriteColor()
|
||||
setWatchedColor()
|
||||
SetUpVideoOptions(itemData.mediaSources)
|
||||
SetUpAudioOptions(itemData.mediaStreams)
|
||||
|
||||
|
|
@ -295,13 +361,11 @@ sub setFavoriteColor()
|
|||
fave = m.top.itemContent.favorite
|
||||
fave_button = m.top.findNode("favorite-button")
|
||||
if isValid(fave) and fave
|
||||
fave_button.textColor = "#00ff00ff"
|
||||
fave_button.focusedTextColor = "#269926ff"
|
||||
fave_button.text = tr("Favorite")
|
||||
fave_button.iconBlendColor = ColorPalette.RED
|
||||
fave_button.text = tr("Favorited")
|
||||
else
|
||||
fave_button.textColor = "0xddddddff"
|
||||
fave_button.focusedTextColor = "#262626ff"
|
||||
fave_button.text = tr("Set Favorite")
|
||||
fave_button.iconBlendColor = ColorPalette.WHITE
|
||||
fave_button.text = tr("Mark As Favorite")
|
||||
end if
|
||||
end sub
|
||||
|
||||
|
|
@ -309,13 +373,9 @@ sub setWatchedColor()
|
|||
watched = m.top.itemContent.watched
|
||||
watched_button = m.top.findNode("watched-button")
|
||||
if watched
|
||||
watched_button.textColor = "#ff0000ff"
|
||||
watched_button.focusedTextColor = "#992626ff"
|
||||
watched_button.text = tr("Watched")
|
||||
else
|
||||
watched_button.textColor = "0xddddddff"
|
||||
watched_button.focusedTextColor = "#262626ff"
|
||||
watched_button.text = tr("Set Watched")
|
||||
watched_button.text = tr("Mark As Watched")
|
||||
end if
|
||||
end sub
|
||||
|
||||
|
|
@ -369,23 +429,17 @@ sub videoOptionsClosed()
|
|||
m.top.findNode("buttons").setFocus(true)
|
||||
end sub
|
||||
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
|
||||
' Due to the way the button pressed event works, need to catch the release for the button as the press is being sent
|
||||
' directly to the main loop. Will get this sorted in the layout update for Movie Details
|
||||
if key = KeyCode.OK and m.top.findNode("options-button").isInFocusChain()
|
||||
m.options.visible = true
|
||||
m.options.setFocus(true)
|
||||
end if
|
||||
|
||||
if key = KeyCode.DOWN and m.buttonGrp.isInFocusChain()
|
||||
sub onButtonGroupEscape()
|
||||
if LCase(m.buttonGrp.escape) = "down"
|
||||
m.top.lastFocus = m.extrasGrid
|
||||
m.extrasGrid.setFocus(true)
|
||||
m.top.findNode("VertSlider").reverse = false
|
||||
m.top.findNode("extrasFader").reverse = false
|
||||
m.top.findNode("pplAnime").control = AnimationControl.START
|
||||
return true
|
||||
end if
|
||||
end sub
|
||||
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
|
||||
if key = KeyCode.UP and m.top.findNode("extrasGrid").isInFocusChain()
|
||||
if m.extrasGrid.itemFocused = 0
|
||||
|
|
@ -394,6 +448,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
|||
m.top.findNode("extrasFader").reverse = true
|
||||
m.top.findNode("pplAnime").control = AnimationControl.START
|
||||
m.buttonGrp.setFocus(true)
|
||||
m.buttonGrp.getChild(m.buttonGrp.getChildCount() - 1).focus = true
|
||||
return true
|
||||
end if
|
||||
|
||||
|
|
@ -402,6 +457,75 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
|||
|
||||
if not press then return false
|
||||
|
||||
if key = KeyCode.OK and m.buttonGrp.hasFocus()
|
||||
m.loadStatus = ViewLoadStatus.RELOAD
|
||||
|
||||
buttonList = m.buttonGrp.getChildren(-1, 0)
|
||||
|
||||
i = 0
|
||||
for each button in buttonList
|
||||
if button.focus
|
||||
m.top.buttonSelected = button.id
|
||||
if button.id = "options-button"
|
||||
m.options.visible = true
|
||||
m.options.setFocus(true)
|
||||
end if
|
||||
exit for
|
||||
end if
|
||||
i++
|
||||
end for
|
||||
|
||||
return true
|
||||
end if
|
||||
|
||||
if key = KeyCode.DOWN and m.buttonGrp.hasFocus()
|
||||
buttonList = m.buttonGrp.getChildren(-1, 0)
|
||||
|
||||
i = 0
|
||||
for each button in buttonList
|
||||
if button.focus
|
||||
button.focus = false
|
||||
if i + 1 < m.buttonGrp.getChildCount()
|
||||
nextButton = m.buttonGrp.getChild(i + 1)
|
||||
if isValid(nextButton)
|
||||
nextButton.focus = true
|
||||
end if
|
||||
else
|
||||
m.top.lastFocus = m.extrasGrid
|
||||
m.extrasGrid.setFocus(true)
|
||||
m.top.findNode("VertSlider").reverse = false
|
||||
m.top.findNode("extrasFader").reverse = false
|
||||
m.top.findNode("pplAnime").control = AnimationControl.START
|
||||
end if
|
||||
exit for
|
||||
end if
|
||||
i++
|
||||
end for
|
||||
|
||||
return true
|
||||
end if
|
||||
|
||||
if key = KeyCode.UP and m.buttonGrp.hasFocus()
|
||||
buttonList = m.buttonGrp.getChildren(-1, 0)
|
||||
|
||||
i = 0
|
||||
for each button in buttonList
|
||||
if button.focus
|
||||
if i - 1 >= 0
|
||||
button.focus = false
|
||||
nextButton = m.buttonGrp.getChild(i - 1)
|
||||
if isValid(nextButton)
|
||||
nextButton.focus = true
|
||||
end if
|
||||
end if
|
||||
exit for
|
||||
end if
|
||||
i++
|
||||
end for
|
||||
|
||||
return true
|
||||
end if
|
||||
|
||||
if key = KeyCode.BACK
|
||||
if m.options.visible = true
|
||||
m.options.visible = false
|
||||
|
|
@ -410,11 +534,20 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
|||
return true
|
||||
end if
|
||||
|
||||
if m.top.findNode("extrasGrid").isInFocusChain()
|
||||
m.top.lastFocus = m.buttonGrp
|
||||
m.top.findNode("VertSlider").reverse = true
|
||||
m.top.findNode("extrasFader").reverse = true
|
||||
m.top.findNode("pplAnime").control = AnimationControl.START
|
||||
m.buttonGrp.setFocus(true)
|
||||
m.buttonGrp.getChild(m.buttonGrp.getChildCount() - 1).focus = true
|
||||
return true
|
||||
end if
|
||||
|
||||
return false
|
||||
end if
|
||||
|
||||
if key = KeyCode.PLAY and m.extrasGrid.hasFocus()
|
||||
print "Play was pressed from the movie details extras slider"
|
||||
if isValid(m.extrasGrid.focusedItem)
|
||||
m.top.quickPlayNode = m.extrasGrid.focusedItem
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -1,46 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<component name="MovieDetails" extends="JFScreen">
|
||||
<children>
|
||||
<LayoutGroup id="main_group" layoutDirection="horiz" itemSpacings="[30]">
|
||||
<Poster id="moviePoster" translation="[250,150]" width="300" height="450" />
|
||||
<LayoutGroup id="container" layoutDirection="vert" itemSpacings="[30]" translation="[100, 0]">
|
||||
<LayoutGroup id="infoGroup" layoutDirection="horiz" horizAlignment="left" itemSpacings="[20]">
|
||||
<Label id="releaseYear" font="font:SmallestSystemFont" />
|
||||
<Label font="font:SmallestSystemFont" text="•" />
|
||||
<Label id="genres" font="font:SmallestSystemFont" />
|
||||
<Label id="officialRating" font="font:SmallestBoldSystemFont" />
|
||||
<Label id="runtime" font="font:SmallestSystemFont" />
|
||||
|
||||
<LayoutGroup layoutDirection="vert" translation="[455, 150]" itemSpacings="[25]" id="details">
|
||||
<LayoutGroup layoutDirection="horiz" itemSpacings="[100]" id="infoGroup">
|
||||
<Label id="releaseYear" />
|
||||
<Label id="runtime" />
|
||||
<Label id="officialRating" />
|
||||
<LayoutGroup id="communityRatingGroup" layoutDirection="horiz" itemSpacings="[-5]">
|
||||
<Poster id="star" uri="pkg:/images/sharp_star_white_18dp.png" height="32" width="32" blendColor="#cb272a" />
|
||||
<Label id="communityRating" />
|
||||
</LayoutGroup>
|
||||
<LayoutGroup id="criticRatingGroup" layoutDirection="horiz" itemSpacings="[-5]">
|
||||
<Poster id="criticRatingIcon" height="32" width="32" />
|
||||
<Label id="criticRatingLabel" />
|
||||
</LayoutGroup>
|
||||
<Label id="ends-at" />
|
||||
<Label id="aired" />
|
||||
<LayoutGroup id="communityRatingGroup" layoutDirection="horiz" itemSpacings="[-5]">
|
||||
<Poster id="star" uri="pkg:/images/sharp_star_white_18dp.png" height="32" width="32" blendColor="#cb272a" />
|
||||
<Label id="communityRating" font="font:SmallestSystemFont" />
|
||||
</LayoutGroup>
|
||||
<Label id="genres" />
|
||||
<Label id="director" />
|
||||
<LayoutGroup layoutDirection="horiz">
|
||||
<Label id="video_codec" vertAlign="bottom" height="39" />
|
||||
<label id="video_codec_count" font="font:smallestSystemFont" vertAlign="top" color="#ceffff" />
|
||||
|
||||
<LayoutGroup id="criticRatingGroup" layoutDirection="horiz" itemSpacings="[-5]">
|
||||
<Poster id="criticRatingIcon" height="32" width="32" />
|
||||
<Label id="criticRatingLabel" font="font:SmallestSystemFont" />
|
||||
</LayoutGroup>
|
||||
<LayoutGroup layoutDirection="horiz">
|
||||
<Label id="audio_codec" vertAlign="bottom" height="39" />
|
||||
<label id="audio_codec_count" font="font:smallestSystemFont" vertAlign="top" color="#ceffff" />
|
||||
</LayoutGroup>
|
||||
<ButtonGroupHoriz id="buttons" itemSpacings="[10]" visible="false">
|
||||
<Button text="Play" id="play-button" iconUri="" focusedIconUri="" maxWidth="175" minWidth="175" />
|
||||
<Button text="Options" id="options-button" iconUri="" focusedIconUri="" maxWidth="250" minWidth="250" />
|
||||
<Button text="Watched" id="watched-button" iconUri="" focusedIconUri="" maxWidth="350" minWidth="300" />
|
||||
<Button text="Favorite" id="favorite-button" iconUri="" focusedIconUri="" maxWidth="300" minWidth="300" />
|
||||
<Button text="Edit Subtitles" id="editSubtitlesButton" iconUri="" focusedIconUri="" maxWidth="300" minWidth="300" />
|
||||
</ButtonGroupHoriz>
|
||||
<Label id="tagline" />
|
||||
<Label id="overview" wrap="true" maxLines="8" />
|
||||
|
||||
<Label id="ends-at" font="font:SmallestSystemFont" />
|
||||
<Label id="aired" font="font:SmallestSystemFont" />
|
||||
</LayoutGroup>
|
||||
|
||||
<LayoutGroup id="infoGroup" layoutDirection="horiz" horizAlignment="left" itemSpacings="[50]">
|
||||
<LayoutGroup layoutDirection="vert" itemSpacings="[30]">
|
||||
<Label id="overview" wrap="true" maxLines="8" width="1000" />
|
||||
<Label id="director" font="font:SmallestSystemFont" color="#aaaaaa" />
|
||||
|
||||
<LayoutGroup layoutDirection="vert" itemSpacings="[0]">
|
||||
<LayoutGroup layoutDirection="horiz">
|
||||
<Label id="video_codec" vertAlign="bottom" height="39" font="font:SmallestSystemFont" color="#aaaaaa" />
|
||||
<label id="video_codec_count" font="font:smallestSystemFont" vertAlign="top" color="#aaaaaa" />
|
||||
</LayoutGroup>
|
||||
<LayoutGroup layoutDirection="horiz">
|
||||
<Label id="audio_codec" vertAlign="bottom" height="39" font="font:SmallestSystemFont" color="#aaaaaa" />
|
||||
<label id="audio_codec_count" font="font:smallestSystemFont" vertAlign="top" color="#aaaaaa" />
|
||||
</LayoutGroup>
|
||||
</LayoutGroup>
|
||||
|
||||
</LayoutGroup>
|
||||
|
||||
<LayoutGroup id="buttons" layoutDirection="vert" itemSpacings="[10]">
|
||||
<TextButton id="play-button" text="Play" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/play.png" height="75" width="600" />
|
||||
<TextButton id="options-button" text="Options" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/options.png" height="75" width="600" />
|
||||
<TextButton id="trailer-button" text="Play Trailer" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/play.png" height="75" width="600" />
|
||||
<TextButton id="watched-button" text="Watched" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/check.png" height="75" width="600" />
|
||||
<TextButton id="favorite-button" text="Favorite" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/heart.png" height="75" width="600" />
|
||||
<TextButton id="editSubtitlesButton" text="Manage Subtitles" iconSide="left" fontSize="35" padding="35" icon="pkg:/images/icons/cc.png" height="75" width="600" />
|
||||
</LayoutGroup>
|
||||
</LayoutGroup>
|
||||
</LayoutGroup>
|
||||
|
||||
<MovieOptions id="movieOptions" visible="false" />
|
||||
|
|
@ -49,10 +58,12 @@
|
|||
<extrasSlider id="movieExtras" />
|
||||
</children>
|
||||
<interface>
|
||||
<field id="buttonSelected" type="string" alwaysNotify="true" />
|
||||
<field id="itemContent" type="node" />
|
||||
<field id="trailerAvailable" type="bool" onChange="trailerAvailableChanged" value="false" />
|
||||
<field id="trailerAvailable" type="bool" onChange="trailerAvailableChanged" value="true" />
|
||||
<field id="selectedAudioStreamIndex" type="integer" />
|
||||
<field id="selectedVideoStreamId" type="string" />
|
||||
<field id="quickPlayNode" type="node" alwaysNotify="true" />
|
||||
<field id="refreshMovieDetailsData" type="bool" alwaysNotify="true" />
|
||||
</interface>
|
||||
</component>
|
||||
BIN
images/icons/cc.png
Normal file
BIN
images/icons/cc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
images/icons/check.png
Normal file
BIN
images/icons/check.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 817 B |
BIN
images/icons/heart.png
Normal file
BIN
images/icons/heart.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
images/icons/options.png
Normal file
BIN
images/icons/options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4 KiB |
|
|
@ -327,13 +327,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Hide Taglines",
|
||||
"description": "Hides tagline text on details pages.",
|
||||
"settingName": "ui.details.hidetagline",
|
||||
"type": "bool",
|
||||
"default": "false"
|
||||
},
|
||||
{
|
||||
"title": "Return to Top",
|
||||
"description": "Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).",
|
||||
|
|
|
|||
|
|
@ -235,6 +235,19 @@ sub Main (args as dynamic) as void
|
|||
currentScene.callFunc("updateSeason")
|
||||
end if
|
||||
|
||||
stopLoadingSpinner()
|
||||
else if isNodeEvent(msg, "refreshMovieDetailsData")
|
||||
startLoadingSpinner()
|
||||
|
||||
currentScene = m.global.sceneManager.callFunc("getActiveScene")
|
||||
|
||||
' Refresh movie detail data
|
||||
currentScene.itemContent.json = api.users.GetItem(m.global.session.user.id, currentScene.itemContent.id)
|
||||
movieMetaData = ItemMetaData(currentScene.itemContent.id)
|
||||
|
||||
' Set updated starting point for the queue item
|
||||
m.global.queueManager.callFunc("setTopStartingPoint", currentScene.itemContent.json.UserData.PlaybackPositionTicks)
|
||||
|
||||
stopLoadingSpinner()
|
||||
else if isNodeEvent(msg, "selectedItem")
|
||||
' If you select a library from ANYWHERE, follow this flow
|
||||
|
|
@ -669,10 +682,13 @@ sub Main (args as dynamic) as void
|
|||
message_dialog("This type is not yet supported: " + node.type + ".")
|
||||
end if
|
||||
else if isNodeEvent(msg, "buttonSelected")
|
||||
|
||||
' If a button is selected, we have some determining to do
|
||||
btn = getButton(msg)
|
||||
btn = msg.getData()
|
||||
if isValid(btn) then btn = LCase(btn)
|
||||
|
||||
group = sceneManager.callFunc("getActiveScene")
|
||||
if isValid(btn) and btn.id = "play-button"
|
||||
if isValid(btn) and btn = "play-button"
|
||||
' User chose Play button from movie detail view
|
||||
startLoadingSpinner()
|
||||
' Check if a specific Audio Stream was selected
|
||||
|
|
@ -705,7 +721,7 @@ sub Main (args as dynamic) as void
|
|||
group.lastFocus.setFocus(true)
|
||||
end if
|
||||
|
||||
else if btn <> invalid and btn.id = "trailer-button"
|
||||
else if isValid(btn) and btn = "trailer-button"
|
||||
' User chose to play a trailer from the movie detail view
|
||||
startLoadingSpinner()
|
||||
dialog = createObject("roSGNode", "ProgressDialog")
|
||||
|
|
@ -726,7 +742,7 @@ sub Main (args as dynamic) as void
|
|||
if isValid(group) and isValid(group.lastFocus)
|
||||
group.lastFocus.setFocus(true)
|
||||
end if
|
||||
else if btn <> invalid and btn.id = "watched-button"
|
||||
else if isValid(btn) and btn = "watched-button"
|
||||
movie = group.itemContent
|
||||
if isValid(movie) and isValid(movie.watched) and isValid(movie.id)
|
||||
if movie.watched
|
||||
|
|
@ -736,7 +752,7 @@ sub Main (args as dynamic) as void
|
|||
end if
|
||||
movie.watched = not movie.watched
|
||||
end if
|
||||
else if btn <> invalid and btn.id = "favorite-button"
|
||||
else if isValid(btn) and btn = "favorite-button"
|
||||
movie = group.itemContent
|
||||
if movie.favorite
|
||||
UnmarkItemFavorite(movie.id)
|
||||
|
|
@ -744,7 +760,7 @@ sub Main (args as dynamic) as void
|
|||
MarkItemFavorite(movie.id)
|
||||
end if
|
||||
movie.favorite = not movie.favorite
|
||||
else if isValid(btn) and LCase(btn.id) = "editsubtitlesbutton"
|
||||
else if isValid(btn) and btn = "editsubtitlesbutton"
|
||||
subtitleSearchView = createObject("roSGNode", "SubtitleSearchView")
|
||||
subtitleSearchView.observeField("subtitleLanguageButtonSelected", m.port)
|
||||
subtitleSearchView.observeField("subtitleSearchButtonSelected", m.port)
|
||||
|
|
|
|||
|
|
@ -562,20 +562,19 @@ function CreateMovieDetailsGroup(movie as object) as dynamic
|
|||
group.observeField("quickPlayNode", m.port)
|
||||
group.overhangTitle = movie.title
|
||||
group.optionsAvailable = false
|
||||
group.trailerAvailable = false
|
||||
' push scene asap (to prevent extra button presses when retriving series/movie info)
|
||||
m.global.sceneManager.callFunc("pushScene", group)
|
||||
group.itemContent = movieMetaData
|
||||
|
||||
group.observeField("refreshMovieDetailsData", m.port)
|
||||
|
||||
' local trailers
|
||||
trailerData = api.users.GetLocalTrailers(m.global.session.user.id, movie.id)
|
||||
if isValid(trailerData)
|
||||
group.trailerAvailable = trailerData.Count() > 0
|
||||
end if
|
||||
group.trailerAvailable = isValidAndNotEmpty(trailerData)
|
||||
|
||||
' watch for button presses
|
||||
buttons = group.findNode("buttons")
|
||||
for each b in buttons.getChildren(-1, 0)
|
||||
b.observeField("buttonSelected", m.port)
|
||||
end for
|
||||
group.observeField("buttonSelected", m.port)
|
||||
|
||||
' setup and load movie extras
|
||||
extras = group.findNode("extrasGrid")
|
||||
extras.observeField("selectedItem", m.port)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ function ImageURL(id, version = "Primary", params = {})
|
|||
params.append(param)
|
||||
end if
|
||||
url = Substitute("Items/{0}/Images/{1}", id, version)
|
||||
' ?maxHeight=384&maxWidth=256&tag=<tag>&quality=90"
|
||||
return buildURL(url, params)
|
||||
end function
|
||||
|
||||
|
|
|
|||
|
|
@ -8,5 +8,7 @@ enum ColorPalette
|
|||
DARKGREY = "#101010"
|
||||
MIDGREY = "#777777"
|
||||
LIGHTGREY = "#aaaaaa"
|
||||
RED = "#FF0000"
|
||||
BLACK77 = "0x00000077"
|
||||
TRANSPARENT = "0x00000000"
|
||||
end enum
|
||||
|
|
|
|||
15
source/enums/ImageType.bs
Normal file
15
source/enums/ImageType.bs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
enum ImageType
|
||||
PRIMARY = "Primary"
|
||||
ART = "Art"
|
||||
BACKDROP = "Backdrop"
|
||||
BANNER = "Banner"
|
||||
LOGO = "Logo"
|
||||
THUMB = "Thumb"
|
||||
DISC = "Disc"
|
||||
BOX = "Box"
|
||||
SCREENSHOT = "Screenshot"
|
||||
MENU = "Menu"
|
||||
CHAPTER = "Chapter"
|
||||
BOXREAR = "BoxRear"
|
||||
PROFILE = "Profile"
|
||||
end enum
|
||||
5
source/enums/ViewLoadStatus.bs
Normal file
5
source/enums/ViewLoadStatus.bs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
enum ViewLoadStatus
|
||||
INIT
|
||||
FIRSTLOAD
|
||||
RELOAD
|
||||
end enum
|
||||
Loading…
Reference in a new issue