feat: set White/Black names in the Save dialog too
Mirrors the Export PGN dialog: Save now has White/Black fields (pre-filled, placeholders blank) and writes the names back to headers + on-screen info, so a saved game stores real player names instead of You/Opponent. Shared prefill/ write-back helpers between the two dialogs. Bump cache version.
This commit is contained in:
parent
3974c9faab
commit
98f423b794
@ -423,6 +423,21 @@
|
|||||||
return g ? g.name : null;
|
return g ? g.name : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Player-name fields shared by the Save and Export dialogs. Pre-fill treats
|
||||||
|
// PGN placeholders ("?") as blank; write-back updates headers + on-screen info.
|
||||||
|
const cleanHeader = (v) => (v && v !== "?" && v !== "????.??.??" ? v : "");
|
||||||
|
|
||||||
|
function prefillPlayerInputs(whiteEl, blackEl) {
|
||||||
|
whiteEl.value = cleanHeader(gameData.headers.White);
|
||||||
|
blackEl.value = cleanHeader(gameData.headers.Black);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPlayerInputs(whiteEl, blackEl) {
|
||||||
|
gameData.headers.White = whiteEl.value.trim() || "White";
|
||||||
|
gameData.headers.Black = blackEl.value.trim() || "Black";
|
||||||
|
updateGameInfo();
|
||||||
|
}
|
||||||
|
|
||||||
// Promise-based in-app modal. Native prompt()/confirm() are unreliable here —
|
// Promise-based in-app modal. Native prompt()/confirm() are unreliable here —
|
||||||
// browsers suppress them when the page isn't the active tab — so all save/delete
|
// browsers suppress them when the page isn't the active tab — so all save/delete
|
||||||
// prompts go through a real <dialog>. Resolves to true (OK) or false (cancel/Esc).
|
// prompts go through a real <dialog>. Resolves to true (OK) or false (cancel/Esc).
|
||||||
@ -485,7 +500,10 @@
|
|||||||
const dlg = document.getElementById("save-dialog");
|
const dlg = document.getElementById("save-dialog");
|
||||||
const input = document.getElementById("save-name");
|
const input = document.getElementById("save-name");
|
||||||
const note = document.getElementById("save-note");
|
const note = document.getElementById("save-note");
|
||||||
|
const whiteEl = document.getElementById("save-white");
|
||||||
|
const blackEl = document.getElementById("save-black");
|
||||||
input.value = currentSavedName() || defaultGameName();
|
input.value = currentSavedName() || defaultGameName();
|
||||||
|
prefillPlayerInputs(whiteEl, blackEl);
|
||||||
|
|
||||||
// Live "this overwrites" warning, so clicking Save IS the confirmation.
|
// Live "this overwrites" warning, so clicking Save IS the confirmation.
|
||||||
const refreshNote = () => {
|
const refreshNote = () => {
|
||||||
@ -504,6 +522,8 @@
|
|||||||
const name = input.value.trim();
|
const name = input.value.trim();
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
|
|
||||||
|
applyPlayerInputs(whiteEl, blackEl);
|
||||||
|
|
||||||
// Replace any same-named game (case-insensitive); also collapses old duplicates.
|
// Replace any same-named game (case-insensitive); also collapses old duplicates.
|
||||||
const key = name.toLowerCase();
|
const key = name.toLowerCase();
|
||||||
const saved = getSavedGames().filter((g) => g.name.toLowerCase() !== key);
|
const saved = getSavedGames().filter((g) => g.name.toLowerCase() !== key);
|
||||||
@ -535,22 +555,16 @@
|
|||||||
async function exportPGN() {
|
async function exportPGN() {
|
||||||
if (!gameData) return;
|
if (!gameData) return;
|
||||||
|
|
||||||
// Let the user set player names before download; pre-fill from headers,
|
// Let the user set player names before download (shared with the Save dialog).
|
||||||
// treating placeholders ("?") as blank. Names are written back so they show
|
|
||||||
// on screen and persist on Save too.
|
|
||||||
const whiteEl = document.getElementById("pgn-white");
|
const whiteEl = document.getElementById("pgn-white");
|
||||||
const blackEl = document.getElementById("pgn-black");
|
const blackEl = document.getElementById("pgn-black");
|
||||||
const real = (v) => (v && v !== "?" && v !== "????.??.??" ? v : "");
|
prefillPlayerInputs(whiteEl, blackEl);
|
||||||
whiteEl.value = real(gameData.headers.White);
|
|
||||||
blackEl.value = real(gameData.headers.Black);
|
|
||||||
setTimeout(() => { whiteEl.focus(); whiteEl.select(); }, 0);
|
setTimeout(() => { whiteEl.focus(); whiteEl.select(); }, 0);
|
||||||
|
|
||||||
const ok = await openModal(document.getElementById("export-pgn-dialog"));
|
const ok = await openModal(document.getElementById("export-pgn-dialog"));
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
|
|
||||||
gameData.headers.White = whiteEl.value.trim() || "White";
|
applyPlayerInputs(whiteEl, blackEl);
|
||||||
gameData.headers.Black = blackEl.value.trim() || "Black";
|
|
||||||
updateGameInfo();
|
|
||||||
|
|
||||||
const pgn = ChessPressure.toPgn(gameData.headers, gameData.moves);
|
const pgn = ChessPressure.toPgn(gameData.headers, gameData.moves);
|
||||||
const slug = (defaultGameName() || "game")
|
const slug = (defaultGameName() || "game")
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Chess Pressure</title>
|
<title>Chess Pressure</title>
|
||||||
<link rel="stylesheet" href="/style.css?v=31">
|
<link rel="stylesheet" href="/style.css?v=32">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css">
|
<link rel="stylesheet" href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css">
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="/manifest.json">
|
||||||
</head>
|
</head>
|
||||||
@ -127,6 +127,8 @@
|
|||||||
<label>Name:
|
<label>Name:
|
||||||
<input type="text" id="save-name" autocomplete="off">
|
<input type="text" id="save-name" autocomplete="off">
|
||||||
</label>
|
</label>
|
||||||
|
<label>White: <input type="text" id="save-white" autocomplete="off" placeholder="White player"></label>
|
||||||
|
<label>Black: <input type="text" id="save-black" autocomplete="off" placeholder="Black player"></label>
|
||||||
<p id="save-note" class="export-info" style="display:none">A saved game with this name already exists — saving will overwrite it.</p>
|
<p id="save-note" class="export-info" style="display:none">A saved game with this name already exists — saving will overwrite it.</p>
|
||||||
<div class="dialog-buttons">
|
<div class="dialog-buttons">
|
||||||
<button type="button" data-ok>Save</button>
|
<button type="button" data-ok>Save</button>
|
||||||
@ -176,6 +178,6 @@
|
|||||||
<script src="/chess.min.js"></script>
|
<script src="/chess.min.js"></script>
|
||||||
<script src="/gif.js"></script>
|
<script src="/gif.js"></script>
|
||||||
<script src="/engine.js"></script>
|
<script src="/engine.js"></script>
|
||||||
<script src="/app.js?v=31"></script>
|
<script src="/app.js?v=32"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Bump CACHE on every deploy so clients pick up new assets.
|
* Bump CACHE on every deploy so clients pick up new assets.
|
||||||
*/
|
*/
|
||||||
const CACHE = "chess-pressure-v31";
|
const CACHE = "chess-pressure-v32";
|
||||||
|
|
||||||
// Same-origin app shell. Cached by canonical path; the fetch handler matches
|
// Same-origin app shell. Cached by canonical path; the fetch handler matches
|
||||||
// with ignoreSearch so cache-busting query strings (?v=NN) still hit.
|
// with ignoreSearch so cache-busting query strings (?v=NN) still hit.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user