2 // // Static informations:
6 // players: array of sid+id+name,
8 // increment: integer (seconds),
9 // type: string ("live" or "corr")
10 // // Game (dynamic) state:
12 // moves: array of Move objects,
13 // clocks: array of integers,
14 // initime: array of integers (when clock start running),
15 // score: string (several options; '*' == running),
18 import { ajax
} from "@/utils/ajax";
19 import { store
} from "@/store";
21 function dbOperation(callback
) {
23 let DBOpenRequest
= window
.indexedDB
.open("vchess", 4);
25 DBOpenRequest
.onerror = function(event
) {
26 alert(store
.state
.tr
["Database error: stop private browsing, or update your browser"]);
27 callback("error",null);
30 DBOpenRequest
.onsuccess = function() {
31 db
= DBOpenRequest
.result
;
36 DBOpenRequest
.onupgradeneeded = function(event
) {
37 let db
= event
.target
.result
;
38 let objectStore
= db
.createObjectStore("games", { keyPath: "id" });
39 objectStore
.createIndex("score", "score"); //to search by game result
43 export const GameStorage
= {
44 // Optional callback to get error status
45 add: function(game
, callback
) {
46 dbOperation((err
,db
) => {
51 let transaction
= db
.transaction("games", "readwrite");
52 transaction
.oncomplete = function() {
53 callback(); //everything's fine
55 let objectStore
= transaction
.objectStore("games");
56 objectStore
.add(game
);
60 // TODO: also option to takeback a move ?
61 // obj: chat, move, fen, clocks, score[Msg], initime, ...
62 update: function(gameId
, obj
) {
63 if (Number
.isInteger(gameId
) || !isNaN(parseInt(gameId
))) {
64 // corr: only move, fen and score
65 ajax("/games", "PUT", {
68 // Some fields may be undefined:
73 scoreMsg: obj
.scoreMsg
,
74 drawOffer: obj
.drawOffer
79 dbOperation((err
,db
) => {
81 .transaction("games", "readwrite")
82 .objectStore("games");
83 objectStore
.get(gameId
).onsuccess = function(event
) {
84 // Ignoring error silently: shouldn't happen now. TODO?
85 if (event
.target
.result
) {
86 const game
= event
.target
.result
;
87 Object
.keys(obj
).forEach(k
=> {
88 if (k
== "move") game
.moves
.push(obj
[k
]);
89 else game
[k
] = obj
[k
];
91 objectStore
.put(game
); //save updated data
98 // Retrieve all local games (running, completed, imported...)
99 // light: do not retrieve moves or clocks (TODO: this is the only usage)
100 getAll: function(light
, callback
) {
101 dbOperation((err
,db
) => {
102 let objectStore
= db
.transaction("games").objectStore("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
108 let g
= cursor
.value
;
110 g
.movesCount
= g
.moves
.length
;
117 } else callback(games
);
122 // Retrieve any game from its identifiers (locally or on server)
123 // NOTE: need callback because result is obtained asynchronously
124 get: function(gameId
, callback
) {
125 // corr games identifiers are integers
126 if (Number
.isInteger(gameId
) || !isNaN(parseInt(gameId
))) {
127 ajax("/games", "GET", { gid: gameId
}, res
=> {
129 game
.moves
.forEach(m
=> {
130 m
.squares
= JSON
.parse(m
.squares
);
137 dbOperation((err
,db
) => {
138 let objectStore
= db
.transaction("games").objectStore("games");
139 objectStore
.get(gameId
).onsuccess = function(event
) {
140 if (event
.target
.result
)
141 callback(event
.target
.result
);
147 // Delete a game in indexedDB
148 remove: function(gameId
, callback
) {
149 dbOperation((err
,db
) => {
151 let transaction
= db
.transaction(["games"], "readwrite");
152 transaction
.oncomplete = function() {
153 callback({}); //everything's fine
155 transaction
.objectStore("games").delete(gameId
);