From 3e53a879e1ef8890f3fc84980dddfa4e43a726df Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Thu, 30 Jun 2016 00:57:55 +0200 Subject: [PATCH 1/5] Feat(localForage): Add TODO: localForage comments to indicate where changes have to be applied --- addon/adapters/base.js | 11 +++++++++++ addon/helpers/storage.js | 10 ++++++++++ addon/mixins/array.js | 1 + addon/mixins/object.js | 1 + addon/mixins/storage.js | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/addon/adapters/base.js b/addon/adapters/base.js index d36daa41..97c46adc 100644 --- a/addon/adapters/base.js +++ b/addon/adapters/base.js @@ -155,14 +155,20 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { storageKey = this._storageKey(type, id); if (id) { + // TODO: localForage - use getItem() + // TODO: localForage - no need to parse if isLocalForage return storage[storageKey] ? JSON.parse(storage[storageKey]) : null; } + // TODO: we can increase performance by using a forEarch and push to records array const records = this._getIndex(type) .filter(function(storageKey) { + // TODO: localForage - use getItem() return storage[storageKey]; }) .map(function(storageKey) { + // TODO: localForage - use getItem() + // TODO: localForage - no need to parse if isLocalForage return JSON.parse(storage[storageKey]); }); @@ -182,6 +188,8 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { const storageKey = this._storageKey(type, id); this._addToIndex(type, storageKey); + // TODO: localForage - use setItem() + // TODO: localForage - no need to stringify if isLocalForage get(this, '_storage')[storageKey] = JSON.stringify(record.data); return null; @@ -192,6 +200,8 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { const storageKey = this._storageKey(type, id); this._addToIndex(type, storageKey); + // TODO: localForage - use setItem() + // TODO: localForage - no need to stringify if isLocalForage get(this, '_storage')[storageKey] = JSON.stringify(record.data); return null; @@ -202,6 +212,7 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { const storageKey = this._storageKey(type, id); this._removeFromIndex(type, storageKey); + // TODO: localForage - use removeItem() delete get(this, '_storage')[storageKey]; return null; diff --git a/addon/helpers/storage.js b/addon/helpers/storage.js index e75da536..fee1066e 100644 --- a/addon/helpers/storage.js +++ b/addon/helpers/storage.js @@ -29,13 +29,22 @@ function tryStorage(name) { } function getStorage(name) { + // TODO: localForage add mappings for session and local + // local -> localStorageWrapper, etc if (storage[name]) { return storage[name]; } else { + // TODO: localForage - check if the localForage check is sufficient (safari private mode) + // TODO: localForage - if isLocalForage use localforage return storage[name] = tryStorage(name) || {}; } } +// TODO: localForage - add isLocalForage helper +function isLocalForage() { + return typeof localforage !== 'undefined' +} + let storages = {}; function storageFor(key, modelName, options = {}) { @@ -144,5 +153,6 @@ export { tryStorage, getStorage, storageFor, + isLocalForage, _resetStorages }; diff --git a/addon/mixins/array.js b/addon/mixins/array.js index fc896de1..84286a22 100644 --- a/addon/mixins/array.js +++ b/addon/mixins/array.js @@ -18,6 +18,7 @@ export default Ember.Mixin.create(StorageProxyMixin, { }, _clear: function() { + // TODO: localForage - use setItem set(this, 'content', Ember.A()); } }); diff --git a/addon/mixins/object.js b/addon/mixins/object.js index 8aa31590..339e291a 100644 --- a/addon/mixins/object.js +++ b/addon/mixins/object.js @@ -28,6 +28,7 @@ export default Ember.Mixin.create(StorageProxyMixin, { }, _clear: function() { + // TODO: localForage - use setItem set(this, 'content', {}); } }); diff --git a/addon/mixins/storage.js b/addon/mixins/storage.js index b86d4ad0..60ad35f2 100644 --- a/addon/mixins/storage.js +++ b/addon/mixins/storage.js @@ -54,6 +54,7 @@ export default Mixin.create({ set(this, '_initialContentString', JSON.stringify(initialContent)); + // TODO: localForage - use getItem() // Retrieve the serialized version from storage.. serialized = storage[storageKey]; @@ -86,6 +87,7 @@ export default Mixin.create({ const storage = this._storage(), storageKey = get(this, '_storageKey'); + // TODO: localForage - do we have to check for the driver? if (window.addEventListener) { window.addEventListener('storage', (event) => { if (event.storageArea === storage && event.key === storageKey) { @@ -114,12 +116,14 @@ export default Mixin.create({ initialContentString = get(this, '_initialContentString'); if (storageKey) { + // TODO: localForage - we don't have to stringify if isLocalForage() let json = JSON.stringify(content); if (json !== initialContentString) { set(this, '_isInitialContent', false); } + // TODO: localForage - use setItem() storage[storageKey] = json; } }, @@ -147,6 +151,7 @@ export default Mixin.create({ // returns void clear: function() { this._clear(); + // TODO: localForage - use removeItem() delete this._storage()[get(this, '_storageKey')]; } }); From 92327ce73ef2e399d9f45224eea31f87fb659d38 Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Thu, 30 Jun 2016 01:10:28 +0200 Subject: [PATCH 2/5] add missing semicolon --- addon/helpers/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/helpers/storage.js b/addon/helpers/storage.js index fee1066e..893c46e4 100644 --- a/addon/helpers/storage.js +++ b/addon/helpers/storage.js @@ -42,7 +42,7 @@ function getStorage(name) { // TODO: localForage - add isLocalForage helper function isLocalForage() { - return typeof localforage !== 'undefined' + return typeof localforage !== 'undefined'; } let storages = {}; From fa7016fe2e688650023d1b7c385b01fe0c6dd7a9 Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Thu, 30 Jun 2016 01:29:37 +0200 Subject: [PATCH 3/5] Small fixes --- addon/adapters/base.js | 9 +++++---- addon/helpers/storage.js | 4 ++-- addon/mixins/storage.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/addon/adapters/base.js b/addon/adapters/base.js index 97c46adc..f4c185ac 100644 --- a/addon/adapters/base.js +++ b/addon/adapters/base.js @@ -1,6 +1,7 @@ import Ember from 'ember'; import DS from 'ember-data'; import ImportExportMixin from '../mixins/adapters/import-export'; +import { isLocalForage } from '../helpers/storage'; const keys = Object.keys || Ember.keys; @@ -156,7 +157,7 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { if (id) { // TODO: localForage - use getItem() - // TODO: localForage - no need to parse if isLocalForage + // TODO: localForage - no need to parse if (isLocalForage()) return storage[storageKey] ? JSON.parse(storage[storageKey]) : null; } @@ -168,7 +169,7 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { }) .map(function(storageKey) { // TODO: localForage - use getItem() - // TODO: localForage - no need to parse if isLocalForage + // TODO: localForage - no need to parse if (isLocalForage()) return JSON.parse(storage[storageKey]); }); @@ -189,7 +190,7 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { this._addToIndex(type, storageKey); // TODO: localForage - use setItem() - // TODO: localForage - no need to stringify if isLocalForage + // TODO: localForage - no need to stringify if (isLocalForage()) get(this, '_storage')[storageKey] = JSON.stringify(record.data); return null; @@ -201,7 +202,7 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { this._addToIndex(type, storageKey); // TODO: localForage - use setItem() - // TODO: localForage - no need to stringify if isLocalForage + // TODO: localForage - no need to stringify if (isLocalForage()) get(this, '_storage')[storageKey] = JSON.stringify(record.data); return null; diff --git a/addon/helpers/storage.js b/addon/helpers/storage.js index 893c46e4..73501e2f 100644 --- a/addon/helpers/storage.js +++ b/addon/helpers/storage.js @@ -29,13 +29,13 @@ function tryStorage(name) { } function getStorage(name) { - // TODO: localForage add mappings for session and local + // TODO: localForage - add mappings for session and local if (isLocalForage()) // local -> localStorageWrapper, etc if (storage[name]) { return storage[name]; } else { // TODO: localForage - check if the localForage check is sufficient (safari private mode) - // TODO: localForage - if isLocalForage use localforage + // TODO: localForage - if (isLocalForage()) use localforage return storage[name] = tryStorage(name) || {}; } } diff --git a/addon/mixins/storage.js b/addon/mixins/storage.js index 60ad35f2..93bffcbb 100644 --- a/addon/mixins/storage.js +++ b/addon/mixins/storage.js @@ -116,7 +116,7 @@ export default Mixin.create({ initialContentString = get(this, '_initialContentString'); if (storageKey) { - // TODO: localForage - we don't have to stringify if isLocalForage() + // TODO: localForage - we don't have to stringify if (isLocalForage()) let json = JSON.stringify(content); if (json !== initialContentString) { From ca9e76098158e40ef60f52aaaaa965992f8f8781 Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Thu, 30 Jun 2016 01:31:34 +0200 Subject: [PATCH 4/5] Add isLocalForage import --- addon/mixins/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/mixins/storage.js b/addon/mixins/storage.js index 93bffcbb..037745d9 100644 --- a/addon/mixins/storage.js +++ b/addon/mixins/storage.js @@ -1,5 +1,5 @@ import Ember from 'ember'; -import { getStorage } from '../helpers/storage'; +import { getStorage, isLocalForage } from '../helpers/storage'; const get = Ember.get; const set = Ember.set; From 433c5c25238485e6b4e3f1955793b3cdaab9a17b Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Wed, 11 Jan 2017 20:36:14 +0800 Subject: [PATCH 5/5] Implement get/set/removeItem --- addon/adapters/base.js | 59 +++++++++++++++++++++++++++------------- addon/helpers/storage.js | 3 +- addon/mixins/storage.js | 8 ++++-- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/addon/adapters/base.js b/addon/adapters/base.js index 75ab8c75..6d599f9f 100644 --- a/addon/adapters/base.js +++ b/addon/adapters/base.js @@ -163,25 +163,32 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { _handleGETRequest(url, query) { const { type, id } = this._urlParts(url); - const storage = get(this, '_storage'), - storageKey = this._storageKey(type, id); + const storageKey = this._storageKey(type, id); + const storage = get(this, '_storage'); if (id) { - // TODO: localForage - use getItem() - // TODO: localForage - no need to parse if (isLocalForage()) - return storage[storageKey] ? JSON.parse(storage[storageKey]) : null; + if (isLocalForage()) { + return storage.getItem(storageKey); + } else { + return storage[storageKey] ? JSON.parse(storage[storageKey]) : null; + } } - // TODO: we can increase performance by using a forEarch and push to records array + // TODO: we can increase performance by using a forEarch and push to records array or just remove empty items const records = this._getIndex(type) .filter(function(storageKey) { - // TODO: localForage - use getItem() - return storage[storageKey]; + if (isLocalForage()) { + return storage.getItem(storageKey); + } else { + return storage[storageKey]; + } }) .map(function(storageKey) { - // TODO: localForage - use getItem() - // TODO: localForage - no need to parse if (isLocalForage()) - return JSON.parse(storage[storageKey]); + if (isLocalForage()) { + return storage.getItem(storageKey); + } else { + return JSON.parse(storage[storageKey]); + } }); if (query && query.filter) { @@ -198,23 +205,32 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { _handlePOSTRequest(url, record) { const { type, id } = record.data; const storageKey = this._storageKey(type, id); + const storage = get(this, '_storage'); this._addToIndex(type, storageKey); - // TODO: localForage - use setItem() - // TODO: localForage - no need to stringify if (isLocalForage()) - get(this, '_storage')[storageKey] = JSON.stringify(record.data); + + if (isLocalForage()) { + storage.setItem(storageKey, record.data); + } else { + storage[storageKey] = JSON.stringify(record.data); + } return null; }, + // TODO: Alias to _handlePOSTRequest _handlePATCHRequest(url, record) { const { type, id } = record.data; const storageKey = this._storageKey(type, id); + const storage = get(this, '_storage'); this._addToIndex(type, storageKey); - // TODO: localForage - use setItem() - // TODO: localForage - no need to stringify if (isLocalForage()) - get(this, '_storage')[storageKey] = JSON.stringify(record.data); + + if (isLocalForage()) { + storage.setItem(storageKey, record.data); + } else { + storage[storageKey] = JSON.stringify(record.data); + } return null; }, @@ -222,10 +238,15 @@ export default JSONAPIAdapter.extend(ImportExportMixin, { _handleDELETERequest(url) { const { type, id } = this._urlParts(url); const storageKey = this._storageKey(type, id); + const storage = get(this, '_storage'); this._removeFromIndex(type, storageKey); - // TODO: localForage - use removeItem() - delete get(this, '_storage')[storageKey]; + + if (isLocalForage()) { + storage.removeItem(storageKey); + } else { + delete storage[storageKey]; + } return null; }, diff --git a/addon/helpers/storage.js b/addon/helpers/storage.js index 91b8f59b..0b9db7ad 100644 --- a/addon/helpers/storage.js +++ b/addon/helpers/storage.js @@ -40,7 +40,8 @@ function getStorage(name) { } } -// TODO: localForage - add isLocalForage helper +// Detect if localforage is used +// TODO: localForage - maybe we should check the config as well? function isLocalForage() { return typeof localforage !== 'undefined'; } diff --git a/addon/mixins/storage.js b/addon/mixins/storage.js index 3f64a2c9..cd6378b8 100644 --- a/addon/mixins/storage.js +++ b/addon/mixins/storage.js @@ -120,15 +120,17 @@ export default Mixin.create({ initialContentString = get(this, '_initialContentString'); if (storageKey) { - // TODO: localForage - we don't have to stringify if (isLocalForage()) let json = JSON.stringify(content); if (json !== initialContentString) { set(this, '_isInitialContent', false); } - // TODO: localForage - use setItem() - storage[storageKey] = json; + if (isLocalForage()) { + storage.setItem(storageKey, content); + } else { + storage[storageKey] = json; + } } },