Stockage ouvert pendant le chargement du moteur ; test navigateur : nombre de parties
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
71ee3605d4
commit
e3aaa0b3a3
+41
-23
@@ -24,33 +24,51 @@ const engine = createWasmEngine(worker.run);
|
||||
const localStorage = attempt(() => window.localStorage);
|
||||
const settings = createSettingsStore(localStorage ?? memoryStorage());
|
||||
|
||||
// Les parties enregistrées (IndexedDB, ou localStorage en repli).
|
||||
const { library } = await openGameLibrary({
|
||||
indexedDB: attempt(() => window.indexedDB),
|
||||
localStorage,
|
||||
});
|
||||
// Le niveau de l'ordinateur : celui de Game.start (STANDARD_PLY).
|
||||
const session = createGameSession(
|
||||
library,
|
||||
{ start: () => Game.start(engine), resume: (journal) => Game.resume(engine, journal) },
|
||||
"2ply",
|
||||
);
|
||||
const saved = await session.restore();
|
||||
// Les parties enregistrées (IndexedDB, ou localStorage en repli), ouvertes
|
||||
// pendant que le moteur se charge : le plateau est dessiné sans les
|
||||
// attendre. L'écran de jeu ne s'en sert qu'une fois engineReady résolue.
|
||||
const opening = (async () => {
|
||||
const { library } = await openGameLibrary({
|
||||
indexedDB: attempt(() => window.indexedDB),
|
||||
localStorage,
|
||||
});
|
||||
// Le niveau de l'ordinateur : celui de Game.start (STANDARD_PLY).
|
||||
const session = createGameSession(
|
||||
library,
|
||||
{ start: () => Game.start(engine), resume: (journal) => Game.resume(engine, journal) },
|
||||
"2ply",
|
||||
);
|
||||
const saved = await session.restore();
|
||||
return { library, session, saved };
|
||||
})();
|
||||
let stored: Awaited<typeof opening> | null = null;
|
||||
/** Le stockage, ouvert (toujours le cas une fois engineReady résolue). */
|
||||
function storage(): Awaited<typeof opening> {
|
||||
if (stored === null) {
|
||||
throw new Error("stockage pas encore ouvert");
|
||||
}
|
||||
return stored;
|
||||
}
|
||||
|
||||
startApp({
|
||||
engineReady: worker.ready,
|
||||
newGame: () => session.newGame(),
|
||||
savedGame: () => saved,
|
||||
resumePrevious: () => session.resumePrevious(),
|
||||
saveGame: (journal) => session.save(journal),
|
||||
engineReady: Promise.all([
|
||||
worker.ready,
|
||||
opening.then((opened) => {
|
||||
stored = opened;
|
||||
}),
|
||||
]),
|
||||
newGame: () => storage().session.newGame(),
|
||||
savedGame: () => storage().saved,
|
||||
resumePrevious: () => storage().session.resumePrevious(),
|
||||
saveGame: (journal) => storage().session.save(journal),
|
||||
games: {
|
||||
list: () => library.list(),
|
||||
journal: async (id) => (await library.load(id))?.journal ?? null,
|
||||
shownId: () => session.shownId,
|
||||
open: (id, branchHead) => session.open(id, branchHead),
|
||||
remove: (id) => library.remove(id),
|
||||
list: () => storage().library.list(),
|
||||
journal: async (id) => (await storage().library.load(id))?.journal ?? null,
|
||||
shownId: () => storage().session.shownId,
|
||||
open: (id, branchHead) => storage().session.open(id, branchHead),
|
||||
remove: (id) => storage().library.remove(id),
|
||||
exportSgf: async (id) => {
|
||||
const game = await library.load(id);
|
||||
const game = await storage().library.load(id);
|
||||
if (game === null) {
|
||||
throw new Error("partie introuvable");
|
||||
}
|
||||
|
||||
@@ -447,6 +447,7 @@ export function startApp(options: AppOptions): void {
|
||||
]) {
|
||||
button.disabled = busy;
|
||||
}
|
||||
ui.menuGames.disabled = false;
|
||||
ui.cancel.disabled = busy || game.pendingHalfMoves.length === 0;
|
||||
renderPanel(game, landscape, doubled);
|
||||
renderMenu();
|
||||
@@ -491,6 +492,7 @@ export function startApp(options: AppOptions): void {
|
||||
}
|
||||
ui.moveHint.hidden = true;
|
||||
ui.menuNewGame.disabled = true;
|
||||
ui.menuGames.disabled = true;
|
||||
renderMenu();
|
||||
}
|
||||
|
||||
|
||||
+28
-3
@@ -154,6 +154,26 @@ async function readJournal() {
|
||||
);
|
||||
}
|
||||
|
||||
/** Le nombre de parties enregistrées dans IndexedDB. */
|
||||
async function savedGameCount() {
|
||||
await savedJournal(); // les enregistrements en cours terminés
|
||||
return page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
const open = indexedDB.open("ustagammon");
|
||||
open.onerror = () => reject(open.error);
|
||||
open.onsuccess = () => {
|
||||
const db = open.result;
|
||||
const count = db.transaction("games").objectStore("games").count();
|
||||
count.onsuccess = () => {
|
||||
db.close();
|
||||
resolve(count.result);
|
||||
};
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/** Le journal enregistré, une fois les enregistrements en cours terminés
|
||||
* (l'application enregistre sans attendre) : deux lectures identiques. */
|
||||
async function savedJournal() {
|
||||
@@ -1057,6 +1077,7 @@ for (let actions = 0; ; actions++) {
|
||||
check(await page.isVisible("#menu"), "M n'ouvre pas le menu");
|
||||
await page.keyboard.press("Escape");
|
||||
const pips = await page.textContent("#strip-player .count");
|
||||
const games = await savedGameCount();
|
||||
const old = await newGameFromMenu();
|
||||
await page.click("#resume-old");
|
||||
await waitForPlayer();
|
||||
@@ -1066,6 +1087,8 @@ for (let actions = 0; ; actions++) {
|
||||
check((await page.textContent("#strip-player .count")) === pips,
|
||||
"« Reprendre l'ancienne » : plateau différent");
|
||||
check(!(await page.isVisible("#banner")), "le bandeau reste après la reprise");
|
||||
check((await savedGameCount()) === games,
|
||||
"« Reprendre l'ancienne » : la nouvelle partie n'a pas été supprimée");
|
||||
log(`nouvelle partie puis « Reprendre l'ancienne » : journal identique (${old.events.length} événements)`);
|
||||
}
|
||||
}
|
||||
@@ -1142,8 +1165,10 @@ step("mes parties");
|
||||
await page.waitForSelector("#games-veil:not([hidden]) .games-item");
|
||||
check(!(await page.isVisible("#menu")), "le menu reste ouvert sous « Mes parties »");
|
||||
const items = page.locator("#games .games-item");
|
||||
// La partie abandonnée par « Reprendre l'ancienne » a été supprimée.
|
||||
check((await items.count()) === 2, `${await items.count()} parties listées au lieu de 2`);
|
||||
// Toutes les parties enregistrées, la dernière jouée d'abord : la
|
||||
// nouvelle, puis celle qui vient de finir.
|
||||
const listed = await items.count();
|
||||
check(listed >= 2 && listed === (await savedGameCount()), `${listed} parties listées`);
|
||||
check(!(await items.nth(0).locator('[data-action="remove"]').isVisible()),
|
||||
"la partie à l'écran peut être supprimée");
|
||||
const oldest = items.nth(1);
|
||||
@@ -1173,7 +1198,7 @@ step("mes parties");
|
||||
"la page a été rechargée");
|
||||
await page.click("#panel-secondary");
|
||||
log(
|
||||
`mes parties : 2 parties listées (${branchCount} branche(s) pour la première), ` +
|
||||
`mes parties : ${listed} parties listées (${branchCount} branche(s) pour la première), ` +
|
||||
`SGF exporté (${sgf.length} octets), première partie reprise sans rechargement`,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user