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

Implement monarch.replace() (#61)

This commit is contained in:
Marius Petcu 2020-05-20 16:36:29 +03:00 committed by GitHub
parent c7fb2ba646
commit 4ad86d41fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 0 deletions

View File

@ -319,6 +319,10 @@ The options table can contain the following fields:
* ```reload``` (boolean) - If the `reload` flag is set Monarch will reload the collection proxy if it's already loaded (this can happen if the previous screen was a popup). * ```reload``` (boolean) - If the `reload` flag is set Monarch will reload the collection proxy if it's already loaded (this can happen if the previous screen was a popup).
* ```no_stack``` (boolean) - If the `no_stack` flag is set Monarch will load the screen without adding it to the screen stack. * ```no_stack``` (boolean) - If the `no_stack` flag is set Monarch will load the screen without adding it to the screen stack.
* ```sequential``` (boolean) - If the `sequential` flag is set Monarch will start loading the screen only after the previous screen finished transitioning out. * ```sequential``` (boolean) - If the `sequential` flag is set Monarch will start loading the screen only after the previous screen finished transitioning out.
* ```pop``` (number) - If `pop` is set to a number, Monarch will pop that number of screens from the stack before adding the new one.
### monarch.replace(screen_id, [options], [data], [callback])
Replace the top of the stack with a new screen. Equivalent to calling `monarch.show()` with `pop = 1`. It takes the same parameters as `monarch.show()`.
### monarch.hide(screen_id, [callback]) ### monarch.hide(screen_id, [callback])

View File

@ -69,6 +69,16 @@ local function pcallfn(fn, ...)
end end
end end
local function assign(to, from)
if not from then
return to
end
for k, v in pairs(from) do
to[k] = v
end
return to
end
local function cowait(delay) local function cowait(delay)
local co = coroutine.running() local co = coroutine.running()
assert(co, "You must run this from within a coroutine") assert(co, "You must run this from within a coroutine")
@ -649,6 +659,8 @@ end
-- This would be the case if doing a show() from a popup on the screen just below the popup. -- This would be the case if doing a show() from a popup on the screen just below the popup.
-- * sequential - Set to true to wait for the previous screen to show itself out before starting the -- * sequential - Set to true to wait for the previous screen to show itself out before starting the
-- show in transition even when transitioning to a different scene ID. -- show in transition even when transitioning to a different scene ID.
-- * no_stack - Set to true to load the screen without adding it to the screen stack.
-- * pop - The number of screens to pop from the stack before adding the new one.
-- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function -- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function
-- @param cb (function) - Optional callback to invoke when screen is shown -- @param cb (function) - Optional callback to invoke when screen is shown
function M.show(id, options, data, cb) function M.show(id, options, data, cb)
@ -712,6 +724,14 @@ function M.show(id, options, data, cb)
end end
end end
if options and options.pop then
for i = 1, options.pop do
local stack_top = #stack
if stack_top < 1 then break end
stack[stack_top] = nil
end
end
-- show screen, wait until preloaded if it is already preloading -- show screen, wait until preloaded if it is already preloading
-- this can typpically happen if you do a show() on app start for a -- this can typpically happen if you do a show() on app start for a
-- screen that has Preload set to true -- screen that has Preload set to true
@ -734,6 +754,20 @@ function M.show(id, options, data, cb)
end end
--- Replace the top of the stack with a new screen
-- @param id (string|hash) - Id of the screen to show
-- @param options (table) - Table with options when showing the screen (can be nil). Valid values:
-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen
-- * reload - Set to true if screen should be reloaded if it already exists in the stack and is loaded.
-- This would be the case if doing a show() from a popup on the screen just below the popup.
-- * no_stack - Set to true to load the screen without adding it to the screen stack.
-- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function
-- @param cb (function) - Optional callback to invoke when screen is shown
function M.replace(id, options, data, cb)
return M.show(id, assign({ pop = 1 }, options), data, cb)
end
-- Hide a screen. The screen must either be at the top of the stack or -- Hide a screen. The screen must either be at the top of the stack or
-- visible but not added to the stack (through the no_stack option) -- visible but not added to the stack (through the no_stack option)
-- @param id (string|hash) - Id of the screen to show -- @param id (string|hash) - Id of the screen to show

View File

@ -133,6 +133,22 @@ return function()
assert_stack({ }) assert_stack({ })
end) end)
it("should be able to replace screens at the top of the stack", function()
monarch.show(SCREEN1_STR)
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
assert_stack({ SCREEN1 })
monarch.show(SCREEN2)
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
assert_stack({ SCREEN1, SCREEN2 })
monarch.replace(SCREEN1)
assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden")
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
assert_stack({ SCREEN1, SCREEN1 })
end)
it("should be able to tell if a screen is visible or not", function() it("should be able to tell if a screen is visible or not", function()
assert(not monarch.is_visible(SCREEN1)) assert(not monarch.is_visible(SCREEN1))
monarch.show(SCREEN1) monarch.show(SCREEN1)
@ -302,6 +318,20 @@ return function()
assert_stack({ SCREEN1, SCREEN2 }) assert_stack({ SCREEN1, SCREEN2 })
end) end)
it("should close any open popups when replacing a non-popup", function()
monarch.show(SCREEN1)
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
assert_stack({ SCREEN1 })
monarch.show(POPUP1)
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
assert_stack({ SCREEN1, POPUP1 })
monarch.show(POPUP2)
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
assert_stack({ SCREEN1, POPUP1, POPUP2 })
monarch.replace(SCREEN2)
assert(wait_until_shown(SCREEN2), "Popup2 was never shown")
assert_stack({ SCREEN2 })
end)
it("should be able to get the id of the screen at the top and bottom of the stack", function() it("should be able to get the id of the screen at the top and bottom of the stack", function()
assert(monarch.top() == nil) assert(monarch.top() == nil)