ui: drop fork tracking for new games; fix stale fork badge
New games have no reference line to return to, so rewinding to fix a finger-slip no longer shows a 'forked' badge — corrections just overwrite silently. Loaded games (built-in / uploaded / saved) keep 'Reset to original', but the badge now reads 'Modified from original' (no move number), which fixes the stale-fork-point bug: the indicator stayed pinned to the first divergence and ignored later rewinds. Resettable correctly across any number of rewinds now.
This commit is contained in:
parent
1d9f9459df
commit
85640e6f8d
@ -10,8 +10,8 @@
|
|||||||
let playTimer = null;
|
let playTimer = null;
|
||||||
let pressureMode = "equal"; // "equal" or "weighted"
|
let pressureMode = "equal"; // "equal" or "weighted"
|
||||||
let board = null;
|
let board = null;
|
||||||
let forkPoint = null; // index where fork happened, null if on original line
|
let hasReference = false; // true for loaded games (built-in/upload/saved) that can be reset
|
||||||
let originalData = null; // saved original game before fork
|
let originalData = null; // pristine copy of a reference game, captured on first edit
|
||||||
let showPieces = true;
|
let showPieces = true;
|
||||||
let showBoard = false;
|
let showBoard = false;
|
||||||
let selectedSquare = null; // tap-to-move: currently selected source square
|
let selectedSquare = null; // tap-to-move: currently selected source square
|
||||||
@ -144,10 +144,11 @@
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return; // illegal move — ignore
|
return; // illegal move — ignore
|
||||||
}
|
}
|
||||||
// First divergence from the originally-loaded line: snapshot it so "Reset to original" works.
|
// For reference games (built-in/upload/saved), snapshot the pristine line the
|
||||||
if (forkPoint === null && currentIndex < gameData.frames.length - 1) {
|
// first time the user diverges from it, so "Reset to original" works. New games
|
||||||
|
// have no reference — corrections just overwrite, with no fork UI.
|
||||||
|
if (hasReference && originalData === null && currentIndex < gameData.frames.length - 1) {
|
||||||
originalData = JSON.parse(JSON.stringify(gameData));
|
originalData = JSON.parse(JSON.stringify(gameData));
|
||||||
forkPoint = currentIndex;
|
|
||||||
}
|
}
|
||||||
// Always overwrite any continuation past the current point, so rewinding and
|
// Always overwrite any continuation past the current point, so rewinding and
|
||||||
// playing a different move replaces the old line instead of appending to it.
|
// playing a different move replaces the old line instead of appending to it.
|
||||||
@ -173,13 +174,11 @@
|
|||||||
const b = gameData.moves[i + 1];
|
const b = gameData.moves[i + 1];
|
||||||
const wClass = currentIndex === i + 1 ? "active" : "";
|
const wClass = currentIndex === i + 1 ? "active" : "";
|
||||||
const bClass = b && currentIndex === i + 2 ? "active" : "";
|
const bClass = b && currentIndex === i + 2 ? "active" : "";
|
||||||
const wForked = forkPoint !== null && i >= forkPoint ? " forked" : "";
|
|
||||||
const bForked = forkPoint !== null && i + 1 >= forkPoint ? " forked" : "";
|
|
||||||
html += `<div class="move-row">`;
|
html += `<div class="move-row">`;
|
||||||
html += `<span class="move-num">${num}.</span>`;
|
html += `<span class="move-num">${num}.</span>`;
|
||||||
html += `<span class="move${wClass ? " " + wClass : ""}${wForked}" data-idx="${i + 1}">${w.san}</span>`;
|
html += `<span class="move${wClass ? " " + wClass : ""}" data-idx="${i + 1}">${w.san}</span>`;
|
||||||
if (b) {
|
if (b) {
|
||||||
html += `<span class="move${bClass ? " " + bClass : ""}${bForked}" data-idx="${i + 2}">${b.san}</span>`;
|
html += `<span class="move${bClass ? " " + bClass : ""}" data-idx="${i + 2}">${b.san}</span>`;
|
||||||
}
|
}
|
||||||
html += `</div>`;
|
html += `</div>`;
|
||||||
}
|
}
|
||||||
@ -294,20 +293,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateForkUI() {
|
function updateForkUI() {
|
||||||
const el = document.getElementById("fork-controls");
|
document.getElementById("fork-controls").style.display = originalData ? "flex" : "none";
|
||||||
if (forkPoint !== null) {
|
|
||||||
el.style.display = "flex";
|
|
||||||
document.getElementById("fork-point").textContent = Math.floor(forkPoint / 2) + 1;
|
|
||||||
} else {
|
|
||||||
el.style.display = "none";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetFork() {
|
function resetFork() {
|
||||||
if (!originalData) return;
|
if (!originalData) return;
|
||||||
gameData = originalData;
|
gameData = originalData;
|
||||||
originalData = null;
|
originalData = null; // back on the pristine reference; still resettable after future edits
|
||||||
forkPoint = null;
|
|
||||||
goTo(0);
|
goTo(0);
|
||||||
updateForkUI();
|
updateForkUI();
|
||||||
}
|
}
|
||||||
@ -329,9 +321,9 @@
|
|||||||
localStorage.setItem(SAVED_KEY, JSON.stringify(list));
|
localStorage.setItem(SAVED_KEY, JSON.stringify(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyParsed(parsed, savedId) {
|
function applyParsed(parsed, savedId, isReference) {
|
||||||
gameData = parsed;
|
gameData = parsed;
|
||||||
forkPoint = null;
|
hasReference = !!isReference;
|
||||||
originalData = null;
|
originalData = null;
|
||||||
currentSavedId = savedId || null;
|
currentSavedId = savedId || null;
|
||||||
currentIndex = 0;
|
currentIndex = 0;
|
||||||
@ -345,7 +337,7 @@
|
|||||||
function loadGame(gameId) {
|
function loadGame(gameId) {
|
||||||
const g = BUILTIN_GAMES.find((x) => x.id === gameId);
|
const g = BUILTIN_GAMES.find((x) => x.id === gameId);
|
||||||
if (!g) return;
|
if (!g) return;
|
||||||
applyParsed(ChessPressure.parsePgn(g.pgn), null);
|
applyParsed(ChessPressure.parsePgn(g.pgn), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSaved(savedId) {
|
function loadSaved(savedId) {
|
||||||
@ -358,10 +350,12 @@
|
|||||||
alert("That saved game could not be loaded (corrupted PGN).");
|
alert("That saved game could not be loaded (corrupted PGN).");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyParsed(parsed, savedId);
|
applyParsed(parsed, savedId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPGN(pgn) {
|
// isReference defaults true (uploaded games are resettable); new games pass false.
|
||||||
|
function loadPGN(pgn, isReference) {
|
||||||
|
if (isReference === undefined) isReference = true;
|
||||||
let parsed;
|
let parsed;
|
||||||
try {
|
try {
|
||||||
parsed = ChessPressure.parsePgn(pgn);
|
parsed = ChessPressure.parsePgn(pgn);
|
||||||
@ -369,7 +363,7 @@
|
|||||||
alert("Could not parse PGN — please check the format and try again.");
|
alert("Could not parse PGN — please check the format and try again.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyParsed(parsed, null);
|
applyParsed(parsed, null, isReference);
|
||||||
document.getElementById("game-select").value = "";
|
document.getElementById("game-select").value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +488,7 @@
|
|||||||
populateGameSelect();
|
populateGameSelect();
|
||||||
|
|
||||||
// Start on a fresh game so the player can begin immediately.
|
// Start on a fresh game so the player can begin immediately.
|
||||||
loadPGN(NEW_GAME_PGN);
|
loadPGN(NEW_GAME_PGN, false);
|
||||||
select.value = "__new";
|
select.value = "__new";
|
||||||
|
|
||||||
// Show board after first render (prevents tan flash)
|
// Show board after first render (prevents tan flash)
|
||||||
@ -504,7 +498,7 @@
|
|||||||
select.addEventListener("change", (e) => {
|
select.addEventListener("change", (e) => {
|
||||||
const v = e.target.value;
|
const v = e.target.value;
|
||||||
if (v === "__new") {
|
if (v === "__new") {
|
||||||
loadPGN(NEW_GAME_PGN);
|
loadPGN(NEW_GAME_PGN, false);
|
||||||
} else if (v.startsWith("saved:")) {
|
} else if (v.startsWith("saved:")) {
|
||||||
loadSaved(v.slice(6));
|
loadSaved(v.slice(6));
|
||||||
} else if (v) {
|
} else if (v) {
|
||||||
|
|||||||
@ -71,7 +71,7 @@
|
|||||||
<div class="move-list" id="move-list"></div>
|
<div class="move-list" id="move-list"></div>
|
||||||
|
|
||||||
<div class="fork-controls" id="fork-controls" style="display:none">
|
<div class="fork-controls" id="fork-controls" style="display:none">
|
||||||
<span class="fork-badge">Forked at move <span id="fork-point"></span></span>
|
<span class="fork-badge">Modified from original</span>
|
||||||
<button id="btn-reset-fork">Reset to original</button>
|
<button id="btn-reset-fork">Reset to original</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -278,7 +278,6 @@ main {
|
|||||||
}
|
}
|
||||||
.move:hover { background: var(--move-bg); }
|
.move:hover { background: var(--move-bg); }
|
||||||
.move.active { background: var(--move-active); font-weight: 600; }
|
.move.active { background: var(--move-active); font-weight: 600; }
|
||||||
.move.forked { border-left: 2px solid var(--fork-color); }
|
|
||||||
|
|
||||||
/* --- Fork controls --- */
|
/* --- Fork controls --- */
|
||||||
.fork-controls {
|
.fork-controls {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user