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

Added is_preloading() and when_loaded()

This commit is contained in:
Björn Ritzl 2019-03-08 10:28:39 +01:00
parent 1bc0ae09ee
commit 57946d27bf
2 changed files with 76 additions and 4 deletions

View File

@ -334,8 +334,26 @@ Preload a Monarch screen. This will load but not enable the screen. This is usef
* ```callback``` (function) - Optional function to call when the screen is preloaded. * ```callback``` (function) - Optional function to call when the screen is preloaded.
### monarch.is_preloading(screen_id)
Check if a Monarch screen is preloading (via monarch.preload() or the Preload screen setting).
**PARAMETERS**
* ```screen_id``` (hash) - Id of the screen to check
**RETURN**
* ```preloading``` (boolean) - True if the screen is preloading.
### monarch.when_preloaded(screen_id, callback)
Invoke a callback when a screen has been preloaded.
**PARAMETERS**
* ```screen_id``` (hash) - Id of the screen to check
* ```callback``` (function) - Function to call when the screen has been preloaded.
### monarch.unload(screen_id, [callback]) ### monarch.unload(screen_id, [callback])
Unload a preloaded Monarch screen. A preloaded screen will automatically get unloaded when hidden, but this function can be useful if a screen has been preloaded and it needs to be unloaded again. Unload a preloaded Monarch screen. A preloaded screen will automatically get unloaded when hidden, but this function can be useful if a screen has been preloaded and it needs to be unloaded again without actually hiding it.
**PARAMETERS** **PARAMETERS**
* ```screen_id``` (hash) - Id of the screen to unload. * ```screen_id``` (hash) - Id of the screen to unload.

View File

@ -140,6 +140,7 @@ local function register(id, settings)
popup = settings and settings.popup, popup = settings and settings.popup,
popup_on_popup = settings and settings.popup_on_popup, popup_on_popup = settings and settings.popup_on_popup,
timestep_below_popup = settings and settings.timestep_below_popup or 1, timestep_below_popup = settings and settings.timestep_below_popup or 1,
preload_listeners = {},
} }
return screens[id] return screens[id]
end end
@ -389,7 +390,6 @@ local function run_coroutine(screen, cb, fn)
fn() fn()
screen.co = nil screen.co = nil
pcallfn(cb) pcallfn(cb)
notify_if_idle()
end) end)
assert(coroutine.resume(co)) assert(coroutine.resume(co))
end end
@ -599,7 +599,15 @@ function M.show(id, options, data, cb)
end end
end end
-- show screen -- show screen, wait until preloaded if it is already preloading
-- this can typpically happen if you do a show() on app start for a
-- screen that has Preload set to true
if M.is_preloading(id) then
M.when_preloaded(id, function()
coroutine.resume(co)
end)
coroutine.yield()
end
show_in(screen, top, options and options.reload, add_to_stack, callbacks.track()) show_in(screen, top, options and options.reload, add_to_stack, callbacks.track())
if cb then callbacks.when_done(cb) end if cb then callbacks.when_done(cb) end
@ -625,6 +633,7 @@ function M.hide(id, cb)
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id))) assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
local screen = screens[id] local screen = screens[id]
log("hide()", screen.id)
if M.in_stack(id) then if M.in_stack(id) then
if not M.is_top(id) then if not M.is_top(id) then
log("hide() you can only hide the screen at the top of the stack", id) log("hide() you can only hide the screen at the top of the stack", id)
@ -684,6 +693,36 @@ function M.back(data, cb)
end end
--- Check if a screen is preloading via monarch.preload() or automatically
-- via the Preload screen option
-- @param id Screen id
-- @return true if preloading
function M.is_preloading(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]
return screen.preloading
end
--- Invoke a callback when a specific screen has been preloaded
-- This is mainly useful on app start when wanting to show a screen that
-- has the Preload flag set (since it will immediately start to load which
-- would prevent a call to monarch.show from having any effect).
function M.when_preloaded(id, cb)
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.preloaded or screen.loaded then
pcallfn(cb, id)
else
screen.preload_listeners[#screen.preload_listeners + 1] = cb
end
end
--- Preload a screen. This will load but not enable and show a screen. Useful for "heavier" screens --- Preload a screen. This will load but not enable and show a screen. Useful for "heavier" screens
-- that you wish to show without any delay. -- that you wish to show without any delay.
-- @param id (string|hash) - Id of the screen to preload -- @param id (string|hash) - Id of the screen to preload
@ -704,14 +743,28 @@ function M.preload(id, cb)
pcallfn(cb) pcallfn(cb)
return true return true
end end
run_coroutine(screen, cb, function()
local function when_preloaded()
-- invoke any listeners added using monarch.when_preloaded()
while #screen.preload_listeners > 0 do
pcallfn(table.remove(screen.preload_listeners), id)
end
-- invoke the normal callback
pcallfn(cb)
end
run_coroutine(screen, when_preloaded, function()
screen.preloading = true
change_context(screen) change_context(screen)
preload(screen) preload(screen)
screen.preloading = false
end) end)
return true return true
end end
--- Unload a preloaded monarch screen
-- @param id (string|hash) - Id of the screen to unload
-- @param cb (function) - Optional callback to invoke when screen is unloaded
function M.unload(id, cb) function M.unload(id, cb)
if M.is_busy() then if M.is_busy() then
log("unload() monarch is busy, ignoring request") log("unload() monarch is busy, ignoring request")
@ -727,6 +780,7 @@ function M.unload(id, cb)
end end
local screen = screens[id] local screen = screens[id]
log("unload()", screen.id)
if not screen.preloaded and not screen.loaded then if not screen.preloaded and not screen.loaded then
log("unload() screen is not loaded", tostring(id)) log("unload() screen is not loaded", tostring(id))
pcallfn(cb) pcallfn(cb)