151 lines
4.9 KiB
JavaScript
151 lines
4.9 KiB
JavaScript
import { builds, callModes, makeRecipe, toolSteps } from "./model.js";
|
|
|
|
const buildSelect = document.getElementById("build-select");
|
|
const modeSelect = document.getElementById("mode-select");
|
|
let currentBuild = "flash";
|
|
let currentStep = 0;
|
|
let currentPart = "startup";
|
|
|
|
function renderBuild() {
|
|
const selected = builds[currentBuild];
|
|
const flow = document.getElementById("build-flow");
|
|
flow.replaceChildren();
|
|
selected.flow.forEach((label, index) => {
|
|
if (index) {
|
|
const arrow = document.createElement("b");
|
|
arrow.textContent = "→";
|
|
arrow.setAttribute("aria-hidden", "true");
|
|
flow.append(arrow);
|
|
}
|
|
const node = document.createElement("span");
|
|
node.textContent = label;
|
|
flow.append(node);
|
|
});
|
|
document.getElementById("build-detail").textContent = selected.detail;
|
|
document.querySelectorAll("[data-build]").forEach((button) => {
|
|
button.setAttribute(
|
|
"aria-pressed",
|
|
String(button.dataset.build === currentBuild),
|
|
);
|
|
});
|
|
buildSelect.value = currentBuild;
|
|
const previousMode = modeSelect.value;
|
|
modeSelect.replaceChildren();
|
|
for (const key of selected.modes) {
|
|
const option = document.createElement("option");
|
|
option.value = key;
|
|
option.textContent = callModes[key].title;
|
|
modeSelect.append(option);
|
|
}
|
|
modeSelect.value = selected.modes.includes(previousMode)
|
|
? previousMode
|
|
: selected.modes[0];
|
|
renderRecipe();
|
|
}
|
|
|
|
function renderRecipe() {
|
|
const mode = callModes[modeSelect.value];
|
|
document.getElementById("endpoint-kind").textContent = mode.kind;
|
|
document.getElementById("endpoint-value").textContent = mode.endpoint;
|
|
document.getElementById("endpoint-detail").textContent = mode.detail;
|
|
document.getElementById("recipe-label").textContent =
|
|
`${builds[currentBuild].title} · ${mode.title}`;
|
|
document.getElementById("call-recipe").textContent = makeRecipe(
|
|
currentBuild,
|
|
modeSelect.value,
|
|
)[currentPart];
|
|
document.querySelectorAll("[data-part]").forEach((button) => {
|
|
button.setAttribute(
|
|
"aria-pressed",
|
|
String(button.dataset.part === currentPart),
|
|
);
|
|
});
|
|
document.getElementById("copy-status").textContent = "";
|
|
}
|
|
|
|
function renderStep() {
|
|
const selected = toolSteps[currentStep];
|
|
document.getElementById("step-number").textContent = String(
|
|
currentStep + 1,
|
|
).padStart(2, "0");
|
|
document.getElementById("step-title").textContent = selected.title;
|
|
document.getElementById("step-explanation").textContent =
|
|
selected.explanation;
|
|
document.getElementById("step-code").textContent = selected.code;
|
|
document.getElementById("step-progress").textContent =
|
|
`${currentStep + 1} / ${toolSteps.length}`;
|
|
document.getElementById("previous-step").disabled = currentStep === 0;
|
|
document.getElementById("next-step").disabled =
|
|
currentStep === toolSteps.length - 1;
|
|
document.querySelectorAll("[data-step]").forEach((button) => {
|
|
button.setAttribute(
|
|
"aria-pressed",
|
|
String(Number(button.dataset.step) === currentStep),
|
|
);
|
|
});
|
|
}
|
|
|
|
const stepList = document.getElementById("tool-steps");
|
|
toolSteps.forEach((step, index) => {
|
|
const button = document.createElement("button");
|
|
button.type = "button";
|
|
button.dataset.step = String(index);
|
|
button.textContent = `${index + 1} ${step.title}`;
|
|
button.addEventListener("click", () => {
|
|
currentStep = index;
|
|
renderStep();
|
|
});
|
|
stepList.append(button);
|
|
});
|
|
|
|
document.querySelectorAll("[data-build]").forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
currentBuild = button.dataset.build;
|
|
renderBuild();
|
|
});
|
|
});
|
|
buildSelect.addEventListener("change", () => {
|
|
currentBuild = buildSelect.value;
|
|
renderBuild();
|
|
});
|
|
modeSelect.addEventListener("change", renderRecipe);
|
|
document.querySelectorAll("[data-part]").forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
currentPart = button.dataset.part;
|
|
renderRecipe();
|
|
});
|
|
});
|
|
document.getElementById("previous-step").addEventListener("click", () => {
|
|
currentStep -= 1;
|
|
renderStep();
|
|
});
|
|
document.getElementById("next-step").addEventListener("click", () => {
|
|
currentStep += 1;
|
|
renderStep();
|
|
});
|
|
document.getElementById("copy-recipe").addEventListener("click", async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(
|
|
document.getElementById("call-recipe").textContent,
|
|
);
|
|
document.getElementById("copy-status").textContent = "已复制调用示例。";
|
|
} catch {
|
|
document.getElementById("copy-status").textContent =
|
|
"可以在上方代码中手动选择并复制。";
|
|
}
|
|
});
|
|
|
|
const themeButton = document.getElementById("theme-toggle");
|
|
themeButton.addEventListener("click", () => {
|
|
const theme =
|
|
document.documentElement.dataset.theme === "dark" ? "light" : "dark";
|
|
document.documentElement.dataset.theme = theme;
|
|
themeButton.setAttribute(
|
|
"aria-label",
|
|
theme === "dark" ? "切换浅色主题" : "切换深色主题",
|
|
);
|
|
});
|
|
|
|
renderBuild();
|
|
renderStep();
|