Fixes
[vchess.git] / client / src / utils / gameStorage.js
1 // Game object: {
2 // // Static informations:
3 // id: string
4 // vname: string,
5 // fenStart: string,
6 // players: array of sid+id+name,
7 // cadence: string,
8 // increment: integer (seconds),
9 // type: string ("live" or "corr")
10 // imported: boolean (optional, default false)
11 // // Game (dynamic) state:
12 // fen: string,
13 // moves: array of Move objects,
14 // clocks: array of integers,
15 // initime: array of integers (when clock start running),
16 // score: string (several options; '*' == running),
17 // }
18
19 import { ajax } from "@/utils/ajax";
20 import { store } from "@/store";
21
22 function dbOperation(callback) {
23 let db = null;
24 let DBOpenRequest = window.indexedDB.open("vchess", 4);
25
26 DBOpenRequest.onerror = function(event) {
27 alert(store.state.tr["Database error: stop private browsing, or update your browser"]);
28 callback("error",null);
29 };
30
31 DBOpenRequest.onsuccess = function() {
32 db = DBOpenRequest.result;
33 callback(null,db);
34 db.close();
35 };
36
37 DBOpenRequest.onupgradeneeded = function(event) {
38 let db = event.target.result;
39 let objectStore = db.createObjectStore("games", { keyPath: "id" });
40 objectStore.createIndex("score", "score"); //to search by game result
41 };
42 }
43
44 export const GameStorage = {
45 // Optional callback to get error status
46 add: function(game, callback) {
47 dbOperation((err,db) => {
48 if (err) {
49 callback("error");
50 return;
51 }
52 let transaction = db.transaction("games", "readwrite");
53 transaction.oncomplete = function() {
54 callback(); //everything's fine
55 };
56 let objectStore = transaction.objectStore("games");
57 objectStore.add(game);
58 });
59 },
60
61 // TODO: also option to takeback a move ?
62 // obj: chat, move, fen, clocks, score[Msg], initime, ...
63 update: function(gameId, obj) {
64 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
65 // corr: only move, fen and score
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
76 }
77 });
78 } else {
79 // live
80 dbOperation((err,db) => {
81 let objectStore = db
82 .transaction("games", "readwrite")
83 .objectStore("games");
84 objectStore.get(gameId).onsuccess = function(event) {
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 }
94 };
95 });
96 }
97 },
98
99 // Retrieve all local games (running, completed, imported...)
100 getAll: function(callback) {
101 dbOperation((err,db) => {
102 let objectStore = db.transaction("games").objectStore("games");
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
107 if (cursor) {
108 games.push(cursor.value);
109 cursor.continue();
110 } else callback(games);
111 };
112 });
113 },
114
115 // Retrieve any game from its identifiers (locally or on server)
116 // NOTE: need callback because result is obtained asynchronously
117 get: function(gameId, callback) {
118 // corr games identifiers are integers
119 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
120 ajax("/games", "GET", { gid: gameId }, res => {
121 let game = res.game;
122 game.moves.forEach(m => {
123 m.squares = JSON.parse(m.squares);
124 });
125 callback(game);
126 });
127 }
128 else {
129 // Local game
130 dbOperation((err,db) => {
131 let objectStore = db.transaction("games").objectStore("games");
132 objectStore.get(gameId).onsuccess = function(event) {
133 if (event.target.result)
134 callback(event.target.result);
135 };
136 });
137 }
138 },
139
140 // Delete a game in indexedDB
141 remove: function(gameId, callback) {
142 dbOperation((err,db) => {
143 if (!err) {
144 let transaction = db.transaction(["games"], "readwrite");
145 transaction.oncomplete = function() {
146 callback({}); //everything's fine
147 };
148 transaction.objectStore("games").delete(gameId);
149 }
150 });
151 }
152 };