Finished with initial flow

This commit is contained in:
Bronley 2021-07-09 06:21:24 -04:00
parent 44bf6d2b12
commit ebd49cefb3
7 changed files with 89 additions and 50 deletions

21
components/JFButton.brs Normal file
View File

@ -0,0 +1,21 @@
sub init()
m.top.observeFieldScoped("text", "onTextChanged")
m.top.iconUri = ""
m.top.focusedIconUri = ""
m.top.showFocusFootprint = true
m.top.minWidth = 0
end sub
sub onTextChanged()
addSpaceAfter = true
minChars = m.top.minChars
if minChars = invalid then minChars = 50
while m.top.text.Len() < minChars
if addSpaceAfter then
m.top.text = m.top.text + Chr(160)
else
m.top.text = Chr(160) + m.top.text
end if
addSpaceAfter = addSpaceAfter = false
end while
end sub

7
components/JFButton.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="JFButton" extends="Button">
<interface>
<field id="minChars" type="int" />
</interface>
<script type="text/brightscript" uri="JFButton.brs" />
</component>

View File

@ -4,15 +4,13 @@ sub init()
m.spinner = m.top.findNode("spinner") m.spinner = m.top.findNode("spinner")
m.serverPicker = m.top.findNode("serverPicker") m.serverPicker = m.top.findNode("serverPicker")
m.serverUrl = m.top.findNode("serverUrl") m.serverUrlTextbox = m.top.findNode("serverUrlTextbox")
m.serverUrlContainer = m.top.findNode("serverUrlContainer") m.serverUrlContainer = m.top.findNode("serverUrlContainer")
m.serverUrlOutline = m.top.findNode("serverUrlOutline") m.serverUrlOutline = m.top.findNode("serverUrlOutline")
m.submit = m.top.findNode("submit") m.submit = m.top.findNode("submit")
m.serverUrl.focusable = true
m.serverPicker.setFocus(true) m.serverPicker.setFocus(true)
ScanForServers() ScanForServers()
m.serverPicker.ObserveField("itemSelected", "onclick")
end sub end sub
@ -22,8 +20,11 @@ function onKeyEvent(key as string, press as boolean) as boolean
if not press then return true if not press then return true
handled = true handled = true
'if the user pressed the down key and we are already at the last child of server picker, then change focus to the url textbox if key = "OK" and m.serverPicker.hasFocus() then
if key = "down" and m.serverPicker.hasFocus() and m.serverPicker.itemFocused = m.serverPicker.content.getChildCount() - 1 m.top.serverUrl = m.serverPicker.content.getChild(m.serverPicker.itemFocused).baseUrl
m.submit.setFocus(true)
'if the user pressed the down key and we are already at the last child of server picker, then change focus to the url textbox
else if key = "down" and m.serverPicker.hasFocus() and m.serverPicker.itemFocused = m.serverPicker.content.getChildCount() - 1
m.serverUrlContainer.setFocus(true) m.serverUrlContainer.setFocus(true)
else if key = "up" and m.serverUrlContainer.hasFocus() else if key = "up" and m.serverUrlContainer.hasFocus()
m.serverPicker.setFocus(true) m.serverPicker.setFocus(true)
@ -51,15 +52,11 @@ function ScanForServers()
end function end function
sub ScanForServersComplete(event) sub ScanForServersComplete(event)
' m.scanOrManual.visible = false
' m.serverPicker.visible = true
' m.serverPicker.SetFocus(true)
servers = event.getData() servers = event.getData()
servers = [servers[0], servers[0]]
items = CreateObject("roSGNode", "ContentNode") items = CreateObject("roSGNode", "ContentNode")
for each server in servers for each server in servers
server.subtype = "ContentNode" server.subtype = "ContentNode"
'add new fields for every server property onto the ContentNode (rather than making a dedicated component just to hold data...)
items.update([server], true) items.update([server], true)
end for end for
m.serverPicker.content = items m.serverPicker.content = items
@ -70,7 +67,7 @@ function ShowKeyboard()
dialog = createObject("roSGNode", "KeyboardDialog") dialog = createObject("roSGNode", "KeyboardDialog")
dialog.title = "Enter the server name or ip address" dialog.title = "Enter the server name or ip address"
dialog.buttons = [tr("OK"), tr("Cancel")] dialog.buttons = [tr("OK"), tr("Cancel")]
dialog.text = m.serverUrl.text dialog.text = m.serverUrlTextbox.text
m.top.getscene().dialog = dialog m.top.getscene().dialog = dialog
m.dialog = dialog m.dialog = dialog
@ -83,7 +80,7 @@ function onDialogButton()
button_text = d.buttons[d.buttonSelected] button_text = d.buttons[d.buttonSelected]
if button_text = tr("OK") if button_text = tr("OK")
m.serverUrl.text = d.text m.serverUrlTextbox.text = d.text
m.dialog.close = true m.dialog.close = true
return true return true
else if button_text = tr("Cancel") else if button_text = tr("Cancel")

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<component name="SetServerScreen" extends="JFGroup"> <component name="SetServerScreen" extends="JFGroup">
<interface> <interface>
<field id="serverUrl" type="string" /> <field id="serverUrl" type="string" alias="serverUrlTextbox.text" />
<field id="serverWidth" alias="serverUrlOutline.width,serverUrl.width,serverUrlContainer.width" value="1570" /> <field id="serverWidth" alias="serverUrlOutline.width,serverUrlTextbox.width,serverUrlContainer.width" value="1570" />
<field id="serverHeight" alias="serverUrlOutline.height,serverUrl.height,serverUrlContainer.height" value="60" /> <field id="serverHeight" alias="serverUrlOutline.height,serverUrlTextbox.height,serverUrlContainer.height" value="60" />
</interface> </interface>
<children> <children>
@ -17,23 +17,24 @@
<MarkupList id="serverPicker" translation="[50, 20]" itemComponentName="JFServer" itemSpacing="[0, 10]" itemSize="[1590, 100]" numRows="3" vertFocusAnimationStyle="fixedFocus" /> <MarkupList id="serverPicker" translation="[50, 20]" itemComponentName="JFServer" itemSpacing="[0, 10]" itemSize="[1590, 100]" numRows="3" vertFocusAnimationStyle="fixedFocus" />
</Rectangle> </Rectangle>
<label text="...or enter server information manually" translation="[0, 670]" /> <label text="...or enter server URL manually" translation="[0, 690]" />
<Rectangle color="0x00000020" width="1690" height="400" translation="[0, 730]"> <Group width="1690" height="140" translation="[0, 730]">
<LayoutGroup layoutDirection="horiz" vertAlignment="center" translation="[10, 70]">
<LayoutGroup layoutDirection="horiz" vertAlignment="center" translation="[10, 50]">
<Label text="URL: " font="font:MediumSystemFont" translation="[0, 25]" /> <Label text="URL: " font="font:MediumSystemFont" translation="[0, 25]" />
<Rectangle id="serverUrlContainer" color="0x00000000"> <Rectangle id="serverUrlContainer" color="0x00000000">
<TextEditBox id="serverUrl" hintText="e.g. 192.168.1.100:8096 or https://example.com/jellyfin"></TextEditBox> <TextEditBox id="serverUrlTextbox" hintText="e.g. 192.168.1.100:8096 or https://example.com/jellyfin"></TextEditBox>
<Poster id="serverUrlOutline" visible="false" uri="pkg:/images/hd_focus.9.png" /> <Poster id="serverUrlOutline" visible="false" uri="pkg:/images/hd_focus.9.png" />
</Rectangle> </Rectangle>
</LayoutGroup> </LayoutGroup>
</Group>
<Button id="submit" text="Submit" translation="[10, 100]" focusable="true" showFocusFootprint="false" iconUri="" focusedIconUri=""></Button>
</Rectangle>
<label text="" id="alert" font="font:MediumSystemFont" translation="[0, 555]" /> <label text="" id="alert" font="font:MediumSystemFont" translation="[0, 555]" />
</Group> </Group>
<LayoutGroup layoutDirection="vert" horizAlignment="center" vertAlignment="top" translation="[960, 930]">
<JFButton id="submit" minChars="30" text="Submit" translation="[120, 930]"></JFButton>
<!--add a known width invisibile element to allow the button to be centered-->
<Rectangle width="1920" height="12" color="#00000000" />
</LayoutGroup>
</children> </children>
<script type="text/brightscript" uri="SetServerScreen.brs" /> <script type="text/brightscript" uri="SetServerScreen.brs" />

