2019-02-12 20:50:06 +01:00
|
|
|
import { arrayToB64, isFile } from './utils';
|
2018-01-24 19:23:13 +01:00
|
|
|
import OwnedFile from './ownedFile';
|
2017-07-21 21:44:55 +02:00
|
|
|
|
2017-08-10 03:16:10 +02:00
|
|
|
class Mem {
|
|
|
|
constructor() {
|
|
|
|
this.items = new Map();
|
|
|
|
}
|
|
|
|
|
|
|
|
get length() {
|
|
|
|
return this.items.size;
|
|
|
|
}
|
|
|
|
|
|
|
|
getItem(key) {
|
|
|
|
return this.items.get(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
setItem(key, value) {
|
|
|
|
return this.items.set(key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
removeItem(key) {
|
|
|
|
return this.items.delete(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
key(i) {
|
|
|
|
return this.items.keys()[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-24 23:54:02 +02:00
|
|
|
class Storage {
|
2017-08-10 03:16:10 +02:00
|
|
|
constructor() {
|
|
|
|
try {
|
|
|
|
this.engine = localStorage || new Mem();
|
|
|
|
} catch (e) {
|
|
|
|
this.engine = new Mem();
|
|
|
|
}
|
2017-08-24 23:54:02 +02:00
|
|
|
this._files = this.loadFiles();
|
|
|
|
}
|
|
|
|
|
|
|
|
loadFiles() {
|
2018-08-08 00:40:17 +02:00
|
|
|
const fs = new Map();
|
2017-08-24 23:54:02 +02:00
|
|
|
for (let i = 0; i < this.engine.length; i++) {
|
|
|
|
const k = this.engine.key(i);
|
|
|
|
if (isFile(k)) {
|
|
|
|
try {
|
2018-01-31 20:12:36 +01:00
|
|
|
const f = new OwnedFile(JSON.parse(this.engine.getItem(k)));
|
2017-09-12 02:09:29 +02:00
|
|
|
if (!f.id) {
|
|
|
|
f.id = f.fileId;
|
|
|
|
}
|
2018-07-31 20:09:18 +02:00
|
|
|
|
2018-08-08 00:40:17 +02:00
|
|
|
fs.set(f.id, f);
|
2017-08-24 23:54:02 +02:00
|
|
|
} catch (err) {
|
|
|
|
// obviously you're not a golfer
|
|
|
|
this.engine.removeItem(k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-08 00:40:17 +02:00
|
|
|
return fs;
|
2017-07-21 21:44:55 +02:00
|
|
|
}
|
2017-07-22 02:01:26 +02:00
|
|
|
|
2019-02-12 20:50:06 +01:00
|
|
|
get id() {
|
|
|
|
let id = this.engine.getItem('device_id');
|
|
|
|
if (!id) {
|
|
|
|
id = arrayToB64(crypto.getRandomValues(new Uint8Array(16)));
|
|
|
|
this.engine.setItem('device_id', id);
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2017-07-21 21:44:55 +02:00
|
|
|
get totalDownloads() {
|
|
|
|
return Number(this.engine.getItem('totalDownloads'));
|
|
|
|
}
|
|
|
|
set totalDownloads(n) {
|
|
|
|
this.engine.setItem('totalDownloads', n);
|
|
|
|
}
|
|
|
|
get totalUploads() {
|
|
|
|
return Number(this.engine.getItem('totalUploads'));
|
|
|
|
}
|
|
|
|
set totalUploads(n) {
|
|
|
|
this.engine.setItem('totalUploads', n);
|
|
|
|
}
|
|
|
|
get referrer() {
|
|
|
|
return this.engine.getItem('referrer');
|
|
|
|
}
|
|
|
|
set referrer(str) {
|
|
|
|
this.engine.setItem('referrer', str);
|
|
|
|
}
|
2017-09-12 02:09:29 +02:00
|
|
|
get enrolled() {
|
|
|
|
return JSON.parse(this.engine.getItem('experiments') || '[]');
|
|
|
|
}
|
|
|
|
|
|
|
|
enroll(id, variant) {
|
|
|
|
const enrolled = this.enrolled;
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
if (!enrolled.find(([i, v]) => i === id)) {
|
|
|
|
enrolled.push([id, variant]);
|
|
|
|
this.engine.setItem('experiments', JSON.stringify(enrolled));
|
|
|
|
}
|
|
|
|
}
|
2017-07-22 02:01:26 +02:00
|
|
|
|
2017-07-21 21:44:55 +02:00
|
|
|
get files() {
|
2018-08-08 00:40:17 +02:00
|
|
|
return Array.from(this._files.values()).sort(
|
|
|
|
(a, b) => a.createdAt - b.createdAt
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get user() {
|
|
|
|
try {
|
|
|
|
return JSON.parse(this.engine.getItem('user'));
|
|
|
|
} catch (e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set user(info) {
|
|
|
|
return this.engine.setItem('user', JSON.stringify(info));
|
2017-07-21 21:44:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
getFileById(id) {
|
2018-08-08 00:40:17 +02:00
|
|
|
return this._files.get(id);
|
2017-07-21 21:44:55 +02:00
|
|
|
}
|
2017-07-22 02:01:26 +02:00
|
|
|
|
2017-09-12 02:09:29 +02:00
|
|
|
get(id) {
|
|
|
|
return this.engine.getItem(id);
|
|
|
|
}
|
|
|
|
|
2018-08-08 00:40:17 +02:00
|
|
|
set(id, value) {
|
|
|
|
return this.engine.setItem(id, value);
|
|
|
|
}
|
|
|
|
|
2017-07-21 21:44:55 +02:00
|
|
|
remove(property) {
|
2017-08-24 23:54:02 +02:00
|
|
|
if (isFile(property)) {
|
2018-08-08 00:40:17 +02:00
|
|
|
this._files.delete(property);
|
2017-08-24 23:54:02 +02:00
|
|
|
}
|
2017-07-21 21:44:55 +02:00
|
|
|
this.engine.removeItem(property);
|
|
|
|
}
|
2017-07-22 02:01:26 +02:00
|
|
|
|
2017-08-24 23:54:02 +02:00
|
|
|
addFile(file) {
|
2018-08-08 00:40:17 +02:00
|
|
|
this._files.set(file.id, file);
|
2018-01-24 19:23:13 +01:00
|
|
|
this.writeFile(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
writeFile(file) {
|
2017-08-24 23:54:02 +02:00
|
|
|
this.engine.setItem(file.id, JSON.stringify(file));
|
2017-07-21 21:44:55 +02:00
|
|
|
}
|
2017-08-31 18:43:36 +02:00
|
|
|
|
|
|
|
writeFiles() {
|
2018-01-24 19:23:13 +01:00
|
|
|
this._files.forEach(f => this.writeFile(f));
|
2017-08-31 18:43:36 +02:00
|
|
|
}
|
2018-08-08 00:40:17 +02:00
|
|
|
|
|
|
|
clearLocalFiles() {
|
|
|
|
this._files.forEach(f => this.engine.removeItem(f.id));
|
|
|
|
this._files = new Map();
|
|
|
|
}
|
|
|
|
|
|
|
|
async merge(files = []) {
|
|
|
|
let incoming = false;
|
|
|
|
let outgoing = false;
|
|
|
|
let downloadCount = false;
|
|
|
|
for (const f of files) {
|
|
|
|
if (!this.getFileById(f.id)) {
|
|
|
|
this.addFile(new OwnedFile(f));
|
|
|
|
incoming = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const workingFiles = this.files.slice();
|
|
|
|
for (const f of workingFiles) {
|
|
|
|
const cc = await f.updateDownloadCount();
|
2019-01-15 19:11:51 +01:00
|
|
|
if (cc) {
|
|
|
|
await this.writeFile(f);
|
|
|
|
}
|
2018-08-08 00:40:17 +02:00
|
|
|
downloadCount = downloadCount || cc;
|
|
|
|
outgoing = outgoing || f.expired;
|
|
|
|
if (f.expired) {
|
|
|
|
this.remove(f.id);
|
|
|
|
} else if (!files.find(x => x.id === f.id)) {
|
|
|
|
outgoing = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
incoming,
|
|
|
|
outgoing,
|
|
|
|
downloadCount
|
|
|
|
};
|
|
|
|
}
|
2017-07-21 21:44:55 +02:00
|
|
|
}
|
2017-08-24 23:54:02 +02:00
|
|
|
|
|
|
|
export default new Storage();
|