2 Commits

Author SHA1 Message Date
Calic
57a9a42054 fix(launcher): localize image-missing placeholder + drop dead icons.lua
- markdown.lua: M.render now accepts an optional `t` 6th arg (ctx.t).
  When present, the image-missing fallback string is looked up via the
  new `image_missing_fmt` key in strings.lua. Callers without t (the
  launcher-test bytecopy) get the hardcoded English string verbatim,
  matching previous behavior.
- panels/detail.lua: both md.render call sites now thread ctx.t through.
- strings.lua: add image_missing_fmt = "[image missing: %s]".
- icons.lua: deleted. The v0.2.0 status-glyph helper was replaced by
  dep_glyph_* string keys in v0.3.0; grep confirmed no remaining refs.
- manifest.module: bump 0.3.2 -> 0.3.3.
2026-06-11 10:22:29 +02:00
Calic
2595759b3e feat(launcher): ship default brand assets
Solid-fill placeholders for the empty-state background (1920×1080) and
the zero-teaser hero fallback (800×450). Brand-refresh slice can drop
both files in without touching code. Loaded once on init via
engine.asset.load_texture (launcher's own sandbox).
2026-06-11 08:10:01 +02:00
8 changed files with 24 additions and 91 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,84 +0,0 @@
-- icons.lua — inline status-icon primitives for the launcher.
--
-- The engine ships text + rect bindings; no sprites, no draw_circle yet,
-- so every icon is composed from draw_rect + draw_text. Each helper
-- returns the rect it occupied so the caller can stash it for hit-tests
-- (tooltip + update-badge click).
local M = {}
M.SPINNER_COLOR = 0xC0C0C0FF
M.WARN_COLOR = 0xFFD000FF
M.UPDATE_COLOR = 0x4090FFFF
M.ERROR_COLOR = 0xFF4040FF
M.LOCAL_COLOR = 0x707070FF -- muted gray for "local-only" repos
M.ICON_W = 16
M.ICON_H = 16
local SPINNER_GLYPHS = { "|", "/", "-", "\\" }
-- Spinner: rotating ASCII glyph cycled at ~7.5 Hz at 60 fps (every 8
-- frames). Returns its bounding rect so the caller can hit-test for
-- tooltip ("checking for updates...").
function M.draw_spinner(x, y, frame)
local glyph = SPINNER_GLYPHS[(math.floor(frame / 8) % 4) + 1]
engine.render.draw_text(glyph, x + 4, y, 12, M.SPINNER_COLOR)
return { x = x, y = y, w = M.ICON_W, h = M.ICON_H }
end
-- Warn: yellow square with "!" centered.
function M.draw_warn(x, y)
engine.render.draw_rect(x, y, M.ICON_W, M.ICON_H, M.WARN_COLOR)
engine.render.draw_text("!", x + 5, y, 14, 0x000000FF)
return { x = x, y = y, w = M.ICON_W, h = M.ICON_H }
end
-- Update badge: blue pill "^v0.5.5". Width depends on the version
-- string; returned rect carries the dynamic width so callers can do
-- right-to-left layout and click-hit-tests.
function M.draw_update_badge(x, y, version_str)
local label = "^" .. version_str
local tw, _ = engine.render.measure_text(label, 12)
local w = tw + 10
engine.render.draw_rect(x, y, w, M.ICON_H, M.UPDATE_COLOR)
engine.render.draw_text(label, x + 5, y + 1, 12, 0xFFFFFFFF)
return { x = x, y = y, w = w, h = M.ICON_H }
end
-- Error: red square with white "!" — same shape as warn but different
-- color so colorblind users still see the shape difference via the
-- background tint contrast.
function M.draw_error(x, y)
engine.render.draw_rect(x, y, M.ICON_W, M.ICON_H, M.ERROR_COLOR)
engine.render.draw_text("!", x + 5, y, 14, 0xFFFFFFFF)
return { x = x, y = y, w = M.ICON_W, h = M.ICON_H }
end
-- Local-only: muted-gray pill with "L" — module exists in the local
-- install but the remote returns 404 even with credentials, so the
-- update channel doesn't apply. Informational, not a warning.
function M.draw_local(x, y)
engine.render.draw_rect(x, y, M.ICON_W, M.ICON_H, M.LOCAL_COLOR)
engine.render.draw_text("L", x + 5, y, 12, 0xFFFFFFFF)
return { x = x, y = y, w = M.ICON_W, h = M.ICON_H }
end
-- Tooltip: small dark panel anchored to the right of (mx, my).
-- Centered vertically on the cursor. Clamped to screen via the
-- screen-size args.
function M.draw_tooltip(mx, my, text, screen_w, screen_h)
if not text or text == "" then return end
local tw, th = engine.render.measure_text(text, 12)
local pad_x, pad_y = 6, 3
local w, h = tw + 2 * pad_x, th + 2 * pad_y
local x = mx + 14
local y = my - h / 2
if x + w > screen_w then x = mx - w - 8 end
if y < 0 then y = 0 end
if y + h > screen_h then y = screen_h - h end
engine.render.draw_rect(x, y, w, h, 0x202020E0)
engine.render.draw_text(text, x + pad_x, y + pad_y, 12, 0xFFFFFFFF)
end
return M

View File

@@ -203,14 +203,22 @@ function init(ctx)
list_tint = nil, -- nil | "warn" | "error" — set in L.4
list_panel_rect = nil, -- set below from window size
detail_panel_rect = nil,
bg_texture = nil, -- L.10 loads it
default_teaser_texture = nil, -- L.10 loads it
bg_texture = nil, -- assigned below from engine.asset.load_texture
default_teaser_texture = nil, -- assigned below from engine.asset.load_texture
t = nil, -- L.8: real implementation installed below
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
}
-- L.10: launcher-owned brand assets. Solid-fill placeholders today;
-- a brand-refresh slice can drop new PNGs in without touching code.
-- Loaded via engine.asset (the launcher's own sandbox-rooted loader),
-- not engine.module.load_texture — assets/launcher/ lives inside the
-- launcher's module dir.
ctx_panels.bg_texture = engine.asset.load_texture("assets/launcher/background.png")
ctx_panels.default_teaser_texture = engine.asset.load_texture("assets/launcher/default_teaser.png")
-- L.8: real string indirection. Looks up `key` in strings.lua, falls
-- back to "[key]" for missing entries, and string.formats with any
-- varargs so callers can pass format-args inline (e.g. counts).

View File

@@ -1,6 +1,6 @@
{
"id": "lib-management.launcher",
"version": "0.3.1",
"version": "0.3.3",
"kind": "module",
"api": "^0.1",
"ci_frames": 10,

View File

@@ -176,7 +176,11 @@ local function render_spans(spans, x, y, max_w, size)
return cur_y + line_h
end
function M.render(blocks, x, y, max_w, module_id_for_imgs)
-- `t` (optional, 6th arg) is the launcher's ctx.t string-lookup function.
-- When present, M.render uses it to localize the image-missing placeholder
-- via the `image_missing_fmt` key. Callers that don't have a t (e.g. tests)
-- may pass nil; the hardcoded English fallback then renders verbatim.
function M.render(blocks, x, y, max_w, module_id_for_imgs, t)
local cur_y = y
for _, b in ipairs(blocks) do
if b.type == "h1" then
@@ -216,7 +220,9 @@ function M.render(blocks, x, y, max_w, module_id_for_imgs)
-- assume a 16:9 max_w-wide image for layout.
cur_y = cur_y + math.floor(max_w * 9 / 16) + PARA_GAP
else
engine.render.draw_text("[image missing: " .. b.src .. "]",
local missing_text = t and t("image_missing_fmt", b.src)
or ("[image missing: " .. b.src .. "]")
engine.render.draw_text(missing_text,
x, cur_y, BODY_SIZE, COLOR_DIM)
local _, h = engine.render.measure_text("[image]", BODY_SIZE)
cur_y = cur_y + h + PARA_GAP

View File

@@ -50,7 +50,7 @@ function M.render(ctx)
if ctx.selected_entry == "news" then
ensure_md(ctx.launcher_dir)
local body = ctx.news_body_blocks or {}
md.render(body, p.x + PADDING, p.y + PADDING, p.w - 2 * PADDING, nil)
md.render(body, p.x + PADDING, p.y + PADDING, p.w - 2 * PADDING, nil, ctx.t)
return
end
@@ -84,7 +84,7 @@ function M.render(ctx)
-- Description (rendered MD).
ensure_md(ctx.launcher_dir)
cur_y = md.render(mc.blocks, p.x + PADDING, cur_y,
p.w - 2 * PADDING, entry.id)
p.w - 2 * PADDING, entry.id, ctx.t)
cur_y = cur_y + 12

View File

@@ -22,4 +22,7 @@ return {
no = "No",
-- News entry default title
news_default_title = "News",
-- Markdown image-missing placeholder (rendered by markdown.lua when
-- engine.module.load_texture returns nil for an inline image source).
image_missing_fmt = "[image missing: %s]",
}