mirror of
https://github.com/britzl/monarch.git
synced 2025-11-26 19:00:53 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07eacc7a5f | ||
|
|
5ee6ea5982 | ||
|
|
f590c75b9e | ||
|
|
d528947998 | ||
|
|
22f0e6cddf |
26
README.md
26
README.md
@@ -352,16 +352,32 @@ Remove a previously added listener.
|
||||
Enable verbose logging of the internals of Monarch.
|
||||
|
||||
|
||||
### monarch.SCREEN_VISIBLE
|
||||
Message sent to listeners when a screen becomes visible.
|
||||
### monarch.SCREEN_TRANSITION_IN_STARTED
|
||||
Message sent to listeners when a screen has started to transition in.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
* ```previous_screen``` (hash) - Id of theprevious screen (if any)
|
||||
* ```previous_screen``` (hash) - Id of the previous screen (if any)
|
||||
|
||||
|
||||
### monarch.SCREEN_HIDDEN
|
||||
Message sent to listeners when a screen is hidden.
|
||||
### monarch.SCREEN_TRANSITION_IN_FINISHED
|
||||
Message sent to listeners when a screen has finished to transition in.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
* ```previous_screen``` (hash) - Id of the previous screen (if any)
|
||||
|
||||
|
||||
### monarch.SCREEN_TRANSITION_OUT_STARTED
|
||||
Message sent to listeners when a screen has started to transition out.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
* ```next_screen``` (hash) - Id of the next screen (if any)
|
||||
|
||||
|
||||
### monarch.SCREEN_TRANSITION_OUT_FINISHED
|
||||
Message sent to listeners when a screen has finished to transition out.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local callback_tracker = require "monarch.utils.callback_tracker"
|
||||
|
||||
local M = {}
|
||||
|
||||
local CONTEXT = hash("monarch_context")
|
||||
@@ -24,8 +26,10 @@ M.FOCUS.GAINED = hash("monarch_focus_gained")
|
||||
M.FOCUS.LOST = hash("monarch_focus_lost")
|
||||
|
||||
-- listener messages
|
||||
M.SCREEN_VISIBLE = hash("monarch_screen_visible")
|
||||
M.SCREEN_HIDDEN = hash("monarch_screen_hidden")
|
||||
M.SCREEN_TRANSITION_IN_STARTED = hash("monarch_screen_transition_in_started")
|
||||
M.SCREEN_TRANSITION_IN_FINISHED = hash("monarch_screen_transition_in_finished")
|
||||
M.SCREEN_TRANSITION_OUT_STARTED = hash("monarch_screen_transition_out_started")
|
||||
M.SCREEN_TRANSITION_OUT_FINISHED = hash("monarch_screen_transition_out_finished")
|
||||
|
||||
|
||||
-- all registered screens
|
||||
@@ -248,6 +252,7 @@ local function show_out(screen, next_screen, cb)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen.id })
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
release_input(screen)
|
||||
@@ -263,7 +268,7 @@ local function show_out(screen, next_screen, cb)
|
||||
screen.co = nil
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_HIDDEN, { screen = screen.id, next_screen = next_screen.id })
|
||||
notify_listeners(M.SCREEN_TRANSITION_OUT_FINISHED, { screen = screen.id, next_screen = next_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
@@ -273,6 +278,7 @@ local function show_in(screen, previous_screen, reload, cb)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
if reload and screen.loaded then
|
||||
@@ -299,17 +305,17 @@ local function show_in(screen, previous_screen, reload, cb)
|
||||
screen.co = nil
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_VISIBLE, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
notify_listeners(M.SCREEN_TRANSITION_IN_FINISHED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_in(screen, previous_screen, cb)
|
||||
log("back_in()", screen.id)
|
||||
print("back_in()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
if screen.preloaded then
|
||||
@@ -329,16 +335,16 @@ local function back_in(screen, previous_screen, cb)
|
||||
screen.co = nil
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_VISIBLE, { screen = screen.id, previous_screen = previous_screen.id })
|
||||
notify_listeners(M.SCREEN_TRANSITION_IN_FINISHED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_out(screen, next_screen, cb)
|
||||
log("back_out()", screen.id)
|
||||
print("back_out()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
notify_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen.id })
|
||||
active_transition_count = active_transition_count + 1
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
@@ -349,7 +355,7 @@ local function back_out(screen, next_screen, cb)
|
||||
screen.co = nil
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_HIDDEN, { screen = screen.id, next_screen = next_screen and next_screen.id })
|
||||
notify_listeners(M.SCREEN_TRANSITION_OUT_FINISHED, { screen = screen.id, next_screen = next_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
@@ -395,8 +401,11 @@ end
|
||||
function M.show(id, options, data, cb)
|
||||
assert(id, "You must provide a screen id")
|
||||
if M.is_busy() then
|
||||
log("show() monarch is busy, ignoring request")
|
||||
return false
|
||||
end
|
||||
|
||||
local callbacks = callback_tracker()
|
||||
|
||||
id = tohash(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
@@ -418,13 +427,13 @@ function M.show(id, options, data, cb)
|
||||
-- close all popups
|
||||
while top.popup do
|
||||
stack[#stack] = nil
|
||||
show_out(top, screen)
|
||||
show_out(top, screen, callbacks.track())
|
||||
top = stack[#stack]
|
||||
end
|
||||
-- unload and transition out from top
|
||||
-- unless we're showing the same screen as is already visible
|
||||
if top and top.id ~= screen.id then
|
||||
show_out(top, screen)
|
||||
show_out(top, screen, callbacks.track())
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -441,7 +450,9 @@ function M.show(id, options, data, cb)
|
||||
end
|
||||
|
||||
-- show screen
|
||||
show_in(screen, top, options and options.reload, cb)
|
||||
show_in(screen, top, options and options.reload, callbacks.track())
|
||||
|
||||
if cb then callbacks.when_done(cb) end
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -453,9 +464,12 @@ end
|
||||
-- @return true if successfully going back, false if busy performing another operation
|
||||
function M.back(data, cb)
|
||||
if M.is_busy() then
|
||||
log("back() monarch is busy, ignoring request")
|
||||
return false
|
||||
end
|
||||
|
||||
local callbacks = callback_tracker()
|
||||
|
||||
local screen = table.remove(stack)
|
||||
if screen then
|
||||
log("back()", screen.id)
|
||||
@@ -467,7 +481,7 @@ function M.back(data, cb)
|
||||
if data then
|
||||
top.data = data
|
||||
end
|
||||
back_in(top, screen, cb)
|
||||
back_in(top, screen, callbacks.track())
|
||||
end)
|
||||
else
|
||||
back_out(screen, top)
|
||||
@@ -475,12 +489,13 @@ function M.back(data, cb)
|
||||
if data then
|
||||
top.data = data
|
||||
end
|
||||
back_in(top, screen, cb)
|
||||
back_in(top, screen, callbacks.track())
|
||||
end
|
||||
end
|
||||
elseif cb then
|
||||
cb()
|
||||
end
|
||||
|
||||
if cb then callbacks.when_done(cb) end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
39
monarch/utils/callback_tracker.lua
Normal file
39
monarch/utils/callback_tracker.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
local M = {}
|
||||
|
||||
|
||||
function M.create()
|
||||
local instance = {}
|
||||
|
||||
local callback = nil
|
||||
local callback_count = 0
|
||||
|
||||
--- Create a callback function and track when it is done
|
||||
-- @return Callback function
|
||||
function instance.track()
|
||||
callback_count = callback_count + 1
|
||||
return function()
|
||||
callback_count = callback_count - 1
|
||||
if callback_count == 0 and callback then
|
||||
callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Call a function when all callbacks have been triggered
|
||||
-- @param cb Function to call when all
|
||||
function instance.when_done(cb)
|
||||
callback = cb
|
||||
if callback_count == 0 then
|
||||
callback()
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
|
||||
return setmetatable(M, {
|
||||
__call = function(_, ...)
|
||||
return M.create(...)
|
||||
end
|
||||
})
|
||||
@@ -241,8 +241,16 @@ return function()
|
||||
monarch.add_listener(URL2)
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
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(wait_until_not_busy())
|
||||
|
||||
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())
|
||||
@@ -252,15 +260,16 @@ return function()
|
||||
|
||||
local messages_1 = mock_msg.messages(URL1)
|
||||
local messages_2 = mock_msg.messages(URL2)
|
||||
assert(#messages_1 == 5)
|
||||
assert(#messages_2 == 1)
|
||||
assert(messages_2[1].message_id == monarch.SCREEN_VISIBLE and messages_1[1].message.screen == SCREEN1)
|
||||
|
||||
assert(messages_1[1].message_id == monarch.SCREEN_VISIBLE and messages_1[1].message.screen == SCREEN1)
|
||||
assert(messages_1[2].message_id == monarch.SCREEN_HIDDEN and messages_1[2].message.screen == SCREEN1)
|
||||
assert(messages_1[3].message_id == monarch.SCREEN_VISIBLE and messages_1[3].message.screen == SCREEN2)
|
||||
assert(messages_1[4].message_id == monarch.SCREEN_HIDDEN and messages_1[4].message.screen == SCREEN2)
|
||||
assert(messages_1[5].message_id == monarch.SCREEN_VISIBLE and messages_1[5].message.screen == SCREEN1)
|
||||
assert(#mock_msg.messages(URL1) == 10)
|
||||
assert(#mock_msg.messages(URL2) == 2)
|
||||
assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
|
||||
assert(mock_msg.messages(URL1)[3].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[4].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[5].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[6].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[7].message.screen == SCREEN2)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user