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
|
bg_texture = nil, -- L.10 loads it
|
||||||
default_teaser_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()
|
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
|
carousel_state = {}, -- per-module-id state, L.5 populates
|
||||||
manifest_cache = {}, -- L.3 populates
|
manifest_cache = {}, -- L.3 populates
|
||||||
launcher_dir = MODULE_DIR, -- L.4: detail.lua dofiles markdown.lua via this
|
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()
|
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 /
|
-- L.7: Conflict-modal takes priority over STATE_LIST input. esc /
|
||||||
-- Cancel close the modal back to STATE_LIST; "Launch anyway" stays
|
-- Cancel close the modal back to STATE_LIST; "Launch anyway" stays
|
||||||
-- a no-op until engine.module.switch_module_supports_fallback ships.
|
-- 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
|
if input.was_action_pressed("ui_back") then
|
||||||
ctx_panels.modal_open = nil
|
|
||||||
state = fsm.next(state, "esc")
|
state = fsm.next(state, "esc")
|
||||||
|
ctx_panels.modal_def = nil
|
||||||
elseif input.was_action_pressed("ui_click") then
|
elseif input.was_action_pressed("ui_click") then
|
||||||
local id = modal_panel.handle_click(ctx_panels.modal_def, mx, my)
|
local id = modal_panel.handle_click(ctx_panels.modal_def, mx, my)
|
||||||
if id == "cancel" then
|
if id == "cancel" then
|
||||||
ctx_panels.modal_open = nil
|
|
||||||
state = fsm.next(state, "cancel")
|
state = fsm.next(state, "cancel")
|
||||||
|
ctx_panels.modal_def = nil
|
||||||
elseif id == "launch_anyway" then
|
elseif id == "launch_anyway" then
|
||||||
local mid = ctx_panels.modal_def.module_id
|
local mid = ctx_panels.modal_def.module_id
|
||||||
ctx_panels.modal_open = nil
|
|
||||||
state = fsm.next(state, "launch_anyway")
|
state = fsm.next(state, "launch_anyway")
|
||||||
|
ctx_panels.modal_def = nil
|
||||||
if engine.module.switch_module_supports_fallback then
|
if engine.module.switch_module_supports_fallback then
|
||||||
engine.switch_module(mid, { mode = "fallback" })
|
engine.switch_module(mid, { mode = "fallback" })
|
||||||
end
|
end
|
||||||
@@ -396,7 +404,7 @@ function render(ctx)
|
|||||||
detail_panel.render(ctx_panels)
|
detail_panel.render(ctx_panels)
|
||||||
|
|
||||||
-- L.7: Conflict modal renders above the panels (backdrop dims them).
|
-- 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)
|
modal_panel.render(ctx_panels.modal_def, screen_w, screen_h)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ function M.handle_click(ctx, mx, my)
|
|||||||
body = {
|
body = {
|
||||||
ctx.t("conflict_body_line1"),
|
ctx.t("conflict_body_line1"),
|
||||||
string.format(ctx.t("conflict_body_line2_fmt"),
|
string.format(ctx.t("conflict_body_line2_fmt"),
|
||||||
r and #r.missing or 0),
|
r and (#(r.errors or {}) + #(r.conflicts or {})) or 0),
|
||||||
},
|
},
|
||||||
buttons = {
|
buttons = {
|
||||||
{ id = "cancel", label = ctx.t("cancel") },
|
{ id = "cancel", label = ctx.t("cancel") },
|
||||||
@@ -164,7 +164,9 @@ function M.handle_click(ctx, mx, my)
|
|||||||
},
|
},
|
||||||
module_id = entry.id,
|
module_id = entry.id,
|
||||||
}
|
}
|
||||||
ctx.modal_open = "conflict"
|
-- C1: signal init.lua to dispatch open_conflict on the FSM
|
||||||
|
-- so state actually transitions into STATE_MODAL_CONFLICT.
|
||||||
|
ctx._pending_modal_open = "conflict"
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user