Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promises demo in BrightScript (BRS) #12

Merged
merged 8 commits into from
Dec 22, 2023
2 changes: 2 additions & 0 deletions .demos/simple-brightscript/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#ROKU_PWD={YOUR_ROKU_DEVICE_DEV_PASSWORD}
#ROKU_HOST={YOUR_ROKU_DEVICE_IP_ADDRESS}
6 changes: 6 additions & 0 deletions .demos/simple-brightscript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#Visual Studio Code
.vscode
out/

#npm
/node_modules
210 changes: 210 additions & 0 deletions .demos/simple-brightscript/components/MainScene.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
sub init()
initOnScreenImage()
m.top.observeFieldScoped("simpleResult", "onSimpleResultChange")
m.top.observeFieldScoped("chainResult", "onChainResultChange")
m.top.observeFieldScoped("parallelResult", "onParallelResultChange")

'Uncomment the example below to run...

'Simple network request example (passing in the `m` scope as context)
' promise = networkRequest("http://ip-api.com/json/", "GET")
' promises_onThen(promise, sub(response as object, context = {} as dynamic)
' print "Your timezone is " + response.timezone
' end sub, m)

'Simple single request using method
' separateCallbacksExample("http://ip-api.com/json/")

'Chain requests
' chainExample()

'Parallel requests
' parallelExample()

'Simple single request using method with error handling
' separateCallbacksExample("http://invalid--url.com")
end sub

function networkRequest(url as string, method = "GET" as string, body = {} as object) as object
promise = promises_create()
task = createObject("roSGNode", "NetworkTask")
task.url = url
task.method = method
task.body = body
task.promise = promise
task.control = "RUN"
return promise
end function

sub separateCallbacksExample(url as string, method = "GET" as string)
context = {
result: invalid
}

promise = networkRequest(url, method)

promises_onThen(promise, sub(response as object, context = {} as dynamic)
if (response.error = invalid)
context.result = "Your timezone is " + response.timezone
else
'See: https://developer.roku.com/en-gb/docs/references/brightscript/events/rourlevent.md#getresponsecode-as-integer
print "Got a network error response!!!", response.responseCode
end if

m.top.simpleResult = context

end sub, context)

promises_onCatch(promise, sub(response as object, context = {} as dynamic)
print "Caught a Simple promise error!!!", response
end sub, context)

promises_onFinally(promise, sub(response as object, context = {} as dynamic)
print "Simple promise completed!!!"
end sub, context)
end sub

sub chainExample()
context = {
result: invalid
}

promise = networkRequest("http://ip-api.com/json/")

promises_chain(promise, context).then(function(ipApiData, context)
if (ipApiData.error = invalid)
print "Promises chain first call completed!!!"
return getTimeApiTimeToFiji(ipApiData.timezone)
else
print "Promises chain first call failed!!!"
return {
error: true
}
end if

end function).then(function(timeApiData, context)
if (timeApiData.error = invalid)
print "Promises chain second call completed!!!"
context.result = getChainResultString(timeApiData)
else
print "Promises chain second call failed!!!"
context.result = {
error: true
}
end if

m.top.chainResult = context

end function).catch(function(error, context)
print "Caught an error with the chain promise!!!", error

end function).finally(function(error, context)
print "Chain promise completed!!!", error
end function)
end sub

sub parallelExample()
promises = promises_all([
getIpApiTimeZoneByDomain("google.com")
getIpApiTimeZoneByDomain("netflix.com")
getIpApiTimeZoneByDomain("chatgpt.com")
])
promises_chain(promises).then(function(timezones)
m.top.parallelResult = {
result: [
"Google.com's timezone is " + timezones[0].timezone,
"Netflix.com's timezone is " + timezones[1].timezone,
"ChatGPT.com's timezone is " + timezones[2].timezone
]
}

end function).catch(function(error)
print "Caught an error with the parallel promise!!!", error

end function)
end sub

'****************************************************************
'#region *** OBSERVER CALLBACKS
'****************************************************************

sub onSimpleResultChange(event as object)
print "onSimpleResultChange:"
print event.getData().result
end sub

sub onChainResultChange(event as object)
print "onChainResultChange:"
print event.getData().result
end sub

sub onParallelResultChange(event as object)
print "onParallelResultChange:"
for each resultStr in event.getData().result
print resultStr
end for
end sub

'****************************************************************
'#endregion *** OBSERVER CALLBACKS
'****************************************************************

'****************************************************************
'#region *** HELPER FUNCTIONS
'****************************************************************

function getIpApiTimeZoneByDomain(domain as string) as object
url = "http://ip-api.com/json/" + domain
return networkRequest(url)
end function

function getTimeApiTimeToFiji(fromTimeZone as object) as object
print "Your timezone is " + fromTimeZone
url = "https://timeapi.io/api/Conversion/ConvertTimeZone"
method = "POST"

body = {
"fromTimeZone": fromTimeZone
"dateTime": getFullDate() + " 00:00:00"
"toTimeZone": "Pacific/Fiji"
"dstAmbiguity": ""
}
return networkRequest(url, method, body)
end function

