3
0
mirror of https://github.com/britzl/monarch.git synced 2025-06-27 10:27:49 +02:00

Compare commits

...

24 Commits

Author SHA1 Message Date
Björn Ritzl
9a6d5f7a7b Update ci-workflow.yml 2025-05-15 08:58:40 +02:00
Björn Ritzl
d68e27b2ad Update ci-workflow.yml 2025-05-15 08:57:50 +02:00
Björn Ritzl
5525707744 Cleaned up callback tests
Fixes #
2025-05-14 22:56:47 +02:00
Alexander
aea267cc35
fix gui template (#112)
https://github.com/britzl/monarch/issues/111
2024-09-27 08:58:51 +02:00
Pawel
6ba3064749
Fixed an error that appears when trying to delete an instance that is already deleted. (#109)
* Prevent deleting already removed instances.

* Prehashed empty hash.

* Use go.exists instead of pcall, when detecting non existing instances.
2024-03-04 16:06:56 +01:00
Björn Ritzl
b78b896ada Update README_API.md 2024-01-30 11:08:38 +01:00
SalavatR
679482f84d
Add a check for missing resources in collection proxies. (#107)
* Update monarch.lua

* Update monarch.lua

* Update monarch.lua
2024-01-30 11:03:37 +01:00
Björn Ritzl
4c6e26fd71 Removed backward comp fix for monarch.back() 2024-01-12 08:31:48 +01:00
bedryck
00c30792a9
fix a problem of sequential in back function (#104) 2024-01-12 08:22:43 +01:00
Björn Ritzl
b01f5d28c3 Update monarch.lua 2023-12-27 15:54:09 +01:00
Pete Garcin
43e847dacc
Guard DEPRECATED transition_id overwriting transition_url (#100) 2023-12-27 15:52:36 +01:00
Björn Ritzl
ce5ca26b6c Update README_TRANSITIONS.md
Fixes #102
2023-12-27 15:51:38 +01:00
Björn Ritzl
742779d749 Allow monarch.post() to loaded screens
Fixes #98
2023-10-26 13:54:14 +02:00
Björn Ritzl
84944f3f22 Added monarch.is_loaded() 2023-10-26 11:43:19 +02:00
Björn Ritzl
c473aa053c Update monarch.lua 2023-08-31 09:25:00 +02:00
Björn Ritzl
169236acbd Improved on_post() to also accept a url 2023-08-31 09:22:24 +02:00
Björn Ritzl
b7053d2ce4 Fixed another back issue (and tests) 2023-08-10 00:21:15 +02:00
Björn Ritzl
91204ca30b
Wait for both in and out transitions (#97) 2023-08-10 00:08:10 +02:00
Björn Ritzl
6f79bd0326 Swap transition count and listener order 2023-08-08 23:51:48 +02:00
Björn Ritzl
e5214edb22 Fix back() callback 2023-08-08 23:51:29 +02:00
Björn Ritzl
1d4e48c0de Update test_monarch.lua 2023-08-08 22:55:29 +02:00
Björn Ritzl
5bdc3e4540 Added option table to back() 2023-08-08 22:53:00 +02:00
Björn Ritzl
85123c84e9 Show how to use monarch listeners 2023-08-08 22:49:58 +02:00
Björn Ritzl
a605f4f6f8 Fixed tests 2023-08-03 10:42:06 +02:00
16 changed files with 270 additions and 160 deletions

View File

@ -7,13 +7,13 @@ jobs:
name: Build and run
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9
with:
java-version: '17'
java-version: '21.0.5+11.0.LTS'
distribution: 'temurin'
- name: Run.sh
env:
DEFOLD_USER: bjorn.ritzl@gmail.com
DEFOLD_AUTH: foobar
DEFOLD_BOOSTRAP_COLLECTION: /test/test.collectionc
run: ./.test/run.sh

3
.gitignore vendored
View File

@ -9,3 +9,6 @@ build
builtins
.internal
luacov.report.out
/.editor_settings
manifest.private.der
manifest.public.der

View File

@ -5,7 +5,6 @@ else
PLATFORM="$1"
fi
echo "${PLATFORM}"
# {"version": "1.2.89", "sha1": "5ca3dd134cc960c35ecefe12f6dc81a48f212d40"}
@ -16,26 +15,28 @@ echo "Using Defold dmengine_headless version ${SHA1}"
# Create dmengine_headless and bob.jar URLs
DMENGINE_URL="http://d.defold.com/archive/${SHA1}/engine/${PLATFORM}/dmengine_headless"
BOB_URL="http://d.defold.com/archive/${SHA1}/bob/bob.jar"
DMENGINE_FILE=dmengine_headless_${SHA1}
BOB_FILE=bob_${SHA1}.jar
# Download dmengine_headless
echo "Downloading ${DMENGINE_URL}"
curl -L -o dmengine_headless ${DMENGINE_URL}
chmod +x dmengine_headless
if ! [ -f ${DMENGINE_FILE} ]; then
echo "Downloading ${DMENGINE_URL} to ${DMENGINE_FILE}"
curl -L -o ${DMENGINE_FILE} ${DMENGINE_URL}
chmod +x ${DMENGINE_FILE}
fi
# Download bob.jar
echo "Downloading ${BOB_URL}"
curl -L -o bob.jar ${BOB_URL}
if ! [ -f ${BOB_FILE} ]; then
echo "Downloading ${BOB_URL} to ${BOB_FILE}"
curl -L -o ${BOB_FILE} ${BOB_URL}
fi
# Fetch libraries
echo "Running bob.jar - resolving dependencies"
java -jar bob.jar --auth "foobar" --email "john@doe.com" resolve
echo "Running ${BOB_FILE} - resolving dependencies"
java -jar ${BOB_FILE} --auth "foobar" --email "john@doe.com" resolve
echo "Running bob.jar - building"
java -jar bob.jar --debug build --keep-unused
echo "Running ${BOB_FILE} - building"
java -jar ${BOB_FILE} --debug build --settings=test.settings
echo "Starting dmengine_headless"
if [ -n "${DEFOLD_BOOSTRAP_COLLECTION}" ]; then
./dmengine_headless --config=bootstrap.main_collection=${DEFOLD_BOOSTRAP_COLLECTION}
else
./dmengine_headless
fi
echo "Starting ${DMENGINE_FILE}"
./${DMENGINE_FILE}

View File

@ -40,13 +40,18 @@ Clear the stack of screens completely. Any visible screen will be hidden by navi
* `callback` (function) - Optional function to call when the stack has been cleared.
## monarch.back([data], [callback])
## monarch.back([options], [data], [callback])
Go back to a previous Monarch screen. This operation will be added to the queue if Monarch is busy.
**PARAMETERS**
* `options` (table) - Options when showing the new screen (see below).
* `data` (table) - Optional data to associate with the screen you are going back to. Retrieve using `monarch.data()`.
* `callback` (function) - Optional function to call when the previous screen is visible.
The options table can contain the following fields:
* `sequential` (boolean) - If the `sequential` flag is set Monarch will start loading the screen only after the previous screen finished transitioning out.
## monarch.preload(screen_id, [options], [callback])
Preload a Monarch screen. This will load but not enable the screen. This is useful for content heavy screens that you wish to be able to show without having to wait for it load. This operation will be added to the queue if Monarch is busy.
@ -207,12 +212,21 @@ IMPORTANT! You must call `monarch.on_message(message_id, message, sender)` from
* `fn` (function) - The function to call screen focus changes
## monarch.on_post(screen_id, fn)
Set a function to be called when `msg.post()` is called on a specific screen. IMPORTANT! You must call `monarch.on_message(message_id, message, sender)` from the same script as this function was called.
## monarch.on_post(screen_id, fn_or_url)
Set either a function to be called when `msg.post()` is called on a specific screen or a URL where the message is sent.
IMPORTANT! If you provide a function you must also make sure to call `monarch.on_message(message_id, message, sender)` from the same script as this function was called.
**PARAMETERS**
* `screen_id` (string|hash) - Id of the screen
* `fn` (function) - The function to call when the screen receives a message using `msg.post`
* `fn_or_url` (function) - The function to call or URL to send message to
## monarch.has_missing_resources(screen_id)
Check if a screen has any missing resources. If the screen is loaded by a collection proxy with Load Dynamically this will use `collectionproxy.missing_resources()`. For other cases this function will always return false.
**RETURN**
* `result` (boolean) - true if the screen has missing resources
## monarch.debug()

View File

@ -114,7 +114,7 @@ end
function on_message(self, message_id, message, sender)
if message_id == hash("my_resize_message") then
self.transition.window_resized(message.width, message.height)
transition.window_resized(message.width, message.height)
end
end
```

View File

@ -29,7 +29,7 @@ function on_input(self, action_id, action)
end
elseif gui.pick_node(self.no, action.x, action.y) then
print("no")
monarch.back(function()
monarch.back(nil, nil, function()
print("back from popup done")
end)
end

View File

@ -27,7 +27,7 @@ function on_input(self, action_id, action)
end)
elseif gui.pick_node(self.cancel, action.x, action.y) then
print("cancel")
monarch.back(function()
monarch.back(nil, nil, function()
print("back from popup done")
end)
elseif gui.pick_node(self.about, action.x, action.y) then

View File

@ -19,7 +19,7 @@ function on_input(self, action_id, action)
end)
elseif gui.pick_node(self.back, action.x, action.y) then
print("back")
monarch.back(function()
monarch.back(nil, nil, function()
print("back from pregame done")
end)
end

View File

@ -4,10 +4,25 @@ function init(self)
monarch.debug()
msg.post("@render:/", "clear_color", { color = vmath.vector4(0.4, 0.6, 0.8,1.0) })
msg.post("#", "init_monarch") -- wait until init() has been called for all screen.script instances
monarch.add_listener()
end
function final(self)
monarch.remove_listener()
end
function on_message(self, message_id, message, sender)
if message_id == hash("init_monarch") then
monarch.show(hash("window1"))
elseif message_id == monarch.SCREEN_TRANSITION_IN_STARTED then
print("Monarch screen transition in started", message.screen)
elseif message_id == monarch.SCREEN_TRANSITION_IN_FINISHED then
print("Monarch screen transition in finished", message.screen)
elseif message_id == monarch.SCREEN_TRANSITION_OUT_STARTED then
print("Monarch screen transition out started", message.screen)
elseif message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED then
print("Monarch screen transition out finished", message.screen)
elseif message_id == monarch.SCREEN_TRANSITION_FAILED then
print("Monarch screen transition failed")
end
end

View File

@ -79,16 +79,9 @@ end
gui_template = function(gui_script)
return [[script: "]].. gui_script .. [["
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512
]]
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
]]
end
gui_script_content = [[local monarch = require "monarch.monarch"
@ -116,43 +109,43 @@ end
collection_template = function(gui_script, name)
return [[name: "]].. name .. [["
scale_along_z: 0
embedded_instances {
id: "go"
data: "components {\n"
" id: \"monarch\"\n"
" component: \"]].. gui_script .. [[\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
]]
scale_along_z: 0
embedded_instances {
id: "go"
data: "components {\n"
" id: \"monarch\"\n"
" component: \"]].. gui_script .. [[\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
]]
end

View File

@ -228,6 +228,17 @@ function M.is_visible(id)
end
--- Check if a screen is loaded
-- @param id (string|hash)
-- @return true if the screen is loaded
function M.is_loaded(id)
assert(id, "You must provide a screen id")
id = tohash(id)
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
return screens[id].loaded
end
--- Check if a screen is a popup
-- @param id Screen id
-- @return true if the screen is a popup
@ -419,7 +430,9 @@ local function unload(screen, force)
elseif screen.factory then
log("unload() factory", screen.id)
for id, instance in pairs(screen.factory_ids) do
go.delete(instance)
if go.exists(instance) then
go.delete(instance)
end
end
screen.factory_ids = nil
if screen.auto_preload and not force then
@ -451,8 +464,7 @@ local function preload(screen)
screen.preloading = true
if screen.proxy then
log("preload() proxy")
local missing_resources = collectionproxy.missing_resources(screen.proxy)
if #missing_resources > 0 then
if M.has_missing_resources(screen.id) then
local error_message = ("preload() collection proxy %s is missing resources"):format(tostring(screen.id))
log(error_message)
screen.preloading = false
@ -509,8 +521,12 @@ local function load(screen)
msg.post(screen.proxy, MSG_ENABLE)
elseif screen.factory then
screen.factory_ids = collectionfactory.create(screen.factory)
screen.transition_url = screen.factory_ids[screen.transition_id]
screen.focus_url = screen.factory_ids[screen.focus_id]
if screen.transition_id then
screen.transition_url = screen.factory_ids[screen.transition_id]
end
if screen.focus_id then
screen.focus_url = screen.factory_ids[screen.focus_id]
end
end
screen.loaded = true
screen.preloaded = false
@ -715,8 +731,8 @@ local function back_out(screen, next_screen, wait_for_transition, cb)
log("back_out()", screen.id)
assert(wait_for_transition ~= nil)
run_coroutine(screen, cb, function()
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen and next_screen.id })
active_transition_count = active_transition_count + 1
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen and next_screen.id })
change_context(screen)
release_input(screen, next_screen)
focus_lost(screen, next_screen)
@ -863,13 +879,10 @@ function M.show(id, options, data, cb)
show_in(screen, top, options and options.reload, add_to_stack, WAIT_FOR_TRANSITION, callbacks.track())
else
-- show screen
local cb = callbacks.track()
show_in(screen, top, options and options.reload, add_to_stack, DO_NOT_WAIT_FOR_TRANSITION, function()
if add_to_stack and top and not top.popup then
show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track())
end
cb()
end)
show_in(screen, top, options and options.reload, add_to_stack, WAIT_FOR_TRANSITION, callbacks.track())
if add_to_stack and top and not top.popup then
show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track())
end
end
callbacks.when_done(function()
@ -912,7 +925,7 @@ function M.hide(id, cb)
log("hide() you can only hide the screen at the top of the stack", id)
return false
end
return M.back(id, cb)
return M.back(nil, nil, cb)
else
log("hide() queuing action", id)
queue_action(function(action_done, action_error)
@ -965,21 +978,27 @@ end
-- Go back to the previous screen in the stack.
-- @param options (table) - Table with options when backing out from the screen (can be nil).
-- Valid values:
-- * sequential - Set to true to wait for the current screen to hide itself out before starting the
-- back in transition even when transitioning to a different scene ID.
-- @param data (*) - Optional data to set for the previous screen
-- @param cb (function) - Optional callback to invoke when the previous screen is visible again
function M.back(data, cb)
function M.back(options, data, cb)
log("back() queuing action")
queue_action(function(action_done)
local callbacks = callback_tracker()
local back_cb = callbacks.track()
local screen = table.remove(stack)
if screen then
log("back()", screen.id)
local top = stack[#stack]
-- if we go back to the same screen we need to first hide it
-- and wait until it is hidden before we show it again
if top and screen.id == top.id then
local same_screen = top and top.id == screen.id
if same_screen or (options and options.sequential) then
local back_cb = callbacks.track()
back_out(screen, top, WAIT_FOR_TRANSITION, function()
if data then
top.data = data
@ -997,16 +1016,16 @@ function M.back(data, cb)
-- we do this to ensure that we do not reset the times step of the screen
-- we go back to until it is no longer obscured by the popup
if screen.popup and not top.popup then
local back_cb = callbacks.track()
back_out(screen, top, WAIT_FOR_TRANSITION, function()
back_in(top, screen, WAIT_FOR_TRANSITION, back_cb)
end)
else
back_in(top, screen, DO_NOT_WAIT_FOR_TRANSITION, function()
back_out(screen, top, WAIT_FOR_TRANSITION, back_cb)
end)
back_in(top, screen, WAIT_FOR_TRANSITION, callbacks.track())
back_out(screen, top, WAIT_FOR_TRANSITION, callbacks.track())
end
else
back_out(screen, top, WAIT_FOR_TRANSITION, back_cb)
back_out(screen, top, WAIT_FOR_TRANSITION, callbacks.track())
end
end
end
@ -1113,6 +1132,20 @@ function M.preload(id, options, cb)
return true -- return true for legacy reasons (before queue existed)
end
--- Check if a screen has missing resources, always returns false for factory
-- @param id (string|hash) - Id of the screen to preload
function M.has_missing_resources(id)
assert(id, "You must provide a screen id")
id = tohash(id)
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
local screen = screens[id]
if screen.proxy then
local missing_resources = collectionproxy.missing_resources(screen.proxy)
return #missing_resources > 0
end
return false
end
--- Unload a preloaded monarch screen
-- @param id (string|hash) - Id of the screen to unload
@ -1164,8 +1197,8 @@ end
-- @return error (string|nil) Error message if unable to send message
function M.post(id, message_id, message)
assert(id, "You must provide a screen id")
if not M.is_visible(id) then
return false, "Unable to post message to screen if it isn't visible"
if not M.is_loaded(id) then
return false, "Unable to post message to screen if it isn't loaded"
end
assert(message_id, "You must provide a message_id")
@ -1317,24 +1350,36 @@ function M.on_focus_changed(id, fn)
end
---
-- Set a function to call when a screen is sent a message using monarch.post()
-- The function will receive (message_id, message, sender)
-- IMPORTANT! You must call monarch.on_message() from the same script as
-- this function was called
-- Set either a function to be called when msg.post() is called on a specific
-- screen or a URL where the message is sent.
-- IMPORTANT! If you provide a function you must also make sure to call
-- monarch.on_message(message_id, message, sender) from the same script as
-- this function was called.
-- @param id Screen id to associate the message listener function with
-- @param fn Message listener function
function M.on_post(id, fn)
-- @param fn_or_url The function to call or URL to send message to
function M.on_post(id, fn_or_url)
assert(id, "You must provide a screen id")
assert(fn, "You must provide a post receiver function")
id = tohash(id)
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
local screen = screens[id]
screen.receiver_url = msg.url()
screen.receiver_fn = fn
local t = type(fn_or_url)
if t == "function" then
screen.receiver_fn = fn_or_url
screen.receiver_url = msg.url()
elseif t == "userdata" or t == "string" then
screen.receiver_fn = nil
screen.receiver_url = fn_or_url
else
screen.receiver_fn = nil
screen.receiver_url = msg.url()
end
end
local empty_hash = hash("")
local function url_to_key(url)
return (url.socket or hash("")) .. (url.path or hash("")) .. (url.fragment or hash(""))
return (url.socket or empty_hash) .. (url.path or empty_hash) .. (url.fragment or empty_hash)
end

2
test.settings Normal file
View File

@ -0,0 +1,2 @@
[bootstrap]
main_collection = /test/test.collectionc

View File

@ -1,5 +1,11 @@
local monarch
function init(self)
print("init - screen1")
monarch = require "monarch.monarch"
print("init - screen1", msg.url())
monarch.on_post("screen1", function(message_id, message, sender)
_G.screen1_on_post = message or true
end)
end
function final(self)
@ -7,7 +13,8 @@ function final(self)
end
function on_message(self, message_id, message, sender)
monarch.on_message(message_id, message, sender)
if message_id == hash("foobar") then
_G.screen1_foobar = message or true
_G.screen1_on_message = message or true
end
end

View File

@ -1,5 +1,11 @@
local monarch
function init(self)
print("init - screen2")
monarch = require "monarch.monarch"
print("init - screen2", msg.url())
monarch.on_post("screen2", function(message_id, message, sender)
_G.screen2_on_post = message or true
end)
end
function final(self)
@ -7,7 +13,8 @@ function final(self)
end
function on_message(self, message_id, message, sender)
monarch.on_message(message_id, message, sender)
if message_id == hash("foobar") then
_G.screen2_foobar = message or true
_G.screen2_on_message = message or true
end
end

View File

@ -64,5 +64,17 @@ function M.last(url)
return messages[#messages]
end
function M.filter(url, fn)
local t = {}
local messages = M.messages(url)
for i=1,#messages do
local message = messages[i]
if fn(message) then
t[#t + 1] = message
end
end
return t
end
return M

View File

@ -12,7 +12,6 @@ local FOCUS1 = hash("focus1")
local BACKGROUND = hash("background")
local POPUP1 = hash("popup1")
local POPUP2 = hash("popup2")
local FOOBAR = hash("foobar")
local TRANSITION1 = hash("transition1")
local function check_stack(expected_screens)
@ -82,7 +81,7 @@ return function()
monarch.when_preloaded(screen_id, done)
end)
end
describe("monarch", function()
before(function()
mock_msg.mock()
@ -143,12 +142,12 @@ return function()
monarch.show(SCREEN1)
assert(wait_until_stack({ SCREEN1 }))
assert(wait_until_visible(SCREEN1))
monarch.show(SCREEN2)
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
assert(wait_until_hidden(SCREEN1))
assert(wait_until_visible(SCREEN2))
monarch.show(POPUP1)
assert(wait_until_stack({ SCREEN1, SCREEN2, POPUP1 }))
assert(wait_until_hidden(SCREEN1))
@ -156,6 +155,17 @@ return function()
assert(wait_until_visible(POPUP1))
end)
it("should be able to tell if a screen is loaded or not", function()
assert(not monarch.is_loaded(SCREEN1))
monarch.show(SCREEN1)
assert(wait_until_visible(SCREEN1))
assert(monarch.is_loaded(SCREEN1))
monarch.hide(SCREEN1)
assert(wait_until_hidden(SCREEN1))
assert(not monarch.is_loaded(SCREEN1))
end)
it("should be able to show a screen without adding it to the stack", function()
monarch.show(BACKGROUND, { no_stack = true })
assert(wait_until_visible(BACKGROUND), "Background was never shown")
@ -220,7 +230,7 @@ return function()
assert(monarch.data(SCREEN2) == data2, "Expected data on screen2 doesn't match actual data")
local data_back = { going = "back" }
monarch.back(data_back)
monarch.back(nil, data_back)
assert(wait_until_visible(SCREEN1))
assert(monarch.data(SCREEN1) == data_back, "Expected data on screen1 doesn't match actual data")
@ -408,43 +418,37 @@ return function()
monarch.show(SCREEN1)
assert(wait_until_not_busy())
assert(mock_msg.messages(URL1)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(mock_msg.messages(URL1)[1].message.screen == SCREEN1)
assert(mock_msg.messages(URL2)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(mock_msg.messages(URL2)[1].message.screen == SCREEN1)
assert(mock_msg.messages(URL1)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(mock_msg.messages(URL1)[2].message.screen == SCREEN1)
assert(mock_msg.messages(URL2)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(mock_msg.messages(URL2)[2].message.screen == SCREEN1)
monarch.remove_listener(URL2)
monarch.show(SCREEN2)
assert(wait_until_not_busy())
assert(#mock_msg.messages(URL1) == 6)
assert(#mock_msg.messages(URL2) == 2)
assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(mock_msg.messages(URL1)[3].message.screen == SCREEN2)
assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(mock_msg.messages(URL1)[4].message.screen == SCREEN2)
assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
assert(mock_msg.messages(URL1)[5].message.screen == SCREEN1)
assert(mock_msg.messages(URL1)[6].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
assert(mock_msg.messages(URL1)[6].message.screen == SCREEN1)
monarch.back()
assert(wait_until_not_busy())
assert(#mock_msg.messages(URL1) == 10)
assert(#mock_msg.messages(URL2) == 2)
assert(mock_msg.messages(URL1)[7].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(mock_msg.messages(URL1)[7].message.screen == SCREEN1)
assert(mock_msg.messages(URL1)[8].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(mock_msg.messages(URL1)[8].message.screen == SCREEN1)
assert(mock_msg.messages(URL1)[9].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
assert(mock_msg.messages(URL1)[9].message.screen == SCREEN2)
assert(mock_msg.messages(URL1)[10].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
assert(mock_msg.messages(URL1)[10].message.screen == SCREEN2)
local messages = mock_msg.filter(URL1, function(m)
return m.message.screen == SCREEN1
end)
assert(messages[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(messages[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(messages[3].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
assert(messages[4].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
assert(messages[5].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(messages[6].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
messages = mock_msg.filter(URL2, function(m)
return m.message.screen == SCREEN1
end)
assert(messages[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(messages[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
messages = mock_msg.filter(URL1, function(m)
return m.message.screen == SCREEN2
end)
assert(messages[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
assert(messages[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
assert(messages[3].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
assert(messages[4].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
end)
it("should be able to show a screen even while it is preloading", function()
@ -491,49 +495,56 @@ return function()
it("should be able to post messages without message data to visible screens", function()
_G.screen1_foobar = nil
_G.screen2_foobar = nil
_G.screen1_on_message = nil
_G.screen1_on_post = nil
_G.screen2_on_message = nil
_G.screen2_on_post = nil
-- proxy screen
monarch.show(SCREEN1)
wait_until_visible(SCREEN1)
assert(monarch.post(SCREEN1, "foobar"), "Expected monarch.post() to return true")
cowait(0.1)
assert(_G.screen1_foobar, "Screen1 never received a message")
assert(_G.screen1_on_message, "Screen1 never received a message")
assert(_G.screen1_on_post, "Screen1 never received a callback")
-- factory screen
monarch.show(SCREEN2)
wait_until_visible(SCREEN2)
assert(monarch.post(SCREEN2, "foobar"), "Expected monarch.post() to return true")
cowait(0.1)
assert(_G.screen2_foobar, "Screen2 never received a message")
assert(_G.screen2_on_message, "Screen2 never received a message")
assert(_G.screen2_on_post, "Screen2 never received a callback")
end)
it("should be able to post messages with message data to visible screens", function()
_G.screen1_foobar = nil
_G.screen2_foobar = nil
_G.screen1_on_message = nil
_G.screen1_on_post = nil
_G.screen2_on_message = nil
_G.screen2_on_post = nil
-- proxy screen
monarch.show(SCREEN1)
wait_until_visible(SCREEN1)
assert(monarch.post(SCREEN1, "foobar", { foo = "bar" }), "Expected monarch.post() to return true")
cowait(0.1)
assert(_G.screen1_foobar, "Screen1 never received a message")
assert(_G.screen1_foobar.foo == "bar", "Screen1 never received message data")
assert(_G.screen1_on_message, "Screen1 never received a message")
assert(_G.screen1_on_message.foo == "bar", "Screen1 never received message data")
-- factory screen
monarch.show(SCREEN2)
wait_until_visible(SCREEN2)
assert(monarch.post(SCREEN2, "foobar", { foo = "bar" }), "Expected monarch.post() to return true")
cowait(0.1)
assert(_G.screen2_foobar, "Screen2 never received a message")
assert(_G.screen2_foobar.foo == "bar", "Screen2 never received message data")
assert(_G.screen2_on_message, "Screen2 never received a message")
assert(_G.screen2_on_message.foo == "bar", "Screen2 never received message data")
end)
it("should not be able to post messages to hidden screens", function()
_G.screen1_foobar = nil
_G.screen1_on_message = nil
_G.screen1_on_post = nil
monarch.show(SCREEN1)
monarch.show(SCREEN2)
@ -542,7 +553,7 @@ return function()
local ok, err = monarch.post(SCREEN1, "foobar")
assert(not ok and err, "Expected monarch.post() to return false plus an error message")
cowait(0.1)
assert(not _G.screen1_foobar, "Screen1 should not have received a message")
assert(not _G.screen1_on_message, "Screen1 should not have received a message")
end)