Fixes
[vchess.git] / client / src / utils / gameStorage.js
CommitLineData
967a2686
BA
1// Game object: {
2// // Static informations:
11667c79 3// id: string
967a2686
BA
4// vname: string,
5// fenStart: string,
6// players: array of sid+id+name,
71468011 7// cadence: string,
967a2686 8// increment: integer (seconds),
910d631b 9// type: string ("live" or "corr")
967a2686
BA
10// imported: boolean (optional, default false)
11// // Game (dynamic) state:
12// fen: string,
13// moves: array of Move objects,
14// clocks: array of integers,
809ba2aa 15// initime: array of integers (when clock start running),
967a2686
BA
16// score: string (several options; '*' == running),
17// }
18
fd7aea36 19import { ajax } from "@/utils/ajax";
602d6bef 20import { store } from "@/store";
fd7aea36 21
6808d7a1 22function dbOperation(callback) {
967a2686
BA
23 let db = null;
24 let DBOpenRequest = window.indexedDB.open("vchess", 4);
25
26 DBOpenRequest.onerror = function(event) {
8477e53d
BA
27 alert(store.state.tr["Database error: stop private browsing, or update your browser"]);
28 callback("error",null);
967a2686
BA
29 };
30
6808d7a1 31 DBOpenRequest.onsuccess = function() {
967a2686 32 db = DBOpenRequest.result;
8477e53d 33 callback(null,db);
967a2686
BA
34 db.close();
35 };
36
37 DBOpenRequest.onupgradeneeded = function(event) {
38 let db = event.target.result;
11667c79 39 let objectStore = db.createObjectStore("games", { keyPath: "id" });
42c15a75 40 objectStore.createIndex("score", "score"); //to search by game result
6808d7a1 41 };
967a2686
BA
42}
43
6808d7a1 44export const GameStorage = {
967a2686 45 // Optional callback to get error status
6808d7a1 46 add: function(game, callback) {
8477e53d
BA
47 dbOperation((err,db) => {
48 if (err) {
49 callback("error");
50 return;
967a2686 51 }
8477e53d
BA
52 let transaction = db.transaction("games", "readwrite");
53 transaction.oncomplete = function() {
54 callback(); //everything's fine
55 };
967a2686
BA
56 let objectStore = transaction.objectStore("games");
57 objectStore.add(game);
58 });
59 },
60
61 // TODO: also option to takeback a move ?
dcd68c41 62 // obj: chat, move, fen, clocks, score[Msg], initime, ...
6808d7a1
BA
63 update: function(gameId, obj) {
64 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
3d55deea 65 // corr: only move, fen and score
6808d7a1
BA
66 ajax("/games", "PUT", {
67 gid: gameId,
68 newObj: {
69 // Some fields may be undefined:
70 chat: obj.chat,
71 move: obj.move,
72 fen: obj.fen,
73 score: obj.score,
74 scoreMsg: obj.scoreMsg,
75 drawOffer: obj.drawOffer
3d55deea 76 }
6808d7a1
BA
77 });
78 } else {
3d55deea 79 // live
8477e53d 80 dbOperation((err,db) => {
6808d7a1
BA
81 let objectStore = db
82 .transaction("games", "readwrite")
83 .objectStore("games");
3d55deea 84 objectStore.get(gameId).onsuccess = function(event) {
8477e53d
BA
85 // Ignoring error silently: shouldn't happen now. TODO?
86 if (event.target.result) {
87 const game = event.target.result;
88 Object.keys(obj).forEach(k => {
89 if (k == "move") game.moves.push(obj[k]);
90 else game[k] = obj[k];
91 });
92 objectStore.put(game); //save updated data
93 }
6808d7a1 94 };
3d55deea
BA
95 });
96 }
967a2686
BA
97 },
98
fd7aea36 99 // Retrieve all local games (running, completed, imported...)
6808d7a1 100 getAll: function(callback) {
8477e53d 101 dbOperation((err,db) => {
6808d7a1 102 let objectStore = db.transaction("games").objectStore("games");
fd7aea36
BA
103 let games = [];
104 objectStore.openCursor().onsuccess = function(event) {
105 let cursor = event.target.result;
106 // if there is still another cursor to go, keep running this code
6808d7a1 107 if (cursor) {
fd7aea36
BA
108 games.push(cursor.value);
109 cursor.continue();
6808d7a1
BA
110 } else callback(games);
111 };
fd7aea36
BA
112 });
113 },
114
115 // Retrieve any game from its identifiers (locally or on server)
116 // NOTE: need callback because result is obtained asynchronously
6808d7a1 117 get: function(gameId, callback) {
fd7aea36 118 // corr games identifiers are integers
6808d7a1
BA
119 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
120 ajax("/games", "GET", { gid: gameId }, res => {
92b82def
BA
121 let game = res.game;
122 game.moves.forEach(m => {
123 m.squares = JSON.parse(m.squares);
124 });
125 callback(game);
fd7aea36 126 });
8477e53d 127 }
6808d7a1 128 else {
8477e53d
BA
129 // Local game
130 dbOperation((err,db) => {
6808d7a1 131 let objectStore = db.transaction("games").objectStore("games");
967a2686 132 objectStore.get(gameId).onsuccess = function(event) {
8477e53d
BA
133 if (event.target.result)
134 callback(event.target.result);
6808d7a1 135 };
fd7aea36
BA
136 });
137 }
967a2686
BA
138 },
139
140 // Delete a game in indexedDB
6808d7a1 141 remove: function(gameId, callback) {
8477e53d
BA
142 dbOperation((err,db) => {
143 if (!err) {
144 let transaction = db.transaction(["games"], "readwrite");
967a2686
BA
145 transaction.oncomplete = function() {
146 callback({}); //everything's fine
6808d7a1 147 };
8477e53d 148 transaction.objectStore("games").delete(gameId);
967a2686 149 }
967a2686 150 });
6808d7a1 151 }
967a2686 152};