Merge pull request #140 from thomabx/master

Redesigned JFMessageDialog
This commit is contained in:
Charles Ewert 2020-03-03 23:33:11 -05:00 committed by GitHub
commit 855ad0b8a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 180 additions and 61 deletions

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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