View File

@ -21,7 +21,7 @@ sub Main()
m.overhang = CreateObject("roSGNode", "JFOverhang") m.overhang = CreateObject("roSGNode", "JFOverhang")
m.scene.insertChild(m.overhang, 0) m.scene.insertChild(m.overhang, 0)
m.page_size = 48 m.page_size = 48
app_start: app_start:
@ -116,7 +116,7 @@ sub Main()
group = CreateItemGrid(selectedItem) group = CreateItemGrid(selectedItem)
group.overhangTitle = selectedItem.title group.overhangTitle = selectedItem.title
m.scene.appendChild(group) m.scene.appendChild(group)
else if selectedItem.type = "Folder" else if selectedItem.type = "Folder"
group.lastFocus = group.focusedChild group.lastFocus = group.focusedChild
group.setFocus(false) group.setFocus(false)
group.visible = false group.visible = false
@ -187,7 +187,7 @@ sub Main()
group.control = "play" group.control = "play"
ReportPlayback(group, "start") ReportPlayback(group, "start")
m.overhang.visible = false m.overhang.visible = false
else else
dialog = createObject("roSGNode", "Dialog") dialog = createObject("roSGNode", "Dialog")
dialog.title = tr("Error loading Channel Data") dialog.title = tr("Error loading Channel Data")
dialog.message = tr("Unable to load Channel Data from the server") dialog.message = tr("Unable to load Channel Data from the server")
@ -438,7 +438,7 @@ function LoginFlow(startOver = false as boolean)
end if end if
'Collect Jellyfin server and user information 'Collect Jellyfin server and user information
start_login: start_login:
if get_setting("server") = invalid or ServerInfo() = invalid or startOver = true then if invalid = invalid or get_setting("server") = invalid or ServerInfo() = invalid or startOver = true then
print "Get server details" print "Get server details"
SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting
serverSelection = CreateServerGroup() serverSelection = CreateServerGroup()
@ -573,4 +573,4 @@ sub SendPerformanceBeacon(signalName as string)
if m.global.app_loaded = false then if m.global.app_loaded = false then
m.scene.signalBeacon(signalName) m.scene.signalBeacon(signalName)
end if end if
end sub end sub

