From 934f7f70431e9892b3ea48ba199356b4f24eaf1b Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Thu, 19 Mar 2020 14:24:01 +0100 Subject: [PATCH] loadMore button for my local games as well --- client/src/App.vue | 9 +++ client/src/utils/compgameStorage.js | 23 +++--- client/src/utils/gameStorage.js | 73 ++++++++++++++---- client/src/views/Game.vue | 2 + client/src/views/Hall.vue | 2 + client/src/views/MyGames.vue | 114 +++++++++++++++------------- client/src/views/Problems.vue | 6 +- 7 files changed, 148 insertions(+), 81 deletions(-) diff --git a/client/src/App.vue b/client/src/App.vue index d8ae21d3..c71ebfc4 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -279,10 +279,19 @@ footer padding: 5px 0 .menuitem.somenews + animation: blinkNews 1s infinite; color: red &:link, &:visited, &:hover color: red +@keyframes blinkNews + 0%, 49% + background-color: yellow + padding: 3px + 50%, 100% + background-color: grey + padding: 3px + // Styles for diagrams and board (partial). // TODO: where to put that ? diff --git a/client/src/utils/compgameStorage.js b/client/src/utils/compgameStorage.js index 05a20749..a5c58af1 100644 --- a/client/src/utils/compgameStorage.js +++ b/client/src/utils/compgameStorage.js @@ -16,28 +16,28 @@ function dbOperation(callback) { DBOpenRequest.onerror = function(event) { alert(store.state.tr["Database error: stop private browsing, or update your browser"]); - callback("error",null); + callback("error", null); }; DBOpenRequest.onsuccess = function(event) { db = DBOpenRequest.result; - callback(null,db); + callback(null, db); db.close(); }; DBOpenRequest.onupgradeneeded = function(event) { let db = event.target.result; - let objectStore = db.createObjectStore("compgames", { keyPath: "vname" }); + db.createObjectStore("compgames", { keyPath: "vname" }); }; } export const CompgameStorage = { add: function(game) { dbOperation((err,db) => { - if (err) - return; - let transaction = db.transaction("compgames", "readwrite"); - let objectStore = transaction.objectStore("compgames"); + if (err) return; + let objectStore = db + .transaction("compgames", "readwrite") + .objectStore("compgames"); objectStore.add(game); }); }, @@ -66,7 +66,9 @@ export const CompgameStorage = { // NOTE: need callback because result is obtained asynchronously get: function(gameId, callback) { dbOperation((err,db) => { - let objectStore = db.transaction("compgames").objectStore("compgames"); + let objectStore = db + .transaction("compgames", "readonly") + .objectStore("compgames"); objectStore.get(gameId).onsuccess = function(event) { callback(event.target.result); }; @@ -77,8 +79,9 @@ export const CompgameStorage = { remove: function(gameId) { dbOperation((err,db) => { if (!err) { - let transaction = db.transaction(["compgames"], "readwrite"); - transaction.objectStore("compgames").delete(gameId); + db.transaction("compgames", "readwrite") + .objectStore("compgames") + .delete(gameId); } }); } diff --git a/client/src/utils/gameStorage.js b/client/src/utils/gameStorage.js index 12986679..fc179f19 100644 --- a/client/src/utils/gameStorage.js +++ b/client/src/utils/gameStorage.js @@ -23,19 +23,22 @@ function dbOperation(callback) { DBOpenRequest.onerror = function(event) { alert(store.state.tr["Database error: stop private browsing, or update your browser"]); - callback("error",null); + callback("error", null); }; DBOpenRequest.onsuccess = function() { db = DBOpenRequest.result; - callback(null,db); + callback(null, db); db.close(); }; DBOpenRequest.onupgradeneeded = function(event) { let db = event.target.result; let objectStore = db.createObjectStore("games", { keyPath: "id" }); - objectStore.createIndex("score", "score"); //to search by game result + // To sarch games by score (useful for running games) + objectStore.createIndex("score", "score", { unique: false }); + // To search by date intervals. Two games cannot start at the same time + objectStore.createIndex("created", "created", { unique: true }); }; } @@ -49,13 +52,14 @@ export const GameStorage = { } let transaction = db.transaction("games", "readwrite"); transaction.oncomplete = function() { - callback(); //everything's fine + // Everything's fine + callback(); }; transaction.onerror = function(err) { - callback(err); //duplicate key error (most likely) + // Duplicate key error (most likely) + callback(err); }; - let objectStore = transaction.objectStore("games"); - objectStore.add(game); + transaction.objectStore("games").add(game); }); }, @@ -82,15 +86,20 @@ export const GameStorage = { }); }, - // Retrieve all local games (running, completed, imported...) - getAll: function(callback) { + // Retrieve (all) running local games + getRunning: function(callback) { dbOperation((err,db) => { - let objectStore = db.transaction("games").objectStore("games"); + let objectStore = db + .transaction("games", "readonly") + .objectStore("games"); + let index = objectStore.index("score"); + const range = IDBKeyRange.only("*"); let games = []; - objectStore.openCursor().onsuccess = function(event) { + index.openCursor(range).onsuccess = function(event) { let cursor = event.target.result; - // if there is still another cursor to go, keep running this code - if (cursor) { + if (!cursor) callback(games); + else { + // If there is still another cursor to go, keep running this code let g = cursor.value; // Do not retrieve moves or clocks (unused in list mode) g.movesCount = g.moves.length; @@ -99,7 +108,41 @@ export const GameStorage = { delete g.initime; games.push(g); cursor.continue(); - } else callback(games); + } + }; + }); + }, + + // Retrieve completed local games + getNext: function(upperDt, callback) { + dbOperation((err,db) => { + let objectStore = db + .transaction("games", "readonly") + .objectStore("games"); + let index = objectStore.index("created"); + const range = IDBKeyRange.upperBound(upperDt); + let games = []; + index.openCursor(range).onsuccess = function(event) { + let cursor = event.target.result; + if (!cursor) { + // Most recent games first: + games = games.sort((g1, g2) => g2.created - g1.created); + // TODO: 20 games showed per request is arbitrary + callback(games.slice(0, 20)); + } + else { + // If there is still another cursor to go, keep running this code + let g = cursor.value; + if (g.score != "*") { + // Do not retrieve moves or clocks (unused in list mode) + g.movesCount = g.moves.length; + delete g.moves; + delete g.clocks; + delete g.initime; + games.push(g); + } + cursor.continue(); + } }; }); }, @@ -121,7 +164,7 @@ export const GameStorage = { remove: function(gameId, callback) { dbOperation((err,db) => { if (!err) { - let transaction = db.transaction(["games"], "readwrite"); + let transaction = db.transaction("games", "readwrite"); transaction.oncomplete = function() { callback(); //everything's fine }; diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 68c8c94d..1a86d9b8 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -445,6 +445,8 @@ export default { const data = JSON.parse(msg.data); switch (data.code) { case "pollclients": + // TODO: shuffling and random filtering on server, if + // the room is really crowded. data.sockIds.forEach(sid => { if (sid != this.st.user.sid) { this.people[sid] = { focus: true }; diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index d11da8b1..47a86975 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -585,6 +585,8 @@ export default { // Since people can be both in Hall and Game, // need to track "askIdentity" requests: let identityAsked = {}; + // TODO: shuffling and random filtering on server, if + // the room is really crowded. data.sockIds.forEach(s => { const page = s.page || "/"; if (s.sid != this.st.user.sid && !identityAsked[s.sid]) { diff --git a/client/src/views/MyGames.vue b/client/src/views/MyGames.vue index a9e69f65..60783941 100644 --- a/client/src/views/MyGames.vue +++ b/client/src/views/MyGames.vue @@ -14,18 +14,18 @@ main @show-game="showGame" @abortgame="abortGame" ) - div(v-show="display=='corr'") - GameList( - ref="corrgames" - :games="corrGames" - @show-game="showGame" - @abortgame="abortGame" - ) - button#loadMoreBtn( - v-if="hasMore" - @click="loadMore()" - ) - | {{ st.tr["Load more"] }} + GameList( + v-show="display=='corr'" + ref="corrgames" + :games="corrGames" + @show-game="showGame" + @abortgame="abortGame" + ) + button#loadMoreBtn( + v-show="hasMore[display]" + @click="loadMore(display)" + ) + | {{ st.tr["Load more"] }}