diff --git a/.eslintrc.json b/.eslintrc.json index f6fc534..8661b65 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -19,7 +19,7 @@ "computed-property-spacing": ["error", "never"], "consistent-return": "error", "consistent-this": "off", - "curly": "error", + "curly": "off", "default-case": "error", "dot-location": ["error", "property"], "dot-notation": "error", @@ -46,7 +46,7 @@ "new-parens": "error", "newline-after-var": "off", "newline-before-return": "off", - "newline-per-chained-call": "error", + "newline-per-chained-call": "off", "no-alert": "off", "no-array-constructor": "error", "no-bitwise": "off", @@ -201,6 +201,7 @@ "utils": true, "Promise": true, "Inlet": true, - "db": true + "db": true, + "firebase": true } } diff --git a/src/auth.js b/src/auth.js new file mode 100644 index 0000000..a8bdafb --- /dev/null +++ b/src/auth.js @@ -0,0 +1,66 @@ +window.logout = function logout() { + firebase.auth().signOut(); +}; +function login(providerName) { + var provider; + if (providerName === 'fb') { + provider = new firebase.auth.FacebookAuthProvider(); + } else if (providerName === 'twitter') { + provider = new firebase.auth.TwitterAuthProvider(); + } else if (providerName === 'google') { + provider = new firebase.auth.GoogleAuthProvider(); + provider.addScope('https://www.googleapis.com/auth/userinfo.profile'); + } else { + provider = new firebase.auth.GithubAuthProvider(); + } + + return firebase + .auth() + .signInWithPopup(provider) + .then(function(result) { + return; + // Save this user in the store + firebase + .database() + .ref('users/' + result.user.uid) + .update({ + displayName: result.user.displayName, + email: result.user.email, + photoURL: result.user.providerData[0].photoURL, + signedUpOn: Date.now() + }) + .then(function() { + // Port items in localstorage to user account + if (window.localStorage.prototyp) { + var items = JSON.parse(window.localStorage.prototyp); + var newItemKey; + items.forEach(function(localItem) { + itemService.fetchItem(localItem.id).then(function(item) { + newItemKey = firebase.database().ref('pens').push().key; + item.createdBy = result.user.uid; + delete item.uid; + firebase.database().ref('pens/' + newItemKey).set(item); + firebase + .database() + .ref('users/' + result.user.uid) + .child('items') + .child(newItemKey) + .set(true); + }); + }); + delete localStorage.prototyp; + } + }); + }) + .catch(function(error) { + // Handle Errors here. + var errorCode = error.code; + var errorMessage = error.message; + // The email of the user's account used. + var email = error.email; + // The firebase.auth.AuthCredential type that was used. + var credential = error.credential; + utils.log(error); + }); +} +window.login = login; diff --git a/src/db.js b/src/db.js index 9575e7c..3e91a0f 100644 --- a/src/db.js +++ b/src/db.js @@ -1,15 +1,18 @@ (() => { const FAUX_DELAY = 1; + + var db; + var dbPromise; + var local = { get: (obj, cb) => { + const retVal = {}; if (typeof obj === 'string') { - const retVal = {}; retVal[obj] = JSON.parse(window.localStorage.getItem(obj)); setTimeout(() => cb(retVal), FAUX_DELAY); } else { - const retVal = {}; Object.keys(obj).forEach(key => { - let val = window.localStorage.getItem(key); + const val = window.localStorage.getItem(key); retVal[key] = val === undefined || val === null ? obj[key] : JSON.parse(val); }); @@ -20,13 +23,118 @@ Object.keys(obj).forEach(key => { window.localStorage.setItem(key, JSON.stringify(obj[key])); }); + /* eslint-disable consistent-return */ setTimeout(() => { - if (cb) cb(); + if (cb) { + return cb(); + } }, FAUX_DELAY); + /* eslint-enable consistent-return */ } }; + 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; + } + utils.log('Initializing firestore'); + dbPromise = new Promise((resolve, reject) => { + if (db) { + return resolve(db); + } + return firebase + .firestore() + .enablePersistence() + .then(function() { + // Initialize Cloud Firestore through firebase + db = firebase.firestore(); + utils.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. + // ... + } 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) { + if (window.IS_EXTENSION) { + chrome.storage.sync.set( + { + lastSeenVersion: version + }, + function() {} + ); + return; + } + // Settings the lastSeenVersion in localStorage also because next time we need + // to fetch it irrespective of the user being logged in or out + local.set({ lastSeenVersion: version }); + 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 }); + const user = doc.data(); + Object.assign(window.user, user); + return user; + }); + } + + 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; + } + window.db = { - local: chrome && chrome.storage ? chrome.storage.local : local, - sync: chrome && chrome.storage ? chrome.storage.sync : local + getDb, + getUser, + getUserLastSeenVersion, + setUserLastSeenVersion, + getSettings, + local: dbLocalAlias, + sync: dbSyncAlias }; })(); diff --git a/src/index.html b/src/index.html index 8ebc9fb..24e2120 100644 --- a/src/index.html +++ b/src/index.html @@ -73,6 +73,13 @@ Open + + Login/Signup + + + Logout + +
@@ -315,6 +322,10 @@
+ +