Pace IGDB requests; rewrite the new help text
IGDB allows 4 requests a second, and an import searching three entries at once (plus detail lookups) went over it. Every IGDB request now waits at least 300 ms after the last one, and a 429 is retried after 1, 2 and 4 seconds before giving up. The import dialog, ranking editor and their error messages are reworded in plainer language, and talk about "spots" instead of "places". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
62fcf6b45d
commit
1f3fa4fb2b
7 files changed
+60
-37
No files matched your search
+12
-12
@@ -138,7 +138,7 @@ function syncRanks() {
|
||||
function moveTo(it, to, flash = true) {
|
||||
to = Math.round(to);
|
||||
if (!Number.isFinite(to) || to < 1 || to > list.maxItems) {
|
||||
toast(`Pick a place from #1 to #${fmt.format(list.maxItems)}.`, { error: true });
|
||||
toast(`Pick a number from 1 to ${fmt.format(list.maxItems)}.`, { error: true });
|
||||
render();
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ function moveTo(it, to, flash = true) {
|
||||
|
||||
function insertPlace(at) {
|
||||
if (!places.makeRoom(at)) {
|
||||
toast(`No room: this list ends at #${fmt.format(list.maxItems)}. Raise its size in List settings.`, { error: true });
|
||||
toast(`There's no room left. This list stops at #${fmt.format(list.maxItems)}; you can make it bigger in List settings.`, { error: true });
|
||||
return;
|
||||
}
|
||||
render();
|
||||
@@ -180,8 +180,8 @@ async function removeItem(it) {
|
||||
if (places.at.has(r + 1)) {
|
||||
const choice = await chooseDialog({
|
||||
title: `Remove “${it.title}”?`,
|
||||
message: `It's #${r}. Should the entries below it move up, or should #${r} stay empty?`,
|
||||
choices: [{ label: `Leave #${r} empty`, value: "keep" }, { label: "Move them up", value: "close", primary: true }],
|
||||
message: `It's at #${r}. Want everything below it to move up, or keep #${r} open?`,
|
||||
choices: [{ label: `Keep #${r} open`, value: "keep" }, { label: "Move them up", value: "close", primary: true }],
|
||||
});
|
||||
if (!choice) return;
|
||||
keep = choice === "keep";
|
||||
@@ -230,7 +230,7 @@ function itemRow(it) {
|
||||
function buildRow(it) {
|
||||
const input = h("input", {
|
||||
class: "rank-input", type: "text", inputmode: "numeric", autocomplete: "off", value: it.rank,
|
||||
"aria-label": `Place of ${it.title}`, title: "Type a place and press Enter. ↑/↓ go to the next entry; Alt+↑/↓ moves this one.",
|
||||
"aria-label": `Spot for ${it.title}`, title: "Type a number and hit Enter. Alt + arrow keys nudge it up or down.",
|
||||
});
|
||||
const commit = () => {
|
||||
// A redraw detaching the box fires blur; that isn't the owner leaving it.
|
||||
@@ -268,7 +268,7 @@ function buildRow(it) {
|
||||
const menu = h("details", { class: "menu row-menu" },
|
||||
h("summary", { class: "icon-btn", "aria-label": `More for ${it.title}`, title: "More" }, icon("chevron-down")),
|
||||
h("div", { class: "menu-pop" },
|
||||
h("button", { type: "button", onclick: () => insertPlace(it.rank) }, icon("plus"), "Insert an empty place above"),
|
||||
h("button", { type: "button", onclick: () => insertPlace(it.rank) }, icon("plus"), "Open up a spot above"),
|
||||
h("button", { type: "button", onclick: () => moveTo(it, 1) }, icon("chevron-up"), "Move to #1"),
|
||||
h("button", { type: "button", onclick: () => moveTo(it, places.last()) }, icon("chevron-down"), "Move to the end"),
|
||||
canRefresh(it) && h("button", { type: "button", onclick: (e) => refreshOne(it, e.currentTarget) }, icon("refresh"), `Refresh from ${sourceName(it)}`),
|
||||
@@ -305,12 +305,12 @@ function emptyRow(from, to) {
|
||||
const label = n === 1 ? `#${fmt.format(from)}` : `#${fmt.format(from)}–${fmt.format(to)}`;
|
||||
const targeted = addAt >= from && addAt <= to;
|
||||
return h("li", { class: "rank-gap" + (targeted ? " is-target" : ""), "data-place": from, "data-place-end": to },
|
||||
h("span", { class: "rank-gap-label" }, h("b", {}, label), n === 1 ? " Empty place" : ` ${fmt.format(n)} empty places`),
|
||||
h("span", { class: "rank-gap-label" }, h("b", {}, label), n === 1 ? " Open spot" : ` ${fmt.format(n)} open spots`),
|
||||
h("span", { class: "rank-gap-actions" },
|
||||
h("button", { type: "button", class: "btn btn--sm btn--ghost", onclick: () => setAddAt(targeted ? 0 : from) },
|
||||
icon(targeted ? "x" : "plus"), targeted ? "Cancel" : "Add here"),
|
||||
h("button", { type: "button", class: "btn btn--sm btn--ghost", title: "Remove these places; everything below moves up", onclick: () => removePlaces(from, n) },
|
||||
icon("trash"), n === 1 ? "Remove place" : "Remove places"),
|
||||
h("button", { type: "button", class: "btn btn--sm btn--ghost", title: "Close this up; everything below moves up", onclick: () => removePlaces(from, n) },
|
||||
icon("trash"), "Close up"),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -319,7 +319,7 @@ function render(flashId) {
|
||||
syncRanks();
|
||||
const gaps = places.last() - places.at.size;
|
||||
rankTools.hidden = items.length === 0;
|
||||
gapInfo.textContent = gaps ? `${fmt.format(gaps)} empty ${gaps === 1 ? "place" : "places"}` : "No gaps";
|
||||
gapInfo.textContent = gaps ? `${fmt.format(gaps)} open ${gaps === 1 ? "spot" : "spots"}` : "No gaps";
|
||||
closeGapsBtn.hidden = gaps === 0;
|
||||
renderAddTarget();
|
||||
if (!items.length) {
|
||||
@@ -393,7 +393,7 @@ function advanceAddAt(added) {
|
||||
|
||||
const rankTools = h("div", { class: "rank-tools", hidden: true });
|
||||
const gapInfo = h("span", { class: "muted small" });
|
||||
const closeGapsBtn = h("button", { type: "button", class: "btn btn--sm btn--ghost", title: "Number the entries 1, 2, 3… keeping their order", onclick: closeGaps }, "Close gaps");
|
||||
const closeGapsBtn = h("button", { type: "button", class: "btn btn--sm btn--ghost", title: "Renumber everything 1, 2, 3… in the same order", onclick: closeGaps }, "Close gaps");
|
||||
const jump = h("input", { type: "text", inputmode: "numeric", placeholder: "Go to #", "aria-label": "Go to place", class: "rank-jump" });
|
||||
jump.addEventListener("keydown", (e) => {
|
||||
if (e.key !== "Enter") return;
|
||||
@@ -634,7 +634,7 @@ function renderResults(res) {
|
||||
action,
|
||||
);
|
||||
});
|
||||
if (full) nodes.unshift(h("p", { class: "alert alert--warn" }, icon("info"), `This list is full (${fmt.format(list.maxItems)}). Raise its size in List settings to add more.`));
|
||||
if (full) nodes.unshift(h("p", { class: "alert alert--warn" }, icon("info"), `This list is full at ${fmt.format(list.maxItems)}. Make it bigger in List settings to add more.`));
|
||||
results.replaceChildren(...nodes);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user