PageSourceSearch

https://vc64web.github.io/js/vc64_storage.js

js vc64web.github.io collected 2026-10-03 10:08:00 UTC 11,575 bytes, 456 lines download raw bytes

1//-- indexedDB API
2_db = null;
3_db_init_called=false;
4_db_wait_counter=0;
5_db_retries=0;
6const _sleep = (milliseconds) => {
7  return new Promise(resolve => setTimeout(resolve, milliseconds));
8}
9async function db(){
10  let me_called_init=false;
11  //wait until _db created
12  while(_db==null)
13  {
14    if(_db_init_called==false)
15    {
16      _db_init_called=true;
17      me_called_init=true;
18
19      if(_db_retries>2)
20      {
21        let msg=`cannot open database... are you using private/incognito browsing? To enable storage use a normal browser window...`;
22        _db_retries=0;
23        _db_init_called=false;
24        throw new Error(msg);
25      }
26      console.error(`opening db ... ${_db_retries+1}.try`);
27      initDB();
28      _db_retries+=1;
29    }
30    let wait_time=100;
31    await _sleep(wait_time);
32    if(me_called_init)
33    {
34      _db_wait_counter+=wait_time;
35    }
36    
37    if(_db_wait_counter > 1500)
38    {//if opening db takes too long, retry
39        _db_init_called = false;
40        _db_wait_counter=0;
41        _me_called_init=false;
42    }
43  }  
44  return _db;
45}
46
47
48function initDB() {  
49  window.addEventListener('unhandledrejection', function(event) {
50    alert("Error: " + event.reason.message);
51  });
52
53  
54  let openReq =  indexedDB.open('vc64db', 4);
55
56  openReq.onupgradeneeded = function (event){
57      let _db = openReq.result;
58      switch (event.oldVersion) {
59          case 0:
60              //no db
61              break;
62          default:
63              break;
64      }
65      if(!_db.objectStoreNames.contains('snapshots'))
66      {
67         var snapshot_store=_db.createObjectStore('snapshots', {keyPath: 'id', autoIncrement: true});
68         snapshot_store.createIndex("title", "title", { unique: false });
69      }
70      if(!_db.objectStoreNames.contains('apps'))
71      {
72         var apps_store=_db.createObjectStore('apps', {keyPath: 'title'}); 
73      }
74
75      //db.deleteObjectStore('custom_buttons');
76      if(!_db.objectStoreNames.contains('custom_buttons'))
77      {
78         //alert("create two local object stores");
79         var custom_buttons_store=_db.createObjectStore('custom_buttons', {keyPath: 'title'});
80      }
81
82  };
83  openReq.onerror = function() { 
84    console.error("Error", openReq.error);
85    _db_wait_counter=1600; //flag this wait as unsuccessful 
86    /*alert('error while open db: '+openReq.error);*/
87  }
88  openReq.onsuccess = function() {
89      _db=openReq.result;
90  }  
91}
92
93
94async function save_snapshot(the_name, the_data) {
95  //beim laden in die drop zone den Titel merken
96  //dann beim take snapshot, den titel automatisch mitgeben
97  //im Snapshotbrowser jeden titel als eigene row darstellen
98  //erste row autosnapshot, danach kommen die Titel
99  //extra user snapshot ist dann unnötig
100  let the_snapshot = {
101    title: the_name,
102    data: the_data //,
103//    created: new Date()
104  };
105
106  let tx_apps = (await db()).transaction('apps', 'readwrite');
107  let req_apps = tx_apps.objectStore('apps').put({title: the_name});
108  req_apps.onsuccess= function(e){ 
109        console.log("wrote app with id="+e.target.result)        
110  };
111
112
113  let tx = (await db()).transaction('snapshots', 'readwrite');
114  tx.oncomplete = function() {
115    console.log("Transaction is complete");
116  };
117  tx.onabort = function() {
118    console.log("Transaction is aborted");
119  };
120 
121  try {
122    let req = tx.objectStore('snapshots').add(the_snapshot);
123    req.onsuccess= function(e){ 
124        console.log("wrote snapshot with id="+e.target.result)        
125    };
126    req.onerror = function(e){ 
127        console.error("could not write snapshot: ",  req.error) 
128    };
129  } catch(err) {
130    if (err.name == 'ConstraintError') {
131      alert("Such snapshot exists already");
132    } else {
133      throw err;
134    }
135  }
136}
137
138async function get_stored_app_titles(callback_fn)
139{
140  let transaction = (await db()).transaction("apps"); // readonly
141  let apps = transaction.objectStore("apps");
142
143  let request = apps.getAllKeys();
144
145  request.onsuccess = function() {
146      if (request.result !== undefined) {
147          callback_fn(request.result);
148      } else {
149          console.log("No titles found");
150      }
151  };
152}
153
154function stored_app_titles() {
155  return new Promise((resolve, reject) => {
156    get_stored_app_titles((result) => {
157        resolve(result);
158    });
159  });
160}
161
162function get_snapshots_for_app_title(app_title)
163{
164    return new Promise(async (resolve, reject) => {
165      let transaction = (await db()).transaction("snapshots"); 
166      let snapshots = transaction.objectStore("snapshots");
167      let titleIndex = snapshots.index("title");
168      let request = titleIndex.getAll(app_title);
169
170      request.onsuccess = function() {
171          resolve(request.result);
172      };
173    });
174}
175
176
177async function get_snapshot_per_id(the_id, callback_fn)
178{
179    let transaction = (await db()).transaction("snapshots"); 
180    let snapshots = transaction.objectStore("snapshots");
181 
182    let request = snapshots.get(parseInt(the_id));
183
184    request.onsuccess = function() {
185        callback_fn(request.result);
186    };
187}
188
189function delete_snapshot_per_id(the_id)
190{
191  get_snapshot_per_id(the_id, 
192  async function(the_snapshot) {
193    let transaction = (await db()).transaction("snapshots", 'readwrite'); 
194    let snapshots = transaction.objectStore("snapshots");
195    snapshots.delete(parseInt(the_id));
196    //check if this was the last snapshot of the game title 
197    get_snapshots_for_app_title(0, the_snapshot.title, 
198      async function (ctx, app_title, snapshot_list) {
199        if(snapshot_list.length == 0)
200        {//when it was the last one, then also delete the app title
201          let tx_apps = (await db()).transaction("apps", 'readwrite'); 
202          let apps = tx_apps.objectStore("apps");
203          apps.delete(app_title);
204        }
205      }
206    );
207  });
208}
209
210
211//--- local storage API ---
212
213
214function local_storage_get(name) {
215  try{
216    return localStorage.getItem(name);
217  } 
218  catch(e) {
219    console.error(e.message);
220    return null;
221  }  
222}
223function local_storage_set(name, value) {
224  try{
225    localStorage.setItem(name,value);
226  } 
227  catch(e) {
228    console.error(e.message);
229  }  
230}
231function local_storage_remove(name) {
232  try{
233    localStorage.removeItem(name);
234  } 
235  catch(e) {
236    console.error(e.message);
237  }  
238}
239
240
241
242
243function load_setting(name, default_value) {
244    var value = local_storage_get(name);
245    if(value === null)
246    {
247        return default_value;
248    } 
249    else
250    {
251        if(value=='true')
252          return true;
253        else if(value=='false')
254          return false;
255        else
256          return value;
257    }
258}
259
260function save_setting(name, value) {
261    if (value!= null) {
262      local_storage_set(name, value);
263    } else {
264      local_storage_remove(name);
265    }
266}
267
268
269
270
271
272
273//-------------- custom buttons
274
275function save_new_empty_group(the_name) {
276  save_custom_buttons_scope(the_name, []);
277}
278
279function save_custom_buttons(the_name, the_data) {
280  var app_specific_data=[];
281  var global_data=[];
282
283  for(button_def_id in the_data)
284  {
285    var button_def=the_data[button_def_id];
286    if(button_def.transient !== undefined && button_def.transient)
287    {
288      //don't save transient buttons
289    }
290    else if(button_def.app_scope)
291    {
292      app_specific_data.push(button_def);
293    }
294    else
295    {
296      global_data.push(button_def); 
297    }
298  }
299  save_custom_buttons_scope(the_name, app_specific_data);
300  save_custom_buttons_scope('__global_scope__', global_data);
301}
302
303
304
305async function save_custom_buttons_scope(the_name, the_data) {
306  let the_custom_buttons = {
307    title: the_name,
308    data: the_data 
309  };
310
311  let tx_apps = (await db()).transaction('apps', 'readwrite');
312  let req_apps = tx_apps.objectStore('apps').put({title: the_name});
313  req_apps.onsuccess= function(e){ 
314        console.log("wrote app with id="+e.target.result)        
315  };
316
317
318  let tx = (await db()).transaction('custom_buttons', 'readwrite');
319  tx.oncomplete = function() {
320    console.log("Transaction is complete");
321  };
322  tx.onabort = function() {
323    console.log("Transaction is aborted");
324  };
325 
326  try {
327    let req = tx.objectStore('custom_buttons').put(the_custom_buttons);
328    req.onsuccess= function(e){ 
329        console.log("wrote custom_buttons with id="+e.target.result)        
330    };
331    req.onerror = function(e){ 
332        console.error("could not write custom_buttons: ",  req.error) 
333    };
334  } catch(err) {
335      throw err;
336  }
337}
338
339
340
341var buttons_from_mixed_scopes = null;
342function get_custom_buttons(the_app_title, callback_fn)
343{
344  get_custom_buttons_app_scope(the_app_title, 
345    function(the_buttons) {
346      buttons_from_mixed_scopes = the_buttons;
347
348      //add globals
349      get_custom_buttons_app_scope('__global_scope__', 
350          function(the_global_buttons) {
351
352              var last_id_in_appscope= buttons_from_mixed_scopes.data.length-1;
353              for(gb_id in the_global_buttons.data)
354              {
355                var gb = the_global_buttons.data[gb_id];
356                last_id_in_appscope++;
357                gb.id=last_id_in_appscope;
358                buttons_from_mixed_scopes.data.push(gb);                                
359              }
360              callback_fn(buttons_from_mixed_scopes.data);
361          }
362        );
363      }
364    );
365}
366
367
368async function get_custom_buttons_app_scope(the_app_title, callback_fn)
369{
370//  if(_db === undefined)
371//    return;
372  try
373  {
374    let transaction = (await db()).transaction("custom_buttons"); 
375    let custom_buttons = transaction.objectStore("custom_buttons");
376
377    let request = custom_buttons.get(the_app_title);
378
379    request.onsuccess = function() {
380        if(request.result !== undefined)
381        {
382          for(button_id in request.result.data)
383          {
384            var action_button = request.result.data[button_id];
385            if(action_button.app_scope === undefined)
386            {
387              action_button.app_scope= true;
388            }
389            if(action_button.lang === undefined)
390            {
391              //migration of js: prefix to lang property, can be removed in a later version ... 
392              if(action_button.script.startsWith("js:"))
393              {
394                action_button.script = action_button.script.substring(3);
395                action_button.lang = "javascript";
396              }
397              else
398              {
399                action_button.lang = "actionscript";
400              }
401            }
402          }
403
404          callback_fn(request.result);
405        }
406        else
407        {
408          let empty_custom_buttons = {
409              title: the_app_title,
410              data: [] 
411            };
412
413          callback_fn(empty_custom_buttons);
414        }
415    };
416  }
417  catch(e)
418  {
419    console.error(e.message);
420    let empty_custom_buttons = {
421              title: the_app_title,
422              data: [] 
423            };
424    callback_fn(empty_custom_buttons);
425  }
426}
427
428async function get_stored_groups(callback_fn)
429{
430  let transaction = (await db()).transaction("custom_buttons"); // readonly
431  let custom_buttons = transaction.objectStore("custom_buttons");
432
433  let request = custom_buttons.getAllKeys();
434
435  request.onsuccess = function() {
436      if (request.result !== undefined) {
437          callback_fn(request.result);
438      } else {
439          console.log("No titles found");
440      }
441  };    
442}
443function stored_groups() {
444  return new Promise((resolve, reject) => {
445    get_stored_groups((result) => {
446        resolve(result);
447    });
448  });
449}
450
451async function delete_button_group(key)
452{
453  let tx_apps = (await db()).transaction("custom_buttons", 'readwrite'); 
454  let custom_buttons = tx_apps.objectStore("custom_buttons");
455  custom_buttons.delete(key);
456}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.