Add ui components and focus handling
This commit is contained in:
parent
c303250ffa
commit
44bf6d2b12
35
components/config/JFServer.brs
Normal file
35
components/config/JFServer.brs
Normal file
|
@ -0,0 +1,35 @@
|
|||
function init() as void
|
||||
m.poster = m.top.findNode("poster")
|
||||
m.name = m.top.findNode("name")
|
||||
m.baseUrl = m.top.findNode("baseUrl")
|
||||
m.labels = m.top.findNode("labels")
|
||||
setTextColor(0)
|
||||
end function
|
||||
|
||||
function itemContentChanged() as void
|
||||
server = m.top.itemContent
|
||||
|
||||
m.poster.uri = server.iconUrl
|
||||
m.name.text = server.name
|
||||
m.baseUrl.text = server.baseUrl
|
||||
end function
|
||||
|
||||
function onFocusPercentChange(event)
|
||||
'print "focusPercentChange: " ; event.getData()
|
||||
setTextColor(event.getData())
|
||||
end function
|
||||
|
||||
function setTextColor(percentFocused)
|
||||
white = "0xffffffff"
|
||||
black = "0x00000099"
|
||||
if percentFocused > .4 then
|
||||
color = black
|
||||
else
|
||||
color = white
|
||||
end if
|
||||
|
||||
children = m.labels.getChildren(-1, 0)
|
||||
for each child in children
|
||||
child.color = color
|
||||
end for
|
||||
end function
|
22
components/config/JFServer.xml
Normal file
22
components/config/JFServer.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<component name="JFServer" extends="Group">
|
||||
|
||||
<interface>
|
||||
<field id="itemContent" type="node" onchange="itemContentChanged" />
|
||||
<field id="focusPercent" type="float" onchange="onFocusPercentChange" />
|
||||
</interface>
|
||||
|
||||
<script type="text/brightscript" uri="JFServer.brs" />
|
||||
|
||||
<children>
|
||||
<Poster id="poster" translation="[0,5]" width="90" height="90" />
|
||||
<Group id="labels" translation="[100,0]">
|
||||
<Label text="Name:" horizAlign="left" font="font:MediumBoldSystemFont" width="130" height="65" translation="[0,5]" />
|
||||
<Label text="URL:" horizAlign="left" font="font:MediumBoldSystemFont" width="130" height="65" translation="[0,55]" />
|
||||
|
||||
<Label id="name" horizAlign="left" font="font:MediumSystemFont" height="65" translation="[125,5]" />
|
||||
<Label id="baseUrl" horizAlign="left" font="font:MediumSystemFont" height="65" translation="[125,55]" />
|
||||
</Group>
|
||||
</children>
|
||||
|
||||
</component>
|
93
components/config/SetServerScreen.brs
Normal file
93
components/config/SetServerScreen.brs
Normal file
|
@ -0,0 +1,93 @@
|
|||
sub init()
|
||||
m.top.setFocus(true)
|
||||
m.top.optionsAvailable = false
|
||||
|
||||
m.spinner = m.top.findNode("spinner")
|
||||
m.serverPicker = m.top.findNode("serverPicker")
|
||||
m.serverUrl = m.top.findNode("serverUrl")
|
||||
m.serverUrlContainer = m.top.findNode("serverUrlContainer")
|
||||
m.serverUrlOutline = m.top.findNode("serverUrlOutline")
|
||||
m.submit = m.top.findNode("submit")
|
||||
|
||||
m.serverUrl.focusable = true
|
||||
m.serverPicker.setFocus(true)
|
||||
ScanForServers()
|
||||
m.serverPicker.ObserveField("itemSelected", "onclick")
|
||||
|
||||
end sub
|
||||
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
print "onKeyEvent", key, press
|
||||
|
||||
if not press then return 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 = "down" and m.serverPicker.hasFocus() and m.serverPicker.itemFocused = m.serverPicker.content.getChildCount() - 1
|
||||
m.serverUrlContainer.setFocus(true)
|
||||
else if key = "up" and m.serverUrlContainer.hasFocus()
|
||||
m.serverPicker.setFocus(true)
|
||||
else if key = "OK" and m.serverUrlContainer.hasFocus()
|
||||
ShowKeyboard()
|
||||
'focus the serverUrl input from submit button
|
||||
else if key = "up" and m.submit.hasFocus()
|
||||
m.serverUrlContainer.setFocus(true)
|
||||
'focus the submit button from serverUrl
|
||||
else if key = "down" and m.serverUrlContainer.hasFocus()
|
||||
m.submit.setFocus(true)
|
||||
else
|
||||
handled = false
|
||||
end if
|
||||
'show/hide input box outline
|
||||
m.serverUrlOutline.visible = m.serverUrlContainer.isInFocusChain()
|
||||
return handled
|
||||
end function
|
||||
|
||||
function ScanForServers()
|
||||
m.ssdpScanner = CreateObject("roSGNode", "SSDPTask")
|
||||
'run the task
|
||||
m.ssdpScanner.observeField("content", "ScanForServersComplete")
|
||||
m.ssdpScanner.control = "RUN"
|
||||
end function
|
||||
|
||||
sub ScanForServersComplete(event)
|
||||
' m.scanOrManual.visible = false
|
||||
|
||||
' m.serverPicker.visible = true
|
||||
' m.serverPicker.SetFocus(true)
|
||||
servers = event.getData()
|
||||
servers = [servers[0], servers[0]]
|
||||
items = CreateObject("roSGNode", "ContentNode")
|
||||
for each server in servers
|
||||
server.subtype = "ContentNode"
|
||||
items.update([server], true)
|
||||
end for
|
||||
m.serverPicker.content = items
|
||||
m.spinner.visible = false
|
||||
end sub
|
||||
|
||||
function ShowKeyboard()
|
||||
dialog = createObject("roSGNode", "KeyboardDialog")
|
||||
dialog.title = "Enter the server name or ip address"
|
||||
dialog.buttons = [tr("OK"), tr("Cancel")]
|
||||
dialog.text = m.serverUrl.text
|
||||
|
||||
m.top.getscene().dialog = dialog
|
||||
m.dialog = dialog
|
||||
|
||||
dialog.observeField("buttonSelected", "onDialogButton")
|
||||
end function
|
||||
|
||||
function onDialogButton()
|
||||
d = m.dialog
|
||||
button_text = d.buttons[d.buttonSelected]
|
||||
|
||||
if button_text = tr("OK")
|
||||
m.serverUrl.text = d.text
|
||||
m.dialog.close = true
|
||||
return true
|
||||
else if button_text = tr("Cancel")
|
||||
m.dialog.close = true
|
||||
return true
|
||||
end if
|
||||
end function
|
41
components/config/SetServerScreen.xml
Normal file
41
components/config/SetServerScreen.xml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<component name="SetServerScreen" extends="JFGroup">
|
||||
<interface>
|
||||
<field id="serverUrl" type="string" />
|
||||
<field id="serverWidth" alias="serverUrlOutline.width,serverUrl.width,serverUrlContainer.width" value="1570" />
|
||||
<field id="serverHeight" alias="serverUrlOutline.height,serverUrl.height,serverUrlContainer.height" value="60" />
|
||||
</interface>
|
||||
|
||||
<children>
|
||||
<Group translation="[150,0]">
|
||||
<label text="Connect to Server" id="prompt" font="font:LargeBoldSystemFont" translation="[0, 150]" />
|
||||
|
||||
<label text="Pick a Jellyfin server from the local network" translation="[0, 200]" />
|
||||
<!--background for server picker-->
|
||||
<Rectangle color="0x00000020" width="1690" height="400" translation="[0, 250]">
|
||||
<Spinner id="spinner" translation="[717, 136]" />
|
||||
<MarkupList id="serverPicker" translation="[50, 20]" itemComponentName="JFServer" itemSpacing="[0, 10]" itemSize="[1590, 100]" numRows="3" vertFocusAnimationStyle="fixedFocus" />
|
||||
</Rectangle>
|
||||
|
||||
<label text="...or enter server information manually" translation="[0, 670]" />
|
||||
|
||||
<Rectangle color="0x00000020" width="1690" height="400" translation="[0, 730]">
|
||||
|
||||
<LayoutGroup layoutDirection="horiz" vertAlignment="center" translation="[10, 50]">
|
||||
<Label text="URL: " font="font:MediumSystemFont" translation="[0, 25]" />
|
||||
<Rectangle id="serverUrlContainer" color="0x00000000">
|
||||
<TextEditBox id="serverUrl" 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" />
|
||||
</Rectangle>
|
||||
</LayoutGroup>
|
||||
|
||||
<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]" />
|
||||
</Group>
|
||||
</children>
|
||||
|
||||
<script type="text/brightscript" uri="SetServerScreen.brs" />
|
||||
|
||||
</component>
|
BIN
images/fhd_focus.9.png
Normal file
BIN
images/fhd_focus.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 885 B |
BIN
images/hd_focus.9.png
Normal file
BIN
images/hd_focus.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
|
@ -1,27 +1,17 @@
|
|||
function CreateServerGroup()
|
||||
' Get and Save Jellyfin Server Information
|
||||
group = CreateObject("roSGNode", "ConfigScene")
|
||||
m.scene.appendChild(group)
|
||||
port = CreateObject("roMessagePort")
|
||||
group.findNode("prompt").text = tr("Connect to Server")
|
||||
screen = CreateObject("roSGNode", "SetServerScreen")
|
||||
m.scene.appendChild(screen)
|
||||
port = CreateObject("roMessagePort")
|
||||
m.colors = {}
|
||||
|
||||
|
||||
config = group.findNode("configOptions")
|
||||
server_field = CreateObject("roSGNode", "ConfigData")
|
||||
server_field.label = tr("Server")
|
||||
server_field.field = "server"
|
||||
server_field.type = "string"
|
||||
if get_setting("server") <> invalid
|
||||
server_field.value = get_setting("server")
|
||||
screen.serverUrl = get_setting("server")
|
||||
end if
|
||||
group.findNode("example").text = tr("192.168.1.100:8096 or https://example.com/jellyfin")
|
||||
items = [ server_field ]
|
||||
config.configItems = items
|
||||
|
||||
button = group.findNode("submit")
|
||||
m.viewModel = {}
|
||||
button = screen.findNode("submit")
|
||||
button.observeField("buttonSelected", port)
|
||||
server_hostname = config.content.getChild(0)
|
||||
group.observeField("backPressed", port)
|
||||
server_hostname = screen.serverUrl
|
||||
screen.observeField("backPressed", port)
|
||||
|
||||
while(true)
|
||||
msg = wait(0, port)
|
||||
|
@ -34,11 +24,11 @@ function CreateServerGroup()
|
|||
if node = "submit"
|
||||
'Append default ports
|
||||
maxSlashes = 0
|
||||
if left(server_hostname.value,8) = "https://" or left(server_hostname.value,7) = "http://" then maxSlashes = 2
|
||||
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
|
||||
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"
|
||||
|
@ -46,29 +36,29 @@ function CreateServerGroup()
|
|||
end if
|
||||
end if
|
||||
'Append http:// to server
|
||||
if left(server_hostname.value,4) <> "http" then server_hostname.value = "http://" + server_hostname.value
|
||||
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 get_setting("server") <> server_hostname.value then
|
||||
set_setting("username", "")
|
||||
set_setting("password", "")
|
||||
endif
|
||||
end if
|
||||
set_setting("server", server_hostname.value)
|
||||
if ServerInfo() = invalid then
|
||||
' Maybe don't unset setting, but offer as a prompt
|
||||
' Server not found, is it online? New values / Retry
|
||||
print "Server not found, is it online? New values / Retry"
|
||||
group.findNode("alert").text = tr("Server not found, is it online?")
|
||||
screen.findNode("alert").text = tr("Server not found, is it online?")
|
||||
SignOut()
|
||||
else
|
||||
group.visible = false
|
||||
screen.visible = false
|
||||
return "true"
|
||||
endif
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end while
|
||||
|
||||
' Just hide it when done, in case we need to come back
|
||||
group.visible = false
|
||||
screen.visible = false
|
||||
end function
|
||||
|
||||
function CreateUserSelectGroup(users = [])
|
||||
|
@ -77,7 +67,7 @@ function CreateUserSelectGroup(users = [])
|
|||
end if
|
||||
group = CreateObject("roSGNode", "UserSelect")
|
||||
m.scene.appendChild(group)
|
||||
port = CreateObject("roMessagePort")
|
||||
port = CreateObject("roMessagePort")
|
||||
|
||||
group.itemContent = users
|
||||
group.findNode("userRow").observeField("userSelected", port)
|
||||
|
@ -107,7 +97,7 @@ function CreateSigninGroup(user = "")
|
|||
' Get and Save Jellyfin user login credentials
|
||||
group = CreateObject("roSGNode", "ConfigScene")
|
||||
m.scene.appendChild(group)
|
||||
port = CreateObject("roMessagePort")
|
||||
port = CreateObject("roMessagePort")
|
||||
|
||||
group.findNode("prompt").text = tr("Sign In")
|
||||
|
||||
|
@ -128,7 +118,7 @@ function CreateSigninGroup(user = "")
|
|||
if get_setting("password") <> invalid
|
||||
password_field.value = get_setting("password")
|
||||
end if
|
||||
items = [ username_field, password_field ]
|
||||
items = [username_field, password_field]
|
||||
config.configItems = items
|
||||
|
||||
button = group.findNode("submit")
|
||||
|
@ -181,9 +171,9 @@ function CreateHomeGroup()
|
|||
sidepanel.observeField("closeSidePanel", m.port)
|
||||
new_options = []
|
||||
options_buttons = [
|
||||
{"title": "Search", "id": "goto_search"},
|
||||
{"title": "Change server", "id": "change_server"},
|
||||
{"title": "Sign out", "id": "sign_out"}
|
||||
{ "title": "Search", "id": "goto_search" },
|
||||
{ "title": "Change server", "id": "change_server" },
|
||||
{ "title": "Sign out", "id": "sign_out" }
|
||||
]
|
||||
for each opt in options_buttons
|
||||
o = CreateObject("roSGNode", "OptionsButton")
|
||||
|
@ -200,7 +190,7 @@ function CreateHomeGroup()
|
|||
user_node.base_title = tr("Profile")
|
||||
user_options = []
|
||||
for each user in AvailableUsers()
|
||||
user_options.push({display: user.username + "@" + user.server, value: user.id})
|
||||
user_options.push({ display: user.username + "@" + user.server, value: user.id })
|
||||
end for
|
||||
user_node.choices = user_options
|
||||
user_node.value = get_setting("active_user")
|
||||
|
@ -303,7 +293,7 @@ function SeriesLister(group, page_size)
|
|||
sort_order = get_user_setting("series_sort_order", "Ascending")
|
||||
sort_field = get_user_setting("series_sort_field", "SortName")
|
||||
|
||||
item_list = ItemList(group.id, {"limit": page_size,
|
||||
item_list = ItemList(group.id, { "limit": page_size,
|
||||
"StartIndex": page_size * (group.pageNumber - 1),
|
||||
"SortBy": sort_field,
|
||||
"SortOrder": sort_order,
|
||||
|
@ -319,7 +309,7 @@ function CollectionLister(group, page_size)
|
|||
sort_order = get_user_setting("boxsets_sort_order", "Ascending")
|
||||
sort_field = get_user_setting("boxsets_sort_field", "SortName")
|
||||
|
||||
item_list = ItemList(group.id, {"limit": page_size,
|
||||
item_list = ItemList(group.id, { "limit": page_size,
|
||||
"StartIndex": page_size * (group.pageNumber - 1),
|
||||
"SortBy": sort_field,
|
||||
"SortOrder": sort_order,
|
||||
|
@ -333,7 +323,7 @@ end function
|
|||
function ChannelLister(group, page_size)
|
||||
sort_order = get_user_setting("channel_sort_order", "Ascending")
|
||||
sort_field = get_user_setting("channel_sort_field", "SortName")
|
||||
group.objects = Channels({"limit": page_size,
|
||||
group.objects = Channels({ "limit": page_size,
|
||||
"StartIndex": page_size * (group.pageNumber - 1),
|
||||
"SortBy": sort_field,
|
||||
"SortOrder": sort_order,
|
||||
|
|
Loading…
Reference in New Issue
Block a user