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

Implement better behaviour for replace() on popups (#64)

This commit is contained in:
Marius Petcu 2020-05-28 18:18:51 +03:00 committed by GitHub
parent 4989939817
commit 00808c0d56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 36 deletions

View File

@ -686,49 +686,61 @@ function M.show(id, options, data, cb)
local top = stack[#stack] local top = stack[#stack]
-- a screen can ignore the stack by setting the no_stack to true -- a screen can ignore the stack by setting the no_stack to true
local add_to_stack = not options or not options.no_stack local add_to_stack = not options or not options.no_stack
if add_to_stack then if add_to_stack and top then
-- manipulate the current top -- manipulate the current top
-- close popup(s) if needed -- close popup(s) if needed
-- transition out -- transition out
if top then local pop = options and options.pop or 0
-- keep top popup visible if new screen can be shown on top of a popup local is_not_popup = not screen.popup
if top.popup and screen.popup_on_popup then local pop_all_popups = is_not_popup -- pop all popups when transitioning screens
disable(top, screen)
else -- keep top popup visible if new screen can be shown on top of a popup
-- close all popups, one by one if top.popup and screen.popup and screen.popup_on_popup then
while top.popup do disable(top, screen)
stack[#stack] = nil else
show_out(top, screen, callbacks.track()) pop_all_popups = true
callbacks.yield_until_done() end
top = stack[#stack]
end -- close popups, one by one, either all of them or the number specified by options.pop
-- unload and transition out from top while top and top.popup do
-- wait until we are done if showing the same screen as is already visible if not pop_all_popups then
local same_screen = top and top.id == screen.id if pop <= 0 then break end
show_out(top, screen, callbacks.track()) pop = pop - 1
if same_screen or (options and options.sequential) then end
callbacks.yield_until_done() stack[#stack] = nil
end show_out(top, screen, callbacks.track())
callbacks.yield_until_done()
top = stack[#stack]
end
-- unload the previous screen and transition out from top
-- wait until we are done if showing the same screen as is already visible
if top and not top.popup then
local same_screen = top and top.id == screen.id
show_out(top, screen, callbacks.track())
if same_screen or (options and options.sequential) then
callbacks.yield_until_done()
end end
end end
end
-- if the screen we want to show is in the stack -- if the screen we want to show is in the stack
-- already and the clear flag is set then we need -- already and the clear flag is set then we need
-- to remove every screen on the stack up until and -- to remove every screen on the stack up until and
-- including the screen itself -- including the screen itself
if options and options.clear then if options and options.clear then
log("show() clearing") log("show() clearing")
while M.in_stack(id) do while M.in_stack(id) do
table.remove(stack) table.remove(stack)
end
end end
end
if options and options.pop then -- pop screens off the stack
for i = 1, options.pop do if is_not_popup then
local stack_top = #stack for i = 1, pop do
if stack_top < 1 then break end local stack_top = #stack
stack[stack_top] = nil if stack_top < 1 then break end
stack[stack_top] = nil
end
end end
end end

View File

@ -329,10 +329,49 @@ return function()
assert(wait_until_shown(POPUP2), "Popup2 was never shown") assert(wait_until_shown(POPUP2), "Popup2 was never shown")
assert_stack({ SCREEN1, POPUP1, POPUP2 }) assert_stack({ SCREEN1, POPUP1, POPUP2 })
monarch.replace(SCREEN2) monarch.replace(SCREEN2)
assert(wait_until_shown(SCREEN2), "Popup2 was never shown") assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
assert_stack({ SCREEN2 }) assert_stack({ SCREEN2 })
end) end)
it("should replace a 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.replace(POPUP2)
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
assert_stack({ SCREEN1, POPUP2 })
end)
it("should replace a pop-up two levels down", 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.show(POPUP2, { pop = 2 })
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
assert_stack({ SCREEN1, POPUP2 })
end)
it("shouldn't over-pop popups", 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, { pop = 10 })
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
assert_stack({ SCREEN1, POPUP2 })
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)
assert(monarch.bottom() == nil) assert(monarch.bottom() == nil)