push to git
17
.vscode/launch.json
vendored
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "HOMEROKU",
|
||||||
|
"type": "brightscript",
|
||||||
|
"request": "launch",
|
||||||
|
"host": "192.168.0.109",
|
||||||
|
"password": "1143",
|
||||||
|
"rootDir": "${workspaceFolder}",
|
||||||
|
"injectRdbOnDeviceComponent": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
EX.json
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"month": "7",
|
||||||
|
"num": 614,
|
||||||
|
"link": "",
|
||||||
|
"year": "2009",
|
||||||
|
"news": "",
|
||||||
|
"safe_title": "Woodpecker",
|
||||||
|
"transcript": "[[A man with a beret and a woman are standing on a boardwalk, leaning on a handrail.]]\nMan: A woodpecker!\n<<Pop pop pop>>\nWoman: Yup.\n\n[[The woodpecker is banging its head against a tree.]]\nWoman: He hatched about this time last year.\n<<Pop pop pop pop>>\n\n[[The woman walks away. The man is still standing at the handrail.]]\n\nMan: ... woodpecker?\nMan: It's your birthday!\n\nMan: Did you know?\n\nMan: Did... did nobody tell you?\n\n[[The man stands, looking.]]\n\n[[The man walks away.]]\n\n[[There is a tree.]]\n\n[[The man approaches the tree with a present in a box, tied up with ribbon.]]\n\n[[The man sets the present down at the base of the tree and looks up.]]\n\n[[The man walks away.]]\n\n[[The present is sitting at the bottom of the tree.]]\n\n[[The woodpecker looks down at the present.]]\n\n[[The woodpecker sits on the present.]]\n\n[[The woodpecker pulls on the ribbon tying the present closed.]]\n\n((full width panel))\n[[The woodpecker is flying, with an electric drill dangling from its feet, held by the cord.]]\n\n{{Title text: If you don't have an extension cord I can get that too. Because we're friends! Right?}}",
|
||||||
|
"alt": "If you don't have an extension cord I can get that too. Because we're friends! Right?",
|
||||||
|
"img": "https://imgs.xkcd.com/comics/woodpecker.png",
|
||||||
|
"title": "Woodpecker",
|
||||||
|
"day": "24"
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
# XKCDViewer
|
# XKCDViewer
|
||||||
|
|
||||||
Unofficial XKCD Reader for Roku® source code.
|
Unofficial XKCD Reader for Roku® source code.
|
||||||
|
|
328
components/BigScene.xml
Executable file
|
@ -0,0 +1,328 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<component name="BigScene" extends="Scene">
|
||||||
|
<children>
|
||||||
|
<Group id="MainScene"
|
||||||
|
>
|
||||||
|
<Group id="header"
|
||||||
|
>
|
||||||
|
<Label id="num"
|
||||||
|
text="Loading..."
|
||||||
|
width="1280" height="75"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
/>
|
||||||
|
<Label id="title"
|
||||||
|
text="Loading Title..."
|
||||||
|
width="1280" height="150"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
/>
|
||||||
|
<Label id="date"
|
||||||
|
text="Loading Date..."
|
||||||
|
width="1280" height="233"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
/>
|
||||||
|
<Poster id="logo"
|
||||||
|
uri="pkg:/images/channel-poster_sd.png"
|
||||||
|
translation="[33, 33]"
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Group id="footer"
|
||||||
|
translation="[0, 640]"
|
||||||
|
>
|
||||||
|
<Label id="alt"
|
||||||
|
text="Loading alt text..."
|
||||||
|
width="1200" height="80"
|
||||||
|
translation="[40, 0]"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
wrap="true"
|
||||||
|
lineSpacing="0"
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Group id="labels">
|
||||||
|
<Rectangle id="left"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[18, 296]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/left.png"
|
||||||
|
/>
|
||||||
|
<Label id="changeIfFirst"
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="PREV"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="first"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[18, 360]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/rewind.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="FIRST"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="right"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[1198, 296]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/right.png"
|
||||||
|
/>
|
||||||
|
<Label id="changeIfFinal"
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="NEXT"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="last"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[1198, 360]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/fastforward.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[-4, 38]"
|
||||||
|
width="0"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="LATEST"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="down"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[512, 580]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/down.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="GET"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="zoom"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[640, 580]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/ok.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="ZOOM"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="load"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[576, 580]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/replay.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="NEW?"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="alt"
|
||||||
|
width="64" height="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
translation="[704, 580]"
|
||||||
|
color="0x00000000"
|
||||||
|
>
|
||||||
|
<Poster
|
||||||
|
translation="[16, 4]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
uri="pkg:/images/buttons/up.png"
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
translation="[0, 38]"
|
||||||
|
width="64"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
text="MORE"
|
||||||
|
color="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="font" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Label>
|
||||||
|
</Rectangle>
|
||||||
|
</Group>
|
||||||
|
<Rectangle id="scrim"
|
||||||
|
visible="false"
|
||||||
|
width="1280"
|
||||||
|
height="720"
|
||||||
|
color="0x00000080"
|
||||||
|
/>
|
||||||
|
<LayoutGroup id="comicholder"
|
||||||
|
layoutDirection="horiz"
|
||||||
|
horizAlignment="center" vertAlignment="center"
|
||||||
|
translation="[640, 360]"
|
||||||
|
>
|
||||||
|
<Poster id="comic"
|
||||||
|
loadDisplayMode="scaleToFit"
|
||||||
|
width="1080"
|
||||||
|
height="400"
|
||||||
|
translation="[100, 0]"
|
||||||
|
loadingBitmapUri="pkg:/images/reactions/loading.png"
|
||||||
|
loadingBitmapOpacity="0.25"
|
||||||
|
>
|
||||||
|
</Poster>
|
||||||
|
</LayoutGroup>
|
||||||
|
</Group>
|
||||||
|
<Rectangle id="SearchScrim"
|
||||||
|
visible="false"
|
||||||
|
width="1280"
|
||||||
|
height="720"
|
||||||
|
color="0x00000080"
|
||||||
|
/>
|
||||||
|
<Rectangle id="SearchScene"
|
||||||
|
visible="false"
|
||||||
|
width="1080"
|
||||||
|
height="382"
|
||||||
|
color="0xFFFFFFFF"
|
||||||
|
translation="[100, 338]"
|
||||||
|
>
|
||||||
|
<TypePad id="comic_id"
|
||||||
|
translation="[10, 70]"
|
||||||
|
/>
|
||||||
|
<Button id="backButton"
|
||||||
|
translation="[8, 312]"
|
||||||
|
minWidth="155"
|
||||||
|
height="50"
|
||||||
|
text="BACK"
|
||||||
|
textColor="0x000000FF"
|
||||||
|
focusedTextColor="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="textFont" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
<Font role="focusedTextFont" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Button>
|
||||||
|
<Button id="doneButton"
|
||||||
|
translation="[162, 312]"
|
||||||
|
minWidth="155"
|
||||||
|
height="50"
|
||||||
|
text="DONE"
|
||||||
|
textColor="0x000000FF"
|
||||||
|
focusedTextColor="0x000000FF"
|
||||||
|
>
|
||||||
|
<Font role="textFont" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
<Font role="focusedTextFont" uri="pkg:/images/xkcd.ttf" size="20" />
|
||||||
|
</Button>
|
||||||
|
<Label id="comic_sel_label"
|
||||||
|
translation="[10, 10]"
|
||||||
|
horizAlign="left" vertAlign="center"
|
||||||
|
text="GET COMIC #..."
|
||||||
|
color="0x000000FF"
|
||||||
|
/>
|
||||||
|
<Poster
|
||||||
|
translation="[715, 10]"
|
||||||
|
width="355"
|
||||||
|
height="362"
|
||||||
|
uri="pkg:/images/reactions/text_entry.png"
|
||||||
|
opacity="0.5"
|
||||||
|
/>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle id="AltScrim"
|
||||||
|
visible="false"
|
||||||
|
width="1280"
|
||||||
|
height="720"
|
||||||
|
color="0x00000080"
|
||||||
|
/>
|
||||||
|
<Rectangle id="AltScene"
|
||||||
|
visible="false"
|
||||||
|
width="1080"
|
||||||
|
height="200"
|
||||||
|
color="0xFFFFFFFF"
|
||||||
|
translation="[100, 520]"
|
||||||
|
>
|
||||||
|
<Label id="alttextbig"
|
||||||
|
text="Loading alt text..."
|
||||||
|
width="980"
|
||||||
|
height="200"
|
||||||
|
translation="[50, 0]"
|
||||||
|
horizAlign="center" vertAlign="center"
|
||||||
|
wrap="true"
|
||||||
|
lineSpacing="0"
|
||||||
|
/>
|
||||||
|
</Rectangle>
|
||||||
|
<!-- <Rectangle id="TextScrim"
|
||||||
|
visible="true"
|
||||||
|
width="1280"
|
||||||
|
height="720"
|
||||||
|
color="0x00000080"
|
||||||
|
>
|
||||||
|
<StandardKeyboardDialog id="TextKeeb"
|
||||||
|
title="Enter Comic Name Query"
|
||||||
|
/>
|
||||||
|
</Rectangle> -->
|
||||||
|
</children>
|
||||||
|
<!-- BrightScript Portion -->
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/literally_everything.brs"></script>
|
||||||
|
</component>
|
30
components/GetXKCDComic.xml
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--********** Copyright 2016 Roku Corp. All Rights Reserved. **********-->
|
||||||
|
|
||||||
|
<component name = "GetXKCDComic" extends = "Task" >
|
||||||
|
|
||||||
|
<interface>
|
||||||
|
<field id = "comicid" type = "string" />
|
||||||
|
<field id = "comic" type = "assocarray" />
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<script type = "text/brightscript" >
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "getcomic"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub getcomic()
|
||||||
|
data = createObject("roUrlTransfer")
|
||||||
|
data.SetCertificatesFile("common:/certs/ca-bundle.crt")
|
||||||
|
data.InitClientCertificates()
|
||||||
|
data.setUrl("https://xkcd.com" + m.top.comicid + "/info.0.json")
|
||||||
|
m.top.comic = ParseJson(data.GetToString())
|
||||||
|
end sub
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</component>
|
32
components/GetXKCDImage.xml
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--********** Copyright 2016 Roku Corp. All Rights Reserved. **********-->
|
||||||
|
|
||||||
|
<component name = "GetXKCDImage" extends = "Task" >
|
||||||
|
|
||||||
|
<interface>
|
||||||
|
<field id = "imageuri" type = "string" />
|
||||||
|
<field id = "image" type = "string" />
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<script type = "text/brightscript" >
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "getcomic"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub getcomic()
|
||||||
|
data = createObject("roUrlTransfer")
|
||||||
|
data.SetCertificatesFile("common:/certs/ca-bundle.crt")
|
||||||
|
data.InitClientCertificates()
|
||||||
|
uri = m.top.imageuri
|
||||||
|
data.setUrl(Left(uri, Len(uri) - 4) + "_2x.png")
|
||||||
|
data.GetToFile("tmp:/comic.png")
|
||||||
|
m.top.image = "tmp:/comic.png"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</component>
|
26
components/TypePad.xml
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<!--********** Copyright 2016 Roku Corp. All Rights Reserved. **********-->
|
||||||
|
|
||||||
|
<component name = "TypePad" extends = "DynamicCustomKeyboard" >
|
||||||
|
|
||||||
|
<script type = "text/brightscript" >
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
sub init()
|
||||||
|
palette = createObject("roSGNode", "RSGPalette")
|
||||||
|
m.top.keyGrid.keyDefinitionUri = "pkg:/images/coolKeyboardLayoutKDF.json"
|
||||||
|
m.top.keyGrid.horizWrap = true
|
||||||
|
m.top.hideTextBox = true
|
||||||
|
palette.colors = {KeyboardColor: "0xFFFFFFFF",
|
||||||
|
PrimaryTextColor: "0x000000FF",
|
||||||
|
SecondaryItemColor: "0x808080FF",
|
||||||
|
FocusColor: "0x000000FF",
|
||||||
|
FocusItemColor: "0xFFFFFFFF" }
|
||||||
|
m.top.keyGrid.palette = palette
|
||||||
|
end sub
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</component>
|
BIN
images/buttons/back.png
Executable file
After Width: | Height: | Size: 486 B |
BIN
images/buttons/down.png
Executable file
After Width: | Height: | Size: 495 B |
BIN
images/buttons/fastforward.png
Executable file
After Width: | Height: | Size: 600 B |
BIN
images/buttons/left.png
Executable file
After Width: | Height: | Size: 463 B |
BIN
images/buttons/ok.png
Executable file
After Width: | Height: | Size: 765 B |
BIN
images/buttons/replay.png
Executable file
After Width: | Height: | Size: 427 B |
BIN
images/buttons/rewind.png
Executable file
After Width: | Height: | Size: 610 B |
BIN
images/buttons/right.png
Executable file
After Width: | Height: | Size: 463 B |
BIN
images/buttons/star.png
Executable file
After Width: | Height: | Size: 546 B |
BIN
images/buttons/up.png
Executable file
After Width: | Height: | Size: 478 B |
BIN
images/channel-poster_fhd.png
Executable file
After Width: | Height: | Size: 53 KiB |
BIN
images/channel-poster_hd.png
Executable file
After Width: | Height: | Size: 27 KiB |
BIN
images/channel-poster_sd.png
Executable file
After Width: | Height: | Size: 17 KiB |
53
images/coolKeyboardLayoutKDF.json
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"keyboardWidthFHD": 300,
|
||||||
|
"keyboardHeightFHD": 242,
|
||||||
|
"keyboardWidthHD": 300,
|
||||||
|
"keyboardHeightHD": 242,
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"grids": [
|
||||||
|
{
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "1" },
|
||||||
|
{ "label": "2" },
|
||||||
|
{ "label": "3" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "4" },
|
||||||
|
{ "label": "5" },
|
||||||
|
{ "label": "6" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "7" },
|
||||||
|
{ "label": "8" },
|
||||||
|
{ "label": "9" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"icon": "theme:DKB_ClearKeyBitmap",
|
||||||
|
"focusIcon": "theme:DKB_ClearKeyFocusBitmap",
|
||||||
|
"strOut": "clear"
|
||||||
|
},
|
||||||
|
{ "label": "0" },
|
||||||
|
{
|
||||||
|
"icon": "theme:DKB_DeleteKeyBitmap",
|
||||||
|
"focusIcon": "theme:DKB_DeleteKeyFocusBitmap",
|
||||||
|
"autoRepeat": 1,
|
||||||
|
"strOut": "backspace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
images/reactions/loading.png
Executable file
After Width: | Height: | Size: 24 KiB |
BIN
images/reactions/loadingBig.png
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
images/reactions/logo.png
Executable file
After Width: | Height: | Size: 11 KiB |
BIN
images/reactions/text_entry.png
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
images/splash-screen_fhd.jpg
Executable file
After Width: | Height: | Size: 57 KiB |
BIN
images/splash-screen_hd.jpg
Executable file
After Width: | Height: | Size: 40 KiB |
BIN
images/splash-screen_sd.jpg
Executable file
After Width: | Height: | Size: 26 KiB |
BIN
images/xkcd.ttf
Executable file
29
manifest
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Roku, Inc. All rights reserved.
|
||||||
|
# Roku Channel Manifest File
|
||||||
|
# Full spec at bit.ly/roku-manifest-file
|
||||||
|
#
|
||||||
|
|
||||||
|
## Channel Details
|
||||||
|
title=Unofficial XKCD Reader for Roku®
|
||||||
|
major_version=1
|
||||||
|
minor_version=0
|
||||||
|
build_version=00001
|
||||||
|
|
||||||
|
## Channel Assets
|
||||||
|
### Main Menu Icons / Channel Poster Artwork
|
||||||
|
#### Image sizes are FHD: 540x405px | HD: 290x218px | SD: 214x144px
|
||||||
|
mm_icon_focus_fhd=pkg:/images/channel-poster_fhd.png
|
||||||
|
mm_icon_focus_hd=pkg:/images/channel-poster_hd.png
|
||||||
|
mm_icon_focus_sd=pkg:/images/channel-poster_sd.png
|
||||||
|
|
||||||
|
### Splash Screen + Loading Screen Artwork
|
||||||
|
#### Image sizes are FHD: 1920x1080px | HD: 1280x720px | SD: 720x480px
|
||||||
|
splash_screen_fhd=pkg:/images/splash-screen_fhd.jpg
|
||||||
|
splash_screen_hd=pkg:/images/splash-screen_hd.jpg
|
||||||
|
splash_screen_sd=pkg:/images/splash-screen_sd.jpg
|
||||||
|
|
||||||
|
splash_color=#FFFFFF
|
||||||
|
splash_min_time=3
|
||||||
|
|
||||||
|
confirm_partner_button=1
|
BIN
out/roku-deploy.zip
Executable file
19
source/Main.brs
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
sub Main()
|
||||||
|
print "in showChannelSGScreen"
|
||||||
|
'Indicate this is a Roku SceneGraph application'
|
||||||
|
screen = CreateObject("roSGScreen")
|
||||||
|
m.port = CreateObject("roMessagePort")
|
||||||
|
screen.setMessagePort(m.port)
|
||||||
|
|
||||||
|
scene = screen.CreateScene("BigScene")
|
||||||
|
screen.show()
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
msg = wait(0, m.port)
|
||||||
|
msgType = type(msg)
|
||||||
|
if msgType = "roSGScreenEvent"
|
||||||
|
if msg.isScreenClosed() then return
|
||||||
|
end if
|
||||||
|
end while
|
||||||
|
end sub
|
||||||
|
|
286
source/literally_everything.brs
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
function init()
|
||||||
|
m.Keebpalette = createObject("roSGNode", "RSGPalette")
|
||||||
|
m.Keebpalette.colors = { DialogBackgroundColor: "0xFFFFFFFF",
|
||||||
|
DialogItemColor: "0x000000FF",
|
||||||
|
DialogTextColor: "0x000000FF",
|
||||||
|
DialogFocusColor: "0xFFFFFFFF",
|
||||||
|
DialogFocusItemColor: "0x000000FF",
|
||||||
|
DialogSecondaryItemColor: "0x000000FF",
|
||||||
|
DialogKeyboardColor: "0xFFFFFFFF",
|
||||||
|
DialogInputFieldColor: "0xFFFFFFFF",
|
||||||
|
DialogFootprintColor: "0xFFFFFFFF" }
|
||||||
|
m.isBig = false
|
||||||
|
m.canExitSearch = true
|
||||||
|
m.inKeyboard = false
|
||||||
|
m.inBigAlt = false
|
||||||
|
m.skipGet = false
|
||||||
|
m.months = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
||||||
|
m.top.backgroundColor = "0xFFFFFFFF"
|
||||||
|
m.top.backgroundURI = ""
|
||||||
|
m.XKCDfontcolor = "0x000000FF"
|
||||||
|
m.XKCDseccolor = "0x606060FF"
|
||||||
|
|
||||||
|
m.title = m.top.findNode("title")
|
||||||
|
m.num = m.top.findNode("num")
|
||||||
|
m.date = m.top.findNode("date")
|
||||||
|
m.comic = m.top.findNode("comic")
|
||||||
|
m.scrim = m.top.findNode("scrim")
|
||||||
|
m.comic_sel_label = m.top.findNode("comic_sel_label")
|
||||||
|
m.alt = m.top.findNode("alt")
|
||||||
|
m.alttextbig = m.top.findNode("alttextbig")
|
||||||
|
m.title.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.title.font.size = 40
|
||||||
|
m.title.color = m.XKCDfontcolor
|
||||||
|
m.comic_sel_label.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.comic_sel_label.font.size = 40
|
||||||
|
m.comic_sel_label.color = m.XKCDfontcolor
|
||||||
|
m.num.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.num.font.size = 20
|
||||||
|
m.num.color = m.XKCDfontcolor
|
||||||
|
m.date.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.date.font.size = 20
|
||||||
|
m.date.color = m.XKCDfontcolor
|
||||||
|
m.alt.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.alt.font.size = 20
|
||||||
|
m.alt.color = m.XKCDseccolor
|
||||||
|
m.alttextbig.font.uri = "pkg:/images/xkcd.ttf"
|
||||||
|
m.alttextbig.font.size = 20
|
||||||
|
m.alttextbig.color = m.XKCDfontcolor
|
||||||
|
m.MainScene = m.top.findNode("MainScene")
|
||||||
|
m.SearchScene = m.top.findNode("SearchScene")
|
||||||
|
m.comic_id = m.top.findNode("comic_id")
|
||||||
|
m.doneButton = m.top.findNode("doneButton")
|
||||||
|
m.backButton = m.top.findNode("backButton")
|
||||||
|
m.comic_id.observeField("text", "searchkeyboardUpdate")
|
||||||
|
m.doneButton.observeField("buttonSelected", "searchbuttonClick")
|
||||||
|
m.backButton.observeField("buttonSelected", "backbuttonClick")
|
||||||
|
|
||||||
|
' m.TextKeeb = m.top.findNode("TextKeeb")
|
||||||
|
' m.TextKeeb.palette = m.Keebpalette
|
||||||
|
' m.TextKeeb.buttons = [
|
||||||
|
' "BACK",
|
||||||
|
' "DONE"
|
||||||
|
' ]
|
||||||
|
|
||||||
|
getNewestComicLol()
|
||||||
|
|
||||||
|
m.top.setFocus(true)
|
||||||
|
end function
|
||||||
|
|
||||||
|
function OpenSearchDialog()
|
||||||
|
m.SearchScene.visible = true
|
||||||
|
m.top.findNode("SearchScrim").visible = true
|
||||||
|
m.inKeyboard = true
|
||||||
|
m.comic_id.setFocus(true)
|
||||||
|
if m.comic_id.text.toInt() > m.num_latestComic OR m.comic_id.text.toInt() <= 0 then
|
||||||
|
m.canExitSearch = false
|
||||||
|
else
|
||||||
|
m.canExitSearch = true
|
||||||
|
end if
|
||||||
|
end function
|
||||||
|
|
||||||
|
function searchkeyboardUpdate()
|
||||||
|
?m.comic_id.text
|
||||||
|
if Len(m.comic_id.text) > 5 then
|
||||||
|
m.comic_id.text = Left(m.comic_id.text, 5)
|
||||||
|
end if
|
||||||
|
if m.comic_id.text.toInt() > m.num_latestComic OR m.comic_id.text.toInt() <= 0 then
|
||||||
|
m.canExitSearch = false
|
||||||
|
else
|
||||||
|
m.canExitSearch = true
|
||||||
|
end if
|
||||||
|
m.comic_sel_label.text = "GET COMIC #" + m.comic_id.text
|
||||||
|
end function
|
||||||
|
|
||||||
|
function searchbuttonClick()
|
||||||
|
if not m.canExitSearch or not m.inKeyboard then return 0
|
||||||
|
m.SearchScene.visible = false
|
||||||
|
m.top.findNode("SearchScrim").visible = false
|
||||||
|
m.inKeyboard = false
|
||||||
|
specificcomicget(m.comic_id.text.toInt())
|
||||||
|
m.comic_id.text = ""
|
||||||
|
m.comic_sel_label.text = "GET COMIC #..."
|
||||||
|
m.comic_id.setFocus(false)
|
||||||
|
m.doneButton.setFocus(false)
|
||||||
|
m.backButton.setFocus(false)
|
||||||
|
m.top.setFocus(true)
|
||||||
|
end function
|
||||||
|
|
||||||
|
function backbuttonClick()
|
||||||
|
m.SearchScene.visible = false
|
||||||
|
m.top.findNode("SearchScrim").visible = false
|
||||||
|
m.inKeyboard = false
|
||||||
|
m.comic_id.text = ""
|
||||||
|
m.comic_sel_label.text = "GET COMIC #..."
|
||||||
|
m.comic_id.setFocus(false)
|
||||||
|
m.doneButton.setFocus(false)
|
||||||
|
m.backButton.setFocus(false)
|
||||||
|
m.top.setFocus(true)
|
||||||
|
end function
|
||||||
|
|
||||||
|
function getNewestComicLol()
|
||||||
|
m.getLatestComicTask = createObject("roSGNode", "GetXKCDComic")
|
||||||
|
m.ct = m.getLatestComicTask
|
||||||
|
m.getLatestComicTask.comicid = ""
|
||||||
|
m.getLatestComicTask.observeField("comic", "startComicInitial")
|
||||||
|
m.getLatestComicTask.control = "RUN"
|
||||||
|
end function
|
||||||
|
|
||||||
|
function startComicInitial()
|
||||||
|
m.num_earliestComic = 1
|
||||||
|
m.num_latestComic = m.getLatestComicTask.comic.num
|
||||||
|
m.num_currentComic = m.getLatestComicTask.comic.num
|
||||||
|
sec = CreateObject("roRegistrySection", "Settings")
|
||||||
|
if sec.Exists("CurrentComic") and not m.skipGet then
|
||||||
|
specificcomicget(sec.Read("CurrentComic").toInt())
|
||||||
|
else
|
||||||
|
getcomic()
|
||||||
|
endif
|
||||||
|
m.skipGet = true
|
||||||
|
end function
|
||||||
|
|
||||||
|
function getcomic()
|
||||||
|
?m.ct.comic
|
||||||
|
if m.ct.comic = invalid then
|
||||||
|
m.title.text = "For some reason, that failed."
|
||||||
|
return true
|
||||||
|
end if
|
||||||
|
m.title.text = m.ct.comic.title
|
||||||
|
m.num.text = "Comic #" + m.ct.comic.num.ToStr()
|
||||||
|
m.alt.text = m.ct.comic.alt
|
||||||
|
m.alttextbig.text = m.ct.comic.alt
|
||||||
|
m.date.text = m.months[m.ct.comic.month.toInt() - 1] + " " + m.ct.comic.day + ", " + m.ct.comic.year
|
||||||
|
m.comic.SetCertificatesFile("common:/certs/ca-bundle.crt")
|
||||||
|
m.comic.InitClientCertificates()
|
||||||
|
m.comic.uri = m.ct.comic.img
|
||||||
|
if m.ct.comic.num >= m.num_latestComic then
|
||||||
|
m.top.findNode("changeIfFinal").text = "NEW?"
|
||||||
|
else
|
||||||
|
m.top.findNode("changeIfFinal").text = "NEXT"
|
||||||
|
end if
|
||||||
|
if m.ct.comic.num <= m.num_earliestComic then
|
||||||
|
m.top.findNode("changeIfFirst").text = ""
|
||||||
|
else
|
||||||
|
m.top.findNode("changeIfFirst").text = "PREV"
|
||||||
|
end if
|
||||||
|
sec = CreateObject("roRegistrySection", "Settings")
|
||||||
|
sec.Write("CurrentComic", m.ct.comic.num.toStr())
|
||||||
|
sec.Flush()
|
||||||
|
end function
|
||||||
|
|
||||||
|
function newcomicget(number as Integer)
|
||||||
|
m.num_currentComic = m.num_currentComic + number
|
||||||
|
if m.num_currentComic > m.num_latestComic then
|
||||||
|
m.num_currentComic = m.num_latestComic
|
||||||
|
getNewestComicLol()
|
||||||
|
return 0
|
||||||
|
else if m.num_currentComic < m.num_earliestComic then
|
||||||
|
m.num_currentComic = m.num_earliestComic
|
||||||
|
return 0
|
||||||
|
end if
|
||||||
|
m.getComicTask = createObject("roSGNode", "GetXKCDComic")
|
||||||
|
m.ct = m.getComicTask
|
||||||
|
m.getComicTask.comicid = "/" + m.num_currentComic.ToStr()
|
||||||
|
m.getComicTask.observeField("comic", "getcomic")
|
||||||
|
m.getComicTask.control = "RUN"
|
||||||
|
end function
|
||||||
|
|
||||||
|
function specificcomicget(number as Integer)
|
||||||
|
m.num_currentComic = number
|
||||||
|
m.getComicTask = createObject("roSGNode", "GetXKCDComic")
|
||||||
|
m.ct = m.getComicTask
|
||||||
|
m.getComicTask.comicid = "/" + m.num_currentComic.ToStr()
|
||||||
|
?m.getComicTask.comicid
|
||||||
|
m.getComicTask.observeField("comic", "getcomic")
|
||||||
|
m.getComicTask.control = "RUN"
|
||||||
|
end function
|
||||||
|
|
||||||
|
function toggleBig()
|
||||||
|
m.isBig = not m.isBig
|
||||||
|
if m.isBig then
|
||||||
|
m.comic.translation = [100, 50]
|
||||||
|
m.comic.width = 1080
|
||||||
|
m.comic.height = 620
|
||||||
|
m.comic.loadingBitmapUri="pkg:/images/reactions/loadingBig.png"
|
||||||
|
m.scrim.visible = true
|
||||||
|
else
|
||||||
|
m.comic.translation = [100, 0]
|
||||||
|
m.comic.width = 1080
|
||||||
|
m.comic.height = 400
|
||||||
|
m.comic.loadingBitmapUri="pkg:/images/reactions/loading.png"
|
||||||
|
m.scrim.visible = false
|
||||||
|
end if
|
||||||
|
end function
|
||||||
|
|
||||||
|
function toggleAlt()
|
||||||
|
m.inBigAlt = not m.inBigAlt
|
||||||
|
if m.inBigAlt then
|
||||||
|
m.top.findNode("AltScrim").visible = true
|
||||||
|
m.top.findNode("AltScene").visible = true
|
||||||
|
else
|
||||||
|
m.top.findNode("AltScrim").visible = false
|
||||||
|
m.top.findNode("AltScene").visible = false
|
||||||
|
end if
|
||||||
|
end function
|
||||||
|
|
||||||
|
function onKeyEvent(key as String, press as Boolean) as Boolean
|
||||||
|
handled = false
|
||||||
|
if press then
|
||||||
|
if not m.inKeyboard then
|
||||||
|
if (key = "back") then
|
||||||
|
handled = false
|
||||||
|
if m.inBigAlt then
|
||||||
|
toggleAlt()
|
||||||
|
handled = true
|
||||||
|
end if
|
||||||
|
if m.isBig then
|
||||||
|
toggleBig()
|
||||||
|
handled = true
|
||||||
|
end if
|
||||||
|
else
|
||||||
|
if (key = "left") then
|
||||||
|
newcomicget(-1)
|
||||||
|
else if (key = "right") then
|
||||||
|
newcomicget(1)
|
||||||
|
else if (key = "down") then
|
||||||
|
if not m.isBig and not m.inBigAlt then OpenSearchDialog()
|
||||||
|
else if (key = "up") then
|
||||||
|
if not m.isBig then
|
||||||
|
toggleAlt()
|
||||||
|
else
|
||||||
|
toggleBig()
|
||||||
|
end if
|
||||||
|
else if (key = "replay" OR key = "fastforward") then
|
||||||
|
getNewestComicLol()
|
||||||
|
else if (key = "rewind") then
|
||||||
|
specificcomicget(1)
|
||||||
|
else if (key = "OK") then
|
||||||
|
if not m.inBigAlt then
|
||||||
|
toggleBig()
|
||||||
|
else
|
||||||
|
toggleAlt()
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
handled = true
|
||||||
|
end if
|
||||||
|
else
|
||||||
|
if (key = "back") then
|
||||||
|
backbuttonClick()
|
||||||
|
else if key = "down" and not m.backButton.hasFocus() and not m.doneButton.hasFocus()
|
||||||
|
m.backButton.setFocus(true)
|
||||||
|
else if key = "up" and not m.comic_id.hasFocus()
|
||||||
|
m.comic_id.setFocus(true)
|
||||||
|
else if key = "left" and not m.doneButton.hasFocus() and not m.comic_id.hasFocus()
|
||||||
|
m.doneButton.setFocus(true)
|
||||||
|
else if key = "left" and not m.backButton.hasFocus() and not m.comic_id.hasFocus()
|
||||||
|
m.backButton.setFocus(true)
|
||||||
|
else if key = "right" and not m.doneButton.hasFocus() and not m.comic_id.hasFocus()
|
||||||
|
m.doneButton.setFocus(true)
|
||||||
|
else if key = "right" and not m.backButton.hasFocus() and not m.comic_id.hasFocus()
|
||||||
|
m.backButton.setFocus(true)
|
||||||
|
end if
|
||||||
|
handled = true
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
return handled
|
||||||
|
end function
|