Files
yinx-cli/lib/ktx2/ui.js
2025-12-16 16:21:26 +08:00

152 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import color from "picocolors";
import { steps } from "./config.js";
import { initKeypress, onKey } from "../keyboard.js";
// 存储结果和状态
let results = [];
let completed = new Set();
let currentStep = 0;
let currentOption = 0;
// 初始化结果
export function initResults() {
results = steps.map(s => s.type === "multiselect" ? [...s.default] : s.default);
completed = new Set();
currentStep = 0;
currentOption = 0;
}
// 渲染导航栏
function renderNav() {
const nav = steps.map((step, i) => {
if (completed.has(i)) {
return color.green(`${step.name}`);
} else if (i === currentStep) {
return color.bgCyan(color.black(` ${step.name} `));
} else {
return color.dim(`${step.name}`);
}
});
return `${nav.join(" ")} ${color.green("✓Submit")}`;
}
// 渲染选项列表
function renderOptions() {
const step = steps[currentStep];
const lines = [];
lines.push(color.cyan(step.message));
lines.push("");
step.options.forEach((opt, i) => {
const isCurrent = i === currentOption;
const isSelected = step.type === "multiselect"
? results[currentStep].includes(opt.value)
: results[currentStep] === opt.value;
let prefix;
if (step.type === "multiselect") {
prefix = isSelected ? color.green("◉ ") : "○ ";
} else {
prefix = isSelected ? color.green("● ") : "○ ";
}
const cursor = isCurrent ? color.cyan(" ") : " ";
const label = isCurrent ? color.cyan(opt.label) : opt.label;
const check = isSelected ? color.green(" ✓") : "";
lines.push(`${cursor}${prefix}${label}${check}`);
if (opt.hint) {
lines.push(` ${color.dim(opt.hint)}`);
}
});
return lines.join("\n");
}
// 渲染整个界面
function render() {
console.clear();
console.log(color.bgCyan(color.black(" KTX2 纹理压缩工具 ")));
console.log("\n" + renderNav());
console.log(color.dim("\n← → 切换步骤 | ↑ ↓ 选择 | Space 选中 | Tab 提交 | Esc 返回\n"));
console.log(renderOptions());
}
// 主交互循环
export async function runInteractive() {
initResults();
initKeypress();
return new Promise((resolve) => {
render();
onKey((str, key) => {
if (!key) return;
const step = steps[currentStep];
const optCount = step.options.length;
if (key.name === "left") {
if (currentStep > 0) {
currentStep--;
currentOption = 0;
}
render();
} else if (key.name === "right") {
if (currentStep < steps.length - 1) {
currentStep++;
currentOption = 0;
}
render();
} else if (key.name === "up") {
currentOption = (currentOption - 1 + optCount) % optCount;
render();
} else if (key.name === "down") {
currentOption = (currentOption + 1) % optCount;
render();
} else if (key.name === "space") {
const opt = step.options[currentOption];
if (step.type === "multiselect") {
const idx = results[currentStep].indexOf(opt.value);
if (idx >= 0) {
results[currentStep].splice(idx, 1);
} else {
results[currentStep].push(opt.value);
}
} else {
results[currentStep] = opt.value;
}
completed.add(currentStep);
render();
} else if (key.name === "return") {
if (step.type === "select") {
results[currentStep] = step.options[currentOption].value;
}
completed.add(currentStep);
if (currentStep < steps.length - 1) {
currentStep++;
currentOption = 0;
}
render();
} else if (key.name === "tab") {
resolve(results);
} else if (key.name === "escape" || (key.ctrl && key.name === "c")) {
resolve(null);
}
});
});
}
// 显示配置摘要
export function showSummary(config) {
console.clear();
console.log(color.bgCyan(color.black(" KTX2 纹理压缩工具 ")));
console.log("\n" + color.green("配置完成!当前设置:"));
console.log(` 文件格式: ${config.exts.join(", ")}`);
console.log(` 压缩程度: ${config.quality}`);
console.log(` 编码格式: ${config.encoding}`);
console.log(` Mipmap: ${config.mipmap}`);
console.log(` 输出选项: ${config.outputOpts.join(", ")}\n`);
}