function getFullDate() as string
date = CreateObject("roDateTime")
fullDate = date.getYear().toStr() + "-"

if date.getMonth() < 10
fullDate += "0"
end if
fullDate += date.getMonth().toStr() + "-"

if date.getDayOfMonth() < 10
fullDate += "0"
end if
fullDate += date.getDayOfMonth().toStr()

return fullDate
end function

function getChainResultString(data as object) as object
currentDay = 25
fijiDay = data.conversionResult.day
fijiHour = data.conversionResult.hour
aheadOrBehind = "ahead"
if (fijiDay > currentDay) then aheadOrBehind = "behind"
return "Fiji is " + fijiHour.toStr() + " hours " + aheadOrBehind + " of your timezone!"
end function

sub initOnscreenImage()
'Setting the image size based on the Roku device UI resolution
resolutionName = LCase(createObject("roDeviceInfo").getUIResolution().name)
backgroundImage = m.top.findNode("backgroundImage")
backgroundImage.uri = backgroundImage.uri.replace("{size}", resolutionName)
end sub

'****************************************************************
'#endregion *** HELPER FUNCTIONS
'****************************************************************
13 changes: 13 additions & 0 deletions .demos/simple-brightscript/components/MainScene.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="MainScene" extends="Scene">
<script type="text/brightscript" uri="MainScene.brs"/>
<script type="text/brightscript" uri="pkg:/source/promises.brs"/>
<interface>
<field id="simpleResult" type="assocarray"/>
<field id="chainResult" type="assocarray"/>
<field id="parallelResult" type="assocarray"/>
</interface>
<children>
<Poster id="backgroundImage" uri="pkg:/images/splash-screen_{size}.png"/>
</children>
</component>
55 changes: 55 additions & 0 deletions .demos/simple-brightscript/components/NetworkTask.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
sub init()
m.port = CreateObject("roMessagePort")
m.REQUEST_TIMEOUT = 5
m.top.functionName = "makeRequest"
end sub

sub makeRequest()
try
result = getNetworkResult(m.top.url, m.top.method, m.top.body)
if (result.data <> invalid)
result = ParseJson(result.data)
end if
promises_resolve(result, m.top.promise)
catch e
promises_reject(e, m.top.promise)
end try
end sub

function getNetworkResult(url as string, method as string, body as object) as object
urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.setUrl(url)
urlTransfer.setRequest(method)
urlTransfer.setCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.initClientCertificates()
urlTransfer.setMessagePort(m.port)
urlTransfer.setPort(m.port)
urlTransfer.setMinimumTransferRate(1, m.REQUEST_TIMEOUT)
if (method = "GET")
urlTransfer.asyncGetToString()
else
urlTransfer.addHeader("Accept", "application/json")
urlTransfer.addHeader("Content-Type", "application/json")
body = FormatJSON(body)
urlTransfer.asyncPostFromString(body)
end if

msg = wait(0, m.port)
if type(msg) = "roUrlEvent"

responseCode = msg.getResponseCode()
responseString = msg.getString()

if responseCode = 200
return {
data: responseString
}
else
return {
error: true
responseCode: responseCode
data: invalid
}
end if
end if
end function
11 changes: 11 additions & 0 deletions .demos/simple-brightscript/components/NetworkTask.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?rokuml version="1.0" encoding="utf-8"?>
<component name="NetworkTask" extends="Task">
<script type="text/brightscript" uri="NetworkTask.brs"/>
<script type="text/brightscript" uri="pkg:/source/promises.brs"/>
<interface>
<field id="url" type="string"/>
<field id="method" type="string"/>
<field id="body" type="assocarray"/>
<field id="promise" type="node"/>
</interface>
</component>
6 changes: 6 additions & 0 deletions .demos/simple-brightscript/components/Promise.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<component name="promises_Promise" extends="Node">
<interface>
<field id="promiseState" type="string" value="pending" alwaysNotify="true" />
</interface>
</component>
<!--//# sourceMappingURL=./Promise.xml.map -->
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions .demos/simple-brightscript/manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Channel Details
title=Promises Demo BrightScript (BRS)
major_version=1
minor_version=0
build_version=0

# Channel Assets
mm_icon_focus_sd=pkg:/images/channel-poster_sd.png
mm_icon_focus_hd=pkg:/images/channel-poster_hd.png
mm_icon_focus_fhd=pkg:/images/channel-poster_fhd.png

# Splash Screen + Loading Screen Artwork
splash_screen_sd=pkg:/images/splash-screen_sd.jpg
splash_screen_hd=pkg:/images/splash-screen_hd.jpg
splash_screen_fhd=pkg:/images/splash-screen_fhd.jpg
splash_color=#808080
splash_min_time=0

# Resolution
ui_resolutions=fhd
15 changes: 15 additions & 0 deletions .demos/simple-brightscript/source/main.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
sub Main(args as object)
screen = createObject("roSGScreen")
m.port = createObject("roMessagePort")
screen.setMessagePort(m.port)
screen.createScene("MainScene")
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
Loading
Loading