mirror of https://github.com/zulip/zulip.git
Add a LocalStorage wrapper for Zulip.
This is a wrapper that allows for versioning and migrations with localStorage along with safe storage of data that respects data types.
This commit is contained in:
parent
ce91a43eee
commit
8b22b94ab1
|
@ -87,6 +87,7 @@
|
|||
"fenced_code": false,
|
||||
"echo": false,
|
||||
"localstorage": false,
|
||||
"localStorage": false,
|
||||
"current_msg_list": true,
|
||||
"home_msg_list": false,
|
||||
"pm_list": false,
|
||||
|
|
|
@ -1,6 +1,149 @@
|
|||
var localstorage = (function () {
|
||||
|
||||
var exports = {};
|
||||
var ls = {
|
||||
// parse JSON without throwing an error.
|
||||
parseJSON: function (str) {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
// check if the datestamp is from before now and if so return true.
|
||||
isExpired: function (stamp) {
|
||||
return new Date(stamp) < new Date();
|
||||
},
|
||||
|
||||
// return the localStorage key that is bound to a version of a key.
|
||||
formGetter: function (version, name) {
|
||||
return "ls__" + version + "__" + name;
|
||||
},
|
||||
|
||||
// create a formData object to put in the data, a signature that it was
|
||||
// created with this library, and when it expires (if ever).
|
||||
formData: function (data, expires) {
|
||||
return {
|
||||
data: data,
|
||||
__valid: true,
|
||||
expires: new Date().getTime() + expires,
|
||||
};
|
||||
},
|
||||
|
||||
getData: function (version, name) {
|
||||
var key = this.formGetter(version, name);
|
||||
var data = localStorage.getItem(key);
|
||||
data = ls.parseJSON(data);
|
||||
|
||||
if (data) {
|
||||
if (data.__valid) {
|
||||
// JSON forms of data with `Infinity` turns into `null`,
|
||||
// so if null then it hasn't expired since nothing was specified.
|
||||
if (!ls.isExpired(data.expires) || data.expires === null) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// set the wrapped version of the data into localStorage.
|
||||
setData: function (version, name, data, expires) {
|
||||
var key = this.formGetter(version, name);
|
||||
var val = this.formData(data, expires);
|
||||
|
||||
localStorage.setItem(key, JSON.stringify(val));
|
||||
},
|
||||
|
||||
// remove the key from localStorage and from memory.
|
||||
removeData: function (version, name) {
|
||||
var key = this.formGetter(version, name);
|
||||
|
||||
localStorage.removeItem(key);
|
||||
},
|
||||
|
||||
// migrate from an older version of a data src to a newer one with a
|
||||
// specified callback function.
|
||||
migrate: function (name, v1, v2, callback) {
|
||||
var old = this.getData(v1, name);
|
||||
this.removeData(v1, name);
|
||||
|
||||
if (old && old.__valid) {
|
||||
var data = callback(old.data);
|
||||
this.setData(v2, name, data, Infinity);
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// return a new function instance that has instance-scoped variables.
|
||||
var exports = function () {
|
||||
var _data = {
|
||||
VERSION: 1,
|
||||
expires: Infinity,
|
||||
expiresIsGlobal: false,
|
||||
};
|
||||
|
||||
var prototype = {
|
||||
// `expires` should be a Number that represents the number of ms from
|
||||
// now that this should expire in.
|
||||
// this allows for it to either be set only once or permanently.
|
||||
setExpiry: function (expires, isGlobal) {
|
||||
_data.expires = expires;
|
||||
_data.expiresIsGlobal = isGlobal || false;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
get: function (name) {
|
||||
var data = ls.getData(_data.VERSION, name);
|
||||
|
||||
if (data) {
|
||||
return data.data;
|
||||
}
|
||||
},
|
||||
|
||||
set: function (name, data) {
|
||||
if (typeof _data.VERSION !== "undefined") {
|
||||
ls.setData(_data.VERSION, name, data, _data.expires);
|
||||
|
||||
// if the expires attribute was not set as a global, then
|
||||
// make sure to return it back to Infinity to not impose
|
||||
// constraints on the next key.
|
||||
if (!_data.expiresIsGlobal) {
|
||||
_data.expires = Infinity;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// remove a key with a given version.
|
||||
remove: function (name) {
|
||||
ls.removeData(_data.VERSION, name);
|
||||
},
|
||||
|
||||
migrate: function (name, v1, v2, callback) {
|
||||
return ls.migrate(name, v1, v2, callback);
|
||||
},
|
||||
};
|
||||
|
||||
// set a new master version for the LocalStorage instance.
|
||||
Object.defineProperty(prototype, "version", {
|
||||
get: function () {
|
||||
return _data.VERSION;
|
||||
},
|
||||
set: function (version) {
|
||||
_data.VERSION = version;
|
||||
|
||||
return prototype;
|
||||
},
|
||||
});
|
||||
|
||||
return prototype;
|
||||
};
|
||||
|
||||
var warned_of_localstorage = false;
|
||||
|
||||
|
@ -17,7 +160,6 @@ exports.supported = function supports_localstorage() {
|
|||
};
|
||||
|
||||
return exports;
|
||||
|
||||
}());
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
|
|
Loading…
Reference in New Issue