mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-25 07:51:12 +02:00
224 lines
5.5 KiB
JavaScript
224 lines
5.5 KiB
JavaScript
import './firebaseInit';
|
|
import firebase from 'firebase/app';
|
|
import 'firebase/firestore';
|
|
import { deferred } from './deferred';
|
|
import { trackEvent } from './analytics';
|
|
import { log } from './utils';
|
|
|
|
/**
|
|
* Converts a firestore query snapshot into native array
|
|
* @param {snapshot} querySnapshot Snapshot object returned by a firestore query
|
|
*/
|
|
function getArrayFromQuerySnapshot(querySnapshot) {
|
|
const arr = [];
|
|
querySnapshot.forEach(doc => {
|
|
// doc.data() has to be after doc.id because docs can have `id` key in them which
|
|
// should override the explicit `id` being set
|
|
arr.push({
|
|
id: doc.id,
|
|
...doc.data()
|
|
});
|
|
// documentCache[doc.id] = doc.data()
|
|
});
|
|
return arr;
|
|
}
|
|
|
|
(() => {
|
|
const FAUX_DELAY = 1;
|
|
|
|
var db;
|
|
var dbPromise;
|
|
|
|
var local = {
|
|
get: (obj, cb) => {
|
|
const retVal = {};
|
|
if (typeof obj === 'string') {
|
|
retVal[obj] = JSON.parse(window.localStorage.getItem(obj));
|
|
setTimeout(() => cb(retVal), FAUX_DELAY);
|
|
} else {
|
|
Object.keys(obj).forEach(key => {
|
|
const val = window.localStorage.getItem(key);
|
|
retVal[key] =
|
|
val === undefined || val === null ? obj[key] : JSON.parse(val);
|
|
});
|
|
setTimeout(() => cb(retVal), FAUX_DELAY);
|
|
}
|
|
},
|
|
set: (obj, cb) => {
|
|
Object.keys(obj).forEach(key => {
|
|
window.localStorage.setItem(key, JSON.stringify(obj[key]));
|
|
});
|
|
/* eslint-disable consistent-return */
|
|
setTimeout(() => {
|
|
if (cb) {
|
|
return cb();
|
|
}
|
|
}, FAUX_DELAY);
|
|
/* eslint-enable consistent-return */
|
|
},
|
|
remove: (key, cb) => {
|
|
window.localStorage.removeItem(key);
|
|
setTimeout(() => cb(), FAUX_DELAY);
|
|
}
|
|
};
|
|
const dbLocalAlias = chrome && chrome.storage ? chrome.storage.local : local;
|
|
const dbSyncAlias = chrome && chrome.storage ? chrome.storage.sync : local;
|
|
|
|
async function getDb() {
|
|
if (dbPromise) {
|
|
return dbPromise;
|
|
}
|
|
log('Initializing firestore');
|
|
dbPromise = new Promise((resolve, reject) => {
|
|
if (db) {
|
|
return resolve(db);
|
|
}
|
|
const firestoreInstance = firebase.firestore();
|
|
|
|
return firestoreInstance
|
|
.enablePersistence({ experimentalTabSynchronization: true })
|
|
.then(function () {
|
|
// Initialize Cloud Firestore through firebase
|
|
db = firebase.firestore();
|
|
// const settings = {
|
|
// timestampsInSnapshots: true
|
|
// };
|
|
// db.settings(settings);
|
|
log('firebase db ready', db);
|
|
resolve(db);
|
|
})
|
|
.catch(function (err) {
|
|
reject(err.code);
|
|
if (err.code === 'failed-precondition') {
|
|
// Multiple tabs open, persistence can only be enabled
|
|
// in one tab at a a time.
|
|
alert(
|
|
"Opening Web Maker web app in multiple tabs isn't supported at present and it seems like you already have it opened in another tab. Please use in one tab."
|
|
);
|
|
trackEvent('fn', 'multiTabError');
|
|
} else if (err.code === 'unimplemented') {
|
|
// The current browser does not support all of the
|
|
// features required to enable persistence
|
|
// ...
|
|
}
|
|
});
|
|
});
|
|
return dbPromise;
|
|
}
|
|
|
|
async function getUserLastSeenVersion() {
|
|
const d = deferred();
|
|
// Will be chrome.storage.sync in extension environment,
|
|
// otherwise will fallback to localstorage
|
|
dbSyncAlias.get(
|
|
{
|
|
lastSeenVersion: ''
|
|
},
|
|
result => {
|
|
d.resolve(result.lastSeenVersion);
|
|
}
|
|
);
|
|
return d.promise;
|
|
// Might consider getting actual value from remote db.
|
|
// Not critical right now.
|
|
}
|
|
|
|
async function setUserLastSeenVersion(version) {
|
|
// Setting the `lastSeenVersion` in localStorage(sync for extension) always
|
|
// because next time we need to fetch it irrespective of the user being
|
|
// logged in or out quickly from local storage.
|
|
dbSyncAlias.set(
|
|
{
|
|
lastSeenVersion: version
|
|
},
|
|
function () {}
|
|
);
|
|
if (window.user) {
|
|
const remoteDb = await getDb();
|
|
remoteDb.doc(`users/${window.user.uid}`).update({
|
|
lastSeenVersion: version
|
|
});
|
|
}
|
|
}
|
|
|
|
async function getUser(userId) {
|
|
const remoteDb = await getDb();
|
|
return remoteDb
|
|
.doc(`users/${userId}`)
|
|
.get()
|
|
.then(doc => {
|
|
if (!doc.exists) {
|
|
// return remoteDb.doc(`users/${userId}`).set(
|
|
// {},
|
|
// {
|
|
// merge: true
|
|
// }
|
|
// );
|
|
return {};
|
|
}
|
|
const user = doc.data();
|
|
|
|
return user;
|
|
});
|
|
}
|
|
|
|
async function fetchItem(itemId) {
|
|
const remoteDb = await getDb();
|
|
return remoteDb
|
|
.doc(`items/${itemId}`)
|
|
.get()
|
|
.then(doc => {
|
|
if (!doc.exists) return {};
|
|
const data = doc.data();
|
|
return data;
|
|
});
|
|
}
|
|
|
|
// Fetch user settings.
|
|
// This isn't hitting the remote db because remote settings
|
|
// get fetch asynchronously (in user/) and update the envioronment.
|
|
function getSettings(defaultSettings) {
|
|
const d = deferred();
|
|
// Will be chrome.storage.sync in extension environment,
|
|
// otherwise will fallback to localstorage
|
|
dbSyncAlias.get(defaultSettings, result => {
|
|
d.resolve(result);
|
|
});
|
|
return d.promise;
|
|
}
|
|
|
|
async function getPublicItemCount(userId) {
|
|
const remoteDb = await getDb();
|
|
return remoteDb
|
|
.collection('items')
|
|
.where('createdBy', '==', userId)
|
|
.where('isPublic', '==', true)
|
|
.get()
|
|
.then(snapShot => {
|
|
return snapShot.size;
|
|
});
|
|
}
|
|
|
|
async function getUserSubscriptionEvents(userId) {
|
|
const remoteDb = await getDb();
|
|
return remoteDb
|
|
.collection('subscriptions')
|
|
.where('userId', '==', userId)
|
|
.get()
|
|
.then(getArrayFromQuerySnapshot);
|
|
}
|
|
|
|
window.db = {
|
|
getDb,
|
|
getUser,
|
|
getUserLastSeenVersion,
|
|
setUserLastSeenVersion,
|
|
getSettings,
|
|
fetchItem,
|
|
getPublicItemCount,
|
|
getUserSubscriptionEvents,
|
|
local: dbLocalAlias,
|
|
sync: dbSyncAlias
|
|
};
|
|
})();
|