View File

@ -10,11 +10,11 @@ function CreateServerGroup()
m.viewModel = {} m.viewModel = {}
button = screen.findNode("submit") button = screen.findNode("submit")
button.observeField("buttonSelected", port) button.observeField("buttonSelected", port)
server_hostname = screen.serverUrl
screen.observeField("backPressed", port) screen.observeField("backPressed", port)
while(true) while(true)
msg = wait(0, port) msg = wait(0, port)
print type(msg), msg
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
return "false" return "false"
else if isNodeEvent(msg, "backPressed") else if isNodeEvent(msg, "backPressed")
@ -22,27 +22,13 @@ function CreateServerGroup()
else if type(msg) = "roSGNodeEvent" else if type(msg) = "roSGNodeEvent"
node = msg.getNode() node = msg.getNode()
if node = "submit" if node = "submit"
'Append default ports serverUrl = standardize_jellyfin_url(screen.serverUrl)
maxSlashes = 0
if left(server_hostname.value, 8) = "https://" or left(server_hostname.value, 7) = "http://" then maxSlashes = 2
'Check to make sure entry has no extra slashes before adding default ports.
if Instr(0, server_hostname.value, "/") = maxSlashes then
if server_hostname.value.len() > 5 and mid(server_hostname.value, server_hostname.value.len() - 4, 1) <> ":" and mid(server_hostname.value, server_hostname.value.len() - 5, 1) <> ":" then
if left(server_hostname.value, 5) = "https" then
server_hostname.value = server_hostname.value + ":8920"
else
server_hostname.value = server_hostname.value + ":8096"
end if
end if
end if
'Append http:// to server
if left(server_hostname.value, 4) <> "http" then server_hostname.value = "http://" + server_hostname.value
'If this is a different server from what we know, reset username/password setting 'If this is a different server from what we know, reset username/password setting
if get_setting("server") <> server_hostname.value then if get_setting("server") <> serverUrl then
set_setting("username", "") set_setting("username", "")
set_setting("password", "") set_setting("password", "")
end if end if
set_setting("server", server_hostname.value) set_setting("server", serverUrl)
if ServerInfo() = invalid then if ServerInfo() = invalid then
' Maybe don't unset setting, but offer as a prompt ' Maybe don't unset setting, but offer as a prompt
' Server not found, is it online? New values / Retry ' Server not found, is it online? New values / Retry

View File

@ -83,7 +83,7 @@ function get_dialog_result(dialog, port)
if isNodeEvent(msg, "backPressed") then if isNodeEvent(msg, "backPressed") then
return -1 return -1
elseif isNodeEvent(msg, "itemSelected") elseif isNodeEvent(msg, "itemSelected")
return dialog.findNode("optionList").itemSelected return dialog.findNode("optionList").itemSelected
end if end if
end while end while
'Dialog has closed outside of this loop, return -1 for failure 'Dialog has closed outside of this loop, return -1 for failure
@ -95,8 +95,8 @@ function lastFocusedChild(obj as object) as object
for i = 0 to obj.getChildCount() for i = 0 to obj.getChildCount()
if obj.focusedChild <> invalid then if obj.focusedChild <> invalid then
child = child.focusedChild child = child.focusedChild
end if end if
end for end for
return child return child
end function end function
@ -144,3 +144,30 @@ end function
function option_dialog(options, message = "", defaultSelection = 0) as integer function option_dialog(options, message = "", defaultSelection = 0) as integer
return show_dialog(message, options, defaultSelection) return show_dialog(message, options, defaultSelection)
end function end function
'
' Take a jellyfin hostname and ensure it's a full url.
' prepend http or https and append default ports, and remove excess slashes
'
function standardize_jellyfin_url(url as string)
'Append default ports
maxSlashes = 0
if left(url, 8) = "https://" or left(url, 7) = "http://" then
maxSlashes = 2
end if
'Check to make sure entry has no extra slashes before adding default ports.
if Instr(0, url, "/") = maxSlashes then
if url.len() > 5 and mid(url, url.len() - 4, 1) <> ":" and mid(url, url.len() - 5, 1) <> ":" then
if left(url, 5) = "https" then
url = url + ":8920"
else
url = url + ":8096"
end if
end if
end if
'Append http:// to server
if left(url, 4) <> "http" then
url = "http://" + url
end if
return url
end function