fix(launcher): wire FSM dispatch + correct conflict-count
The conflict-modal path bypassed the FSM extension landed in L.7: panels/detail.lua set ctx.modal_open directly and init.lua drove modal handling off the side-channel field, so STATE_MODAL_CONFLICT was unreachable at runtime (only the test-lib asserts exercised it). Now detail.lua marks ctx._pending_modal_open and init.lua dispatches the open_conflict event so state actually transitions through the fsm. Modal entry/exit is gated on state == STATE_MODAL_CONFLICT. Also fixes the conflict body line: r.missing doesn't exist on the dep-fetcher result; use #(errors) + #(conflicts) for the count displayed in the modal body.
This commit is contained in:
20
init.lua
20
init.lua
@@ -207,7 +207,6 @@ function init(ctx)
|
||||
bg_texture = nil, -- L.10 loads it
|
||||
default_teaser_texture = nil, -- L.10 loads it
|
||||
t = function(k) return k end, -- L.8 swaps in real t()
|
||||
modal_open = nil, -- L.7 sets to "quit" | "conflict"
|
||||
carousel_state = {}, -- per-module-id state, L.5 populates
|
||||
manifest_cache = {}, -- L.3 populates
|
||||
launcher_dir = MODULE_DIR, -- L.4: detail.lua dofiles markdown.lua via this
|
||||
@@ -340,22 +339,31 @@ function update(ctx, dt)
|
||||
|
||||
local mx, my = engine.input.get_mouse_pos()
|
||||
|
||||
-- C1: detail.lua's launch-button branch signals a conflict via
|
||||
-- ctx._pending_modal_open; dispatch the FSM event here so state
|
||||
-- actually transitions into STATE_MODAL_CONFLICT before the modal
|
||||
-- branch below runs.
|
||||
if ctx_panels._pending_modal_open == "conflict" then
|
||||
state = fsm.next(state, "open_conflict")
|
||||
ctx_panels._pending_modal_open = nil
|
||||
end
|
||||
|
||||
-- L.7: Conflict-modal takes priority over STATE_LIST input. esc /
|
||||
-- Cancel close the modal back to STATE_LIST; "Launch anyway" stays
|
||||
-- a no-op until engine.module.switch_module_supports_fallback ships.
|
||||
if ctx_panels.modal_open == "conflict" then
|
||||
if state == fsm.STATE_MODAL_CONFLICT then
|
||||
if input.was_action_pressed("ui_back") then
|
||||
ctx_panels.modal_open = nil
|
||||
state = fsm.next(state, "esc")
|
||||
ctx_panels.modal_def = nil
|
||||
elseif input.was_action_pressed("ui_click") then
|
||||
local id = modal_panel.handle_click(ctx_panels.modal_def, mx, my)
|
||||
if id == "cancel" then
|
||||
ctx_panels.modal_open = nil
|
||||
state = fsm.next(state, "cancel")
|
||||
ctx_panels.modal_def = nil
|
||||
elseif id == "launch_anyway" then
|
||||
local mid = ctx_panels.modal_def.module_id
|
||||
ctx_panels.modal_open = nil
|
||||
state = fsm.next(state, "launch_anyway")
|
||||
ctx_panels.modal_def = nil
|
||||
if engine.module.switch_module_supports_fallback then
|
||||
engine.switch_module(mid, { mode = "fallback" })
|
||||
end
|
||||
@@ -396,7 +404,7 @@ function render(ctx)
|
||||
detail_panel.render(ctx_panels)
|
||||
|
||||
-- L.7: Conflict modal renders above the panels (backdrop dims them).
|
||||
if ctx_panels.modal_open == "conflict" then
|
||||
if state == fsm.STATE_MODAL_CONFLICT then
|
||||
modal_panel.render(ctx_panels.modal_def, screen_w, screen_h)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user