commit
855ad0b8a2
|
@ -1,19 +1,66 @@
|
||||||
sub init()
|
sub init()
|
||||||
m.top.observeField("buttonSelected", handle_button)
|
options = m.top.findNode("optionList")
|
||||||
|
options.focusBitmapBlendColor="0x0cb0e8"
|
||||||
|
options.color="0xffffff"
|
||||||
|
options.focusedColor="0xffffff"
|
||||||
|
options.setFocus(true)
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
function onKeyEvent(key as string, press as boolean) as boolean
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
if key = "OK"
|
if key = "back"
|
||||||
m.top.buttonSelected = m.top.buttonFocused
|
m.top.backPressed = true
|
||||||
handle_button()
|
|
||||||
return true
|
return true
|
||||||
end if
|
end if
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end function
|
end function
|
||||||
|
|
||||||
function handle_button()
|
sub updateOptions()
|
||||||
' We just toggle the close state, so subsequent touches don't do anything funny
|
for each item in m.top.options
|
||||||
m.top.close = true
|
row = CreateObject("roSGNode", "ContentNode")
|
||||||
m.top.close = false
|
row.title = item
|
||||||
end function
|
m.top.findNode("content").appendChild(row)
|
||||||
|
end for
|
||||||
|
m.top.findNode("optionList").numRows = m.top.options.count()
|
||||||
|
redraw()
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub updateMessage()
|
||||||
|
message = m.top.findNode("messageText")
|
||||||
|
message.text = m.top.message
|
||||||
|
redraw()
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub redraw()
|
||||||
|
boxWidth = 900
|
||||||
|
border = 40
|
||||||
|
itemSpacing = 40
|
||||||
|
optionHeight = 60
|
||||||
|
|
||||||
|
bg = m.top.findNode("dialogBackground")
|
||||||
|
text = m.top.findNode("messageText")
|
||||||
|
options = m.top.findNode("optionList")
|
||||||
|
fontHeight = m.top.fontHeight
|
||||||
|
fontWidth = m.top.fontWidth
|
||||||
|
|
||||||
|
if text.text.len() > 0 then
|
||||||
|
textWidth = boxWidth - ( border * 2 )
|
||||||
|
text.width = textWidth
|
||||||
|
text.numLines = int(fontWidth / textWidth) + 1
|
||||||
|
text.translation = [ border , border ]
|
||||||
|
textHeight = (fontHeight * text.numLines)
|
||||||
|
else
|
||||||
|
textHeight = 0
|
||||||
|
itemSpacing = border
|
||||||
|
end if
|
||||||
|
|
||||||
|
options.translation = [ border * 2, textHeight + itemSpacing]
|
||||||
|
options.itemSize = [ boxWidth - ( border * 4 ), optionHeight ]
|
||||||
|
options.itemSpacing = "[0,20]"
|
||||||
|
|
||||||
|
boxHeight = options.translation[1] + (options.itemSize[1] * options.numRows ) + (options.itemSpacing[1] * (options.NumRows - 1)) + border
|
||||||
|
|
||||||
|
bg.width = boxWidth
|
||||||
|
bg.height = boxHeight
|
||||||
|
|
||||||
|
m.top.translation = [(1920 - boxWidth)/2 , (1080 - boxHeight)/2]
|
||||||
|
end sub
|
||||||
|
|
|
@ -1,4 +1,24 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<component name="JFMessageDialog" extends="Dialog">
|
<component name="JFMessageDialog" extends="JFGroup">
|
||||||
|
<children>
|
||||||
|
<Poster
|
||||||
|
id="dialogBackground"
|
||||||
|
uri="pkg:/images/dialog.9.png"
|
||||||
|
blendColor="#000000"
|
||||||
|
translation="[0, 0]"
|
||||||
|
/>
|
||||||
|
<Label id="messageText" horizAlign="center" wrap="true" />
|
||||||
|
<LabelList id="optionList" vertFocusAnimationStyle="floatingFocus" textHorizAlign="center">
|
||||||
|
<ContentNode id = "content" role = "content"></ContentNode>
|
||||||
|
</LabelList>
|
||||||
|
|
||||||
|
</children>
|
||||||
|
<interface>
|
||||||
|
<field id="id" type="string" />
|
||||||
|
<field id="message" type="string" onChange="updateMessage" />
|
||||||
|
<field id="options" type="array" onChange="updateOptions" />
|
||||||
|
<field id="fontHeight" type="integer" />
|
||||||
|
<field id="fontWidth" type="integer" />
|
||||||
|
</interface>
|
||||||
<script type="text/brightscript" uri="JFMessageDialog.brs" />
|
<script type="text/brightscript" uri="JFMessageDialog.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
BIN
images/dialog.9.png
Normal file
BIN
images/dialog.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
|
@ -78,7 +78,6 @@ sub Main()
|
||||||
group.lastFocus = group.focusedChild
|
group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
m.overhang.title = node.name
|
m.overhang.title = node.name
|
||||||
group = CreateMovieListGroup(node)
|
group = CreateMovieListGroup(node)
|
||||||
group.overhangTitle = node.name
|
group.overhangTitle = node.name
|
||||||
|
@ -103,7 +102,7 @@ sub Main()
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else
|
else
|
||||||
' TODO - switch on more node types
|
' TODO - switch on more node types
|
||||||
message_dialog("This library type is not yet implemented: " + node.type)
|
message_dialog("This library type is not yet implemented: " + node.type + ".")
|
||||||
end if
|
end if
|
||||||
else if isNodeEvent(msg, "collectionSelected")
|
else if isNodeEvent(msg, "collectionSelected")
|
||||||
node = getMsgPicker(msg, "picker")
|
node = getMsgPicker(msg, "picker")
|
||||||
|
@ -160,18 +159,19 @@ sub Main()
|
||||||
else if isNodeEvent(msg, "episodeSelected")
|
else if isNodeEvent(msg, "episodeSelected")
|
||||||
' If you select a TV Episode from ANYWHERE, follow this flow
|
' If you select a TV Episode from ANYWHERE, follow this flow
|
||||||
node = getMsgPicker(msg, "picker")
|
node = getMsgPicker(msg, "picker")
|
||||||
|
|
||||||
group.lastFocus = group.focusedChild
|
|
||||||
group.setFocus(false)
|
|
||||||
group.visible = false
|
|
||||||
video_id = node.id
|
video_id = node.id
|
||||||
|
video = CreateVideoPlayerGroup(video_id)
|
||||||
group = CreateVideoPlayerGroup(video_id)
|
if video <> invalid then
|
||||||
m.scene.appendChild(group)
|
group.lastFocus = group.focusedChild
|
||||||
group.setFocus(true)
|
group.setFocus(false)
|
||||||
group.control = "play"
|
group.visible = false
|
||||||
ReportPlayback(group, "start")
|
group = video
|
||||||
m.overhang.visible = false
|
m.scene.appendChild(group)
|
||||||
|
group.setFocus(true)
|
||||||
|
group.control = "play"
|
||||||
|
ReportPlayback(group, "start")
|
||||||
|
m.overhang.visible = false
|
||||||
|
end if
|
||||||
else if isNodeEvent(msg, "search_value")
|
else if isNodeEvent(msg, "search_value")
|
||||||
query = msg.getRoSGNode().search_value
|
query = msg.getRoSGNode().search_value
|
||||||
group.findNode("SearchBox").visible = false
|
group.findNode("SearchBox").visible = false
|
||||||
|
@ -214,17 +214,19 @@ sub Main()
|
||||||
if btn.id = "play-button"
|
if btn.id = "play-button"
|
||||||
' TODO - Do a better job of picking the last focus
|
' TODO - Do a better job of picking the last focus
|
||||||
' This is currently page layout Group, button Group, then button
|
' This is currently page layout Group, button Group, then button
|
||||||
group.lastFocus = group.focusedChild.focusedChild.focusedChild
|
|
||||||
group.setFocus(false)
|
|
||||||
group.visible = false
|
|
||||||
video_id = group.id
|
video_id = group.id
|
||||||
|
video = CreateVideoPlayerGroup(video_id)
|
||||||
group = CreateVideoPlayerGroup(video_id)
|
if video <> invalid then
|
||||||
m.scene.appendChild(group)
|
group.lastFocus = group.focusedChild.focusedChild.focusedChild
|
||||||
group.setFocus(true)
|
group.setFocus(false)
|
||||||
group.control = "play"
|
group.visible = false
|
||||||
ReportPlayback(group, "start")
|
group = video
|
||||||
m.overhang.visible = false
|
m.scene.appendChild(group)
|
||||||
|
group.setFocus(true)
|
||||||
|
group.control = "play"
|
||||||
|
ReportPlayback(group, "start")
|
||||||
|
m.overhang.visible = false
|
||||||
|
end if
|
||||||
else if btn.id = "watched-button"
|
else if btn.id = "watched-button"
|
||||||
movie = group.itemContent
|
movie = group.itemContent
|
||||||
if movie.watched
|
if movie.watched
|
||||||
|
|
|
@ -335,6 +335,7 @@ end function
|
||||||
function CreateVideoPlayerGroup(video_id)
|
function CreateVideoPlayerGroup(video_id)
|
||||||
' Video is Playing
|
' Video is Playing
|
||||||
video = VideoPlayer(video_id)
|
video = VideoPlayer(video_id)
|
||||||
|
if video = invalid return invalid
|
||||||
timer = video.findNode("playbackTimer")
|
timer = video.findNode("playbackTimer")
|
||||||
|
|
||||||
video.observeField("backPressed", m.port)
|
video.observeField("backPressed", m.port)
|
||||||
|
@ -358,7 +359,6 @@ function MovieLister(group, page_size)
|
||||||
})
|
})
|
||||||
group.objects = item_list
|
group.objects = item_list
|
||||||
|
|
||||||
|
|
||||||
p = group.findNode("paginator")
|
p = group.findNode("paginator")
|
||||||
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
|
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
|
||||||
end function
|
end function
|
||||||
|
|
|
@ -3,7 +3,9 @@ function VideoPlayer(id)
|
||||||
video = CreateObject("roSGNode", "JFVideo")
|
video = CreateObject("roSGNode", "JFVideo")
|
||||||
video.id = id
|
video.id = id
|
||||||
video = VideoContent(video)
|
video = VideoContent(video)
|
||||||
|
if video = invalid
|
||||||
|
return invalid
|
||||||
|
end if
|
||||||
jellyfin_blue = "#00a4dcFF"
|
jellyfin_blue = "#00a4dcFF"
|
||||||
|
|
||||||
video.retrievingBar.filledBarBlendColor = jellyfin_blue
|
video.retrievingBar.filledBarBlendColor = jellyfin_blue
|
||||||
|
@ -23,9 +25,18 @@ function VideoContent(video) as object
|
||||||
|
|
||||||
' If there is a last playback positon, ask user if they want to resume
|
' If there is a last playback positon, ask user if they want to resume
|
||||||
position = meta.json.UserData.PlaybackPositionTicks
|
position = meta.json.UserData.PlaybackPositionTicks
|
||||||
if position > 0 and startPlaybackOver(position) then
|
if position > 0 then
|
||||||
position = 0
|
dialogResult = startPlaybackOver(position)
|
||||||
|
'Dialog returns -1 when back pressed, 0 for resume, and 1 for start over
|
||||||
|
if dialogResult = -1 then
|
||||||
|
'User pressed back, return invalid and don't load video
|
||||||
|
return invalid
|
||||||
|
else if dialogResult = 1 then
|
||||||
|
'Start Over selected, change position to 0
|
||||||
|
position = 0
|
||||||
|
end if
|
||||||
end if
|
end if
|
||||||
|
print "dialogResult: " dialogResult
|
||||||
video.content.BookmarkPosition = int(position/10000000)
|
video.content.BookmarkPosition = int(position/10000000)
|
||||||
|
|
||||||
video.PlaySessionId = ItemGetSession(video.id, position)
|
video.PlaySessionId = ItemGetSession(video.id, position)
|
||||||
|
@ -108,8 +119,8 @@ function getCaptionMode() as string
|
||||||
end function
|
end function
|
||||||
|
|
||||||
'Opens dialog asking user if they want to resume video or start playback over
|
'Opens dialog asking user if they want to resume video or start playback over
|
||||||
function startPlayBackOver(time as LongInteger) as boolean
|
function startPlayBackOver(time as LongInteger) as integer
|
||||||
return option_dialog([ "Resume playing at " + ticksToHuman(time) + ".", "Start over from the begining." ])
|
return option_dialog([ "Resume playing at " + ticksToHuman(time) + ".", "Start over from the beginning." ])
|
||||||
end function
|
end function
|
||||||
|
|
||||||
function directPlaySupported(meta as object) as boolean
|
function directPlaySupported(meta as object) as boolean
|
||||||
|
|
|
@ -57,26 +57,65 @@ function div_ceiling(a as integer, b as integer) as integer
|
||||||
return a/b + 1
|
return a/b + 1
|
||||||
end function
|
end function
|
||||||
|
|
||||||
function message_dialog(message = "" as string)
|
'Returns the item selected or -1 on backpress or other unhandled closure of dialog.
|
||||||
' Takes a string and returns an object for dialog popup
|
function get_dialog_result(dialog, port)
|
||||||
dialog = createObject("roSGNode", "JFMessageDialog")
|
while dialog <> invalid
|
||||||
dialog.id = "popup"
|
msg = wait(0, port)
|
||||||
dialog.buttons = ["OK"]
|
if isNodeEvent(msg, "backPressed") then
|
||||||
dialog.message = message
|
return -1
|
||||||
|
elseif isNodeEvent(msg, "itemSelected")
|
||||||
m.scene.dialog = dialog
|
return dialog.findNode("optionList").itemSelected
|
||||||
m.scene.dialog.setFocus(true)
|
end if
|
||||||
end function
|
|
||||||
|
|
||||||
function option_dialog(options) as integer
|
|
||||||
dialog = CreateObject("roSGNode", "JFMessageDialog")
|
|
||||||
dialog.backExitsDialog = false
|
|
||||||
dialog.buttons = options
|
|
||||||
m.scene.dialog = dialog
|
|
||||||
m.scene.dialog.setFocus(true)
|
|
||||||
|
|
||||||
while m.scene.dialog <> invalid
|
|
||||||
end while
|
end while
|
||||||
|
'Dialog has closed outside of this loop, return -1 for failure
|
||||||
return dialog.buttonSelected
|
return -1
|
||||||
|
end function
|
||||||
|
|
||||||
|
function lastFocusedChild(obj as object) as object
|
||||||
|
child = obj
|
||||||
|
for i = 0 to obj.getChildCount()
|
||||||
|
child = child.focusedChild
|
||||||
|
end for
|
||||||
|
return child
|
||||||
|
end function
|
||||||
|
|
||||||
|
function show_dialog(message as string, options = []) as integer
|
||||||
|
group = m.scene.focusedChild
|
||||||
|
lastFocus = lastFocusedChild(m.scene)
|
||||||
|
'We want to handle backPressed instead of the main loop
|
||||||
|
m.scene.unobserveField("backPressed")
|
||||||
|
|
||||||
|
dialog = createObject("roSGNode", "JFMessageDialog")
|
||||||
|
if options.count() then dialog.options = options
|
||||||
|
if message.len() > 0 then
|
||||||
|
reg = CreateObject("roFontRegistry")
|
||||||
|
font = reg.GetDefaultFont()
|
||||||
|
dialog.fontHeight = font.GetOneLineHeight()
|
||||||
|
dialog.fontWidth = font.GetOneLineWidth(message, 999999999)
|
||||||
|
dialog.message = message
|
||||||
|
end if
|
||||||
|
|
||||||
|
dialog.visible = true
|
||||||
|
dialog.setFocus(true)
|
||||||
|
m.scene.appendChild(dialog)
|
||||||
|
|
||||||
|
port = CreateObject("roMessagePort")
|
||||||
|
dialog.observeField("backPressed", port)
|
||||||
|
dialog.findNode("optionList").observeField("itemSelected", port)
|
||||||
|
|
||||||
|
result = get_dialog_result(dialog, port)
|
||||||
|
|
||||||
|
m.scene.removeChildIndex(m.scene.getChildCount() - 1)
|
||||||
|
lastFocus.setFocus(true)
|
||||||
|
m.scene.observeField("backPressed", m.port)
|
||||||
|
|
||||||
|
return result
|
||||||
|
end function
|
||||||
|
|
||||||
|
function message_dialog(message = "" as string)
|
||||||
|
return show_dialog(message,["OK"])
|
||||||
|
end function
|
||||||
|
|
||||||
|
function option_dialog(options, message = "") as integer
|
||||||
|
return show_dialog(message, options)
|
||||||
end function
|
end function
|
||||||
|
|
Loading…
Reference in New Issue
Block a user