Use the FS store as default store

pull/1/head
yflory 8 years ago
parent aa14ea7ac4
commit 118829617f

@ -0,0 +1,180 @@
define([
'/api/config?cb=' + Math.random().toString().slice(2),
'/customize/messages.js?app=fs',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'/file/fileObject.js'
], function (Config, Messages, Listmap, Crypto, TextPatcher, FO) {
/*
This module uses localStorage, which is synchronous, but exposes an
asyncronous API. This is so that we can substitute other storage
methods.
To override these methods, create another file at:
/customize/storage.js
*/
var Store = {};
var storeObj;
var ready = false;
var filesOp;
var safeSet = function (key, val) {
storeObj[key] = val;
};
// Store uses nodebacks...
Store.set = function (key, val, cb) {
safeSet(key, val);
cb();
};
// implement in alternative store
Store.setBatch = function (map, cb) {
Object.keys(map).forEach(function (key) {
safeSet(key, val);
});
cb(void 0, map);
};
var safeGet = window.safeGet = function (key) {
return storeObj[key];
};
Store.get = function (key, cb) {
cb(void 0, safeGet(key));
};
// implement in alternative store
Store.getBatch = function (keys, cb) {
var res = {};
keys.forEach(function (key) {
res[key] = safeGet(key);
});
cb(void 0, res);
};
var safeRemove = function (key) {
delete storeObj[key];
};
Store.remove = function (key, cb) {
safeRemove(key);
cb();
};
// implement in alternative store
Store.removeBatch = function (keys, cb) {
keys.forEach(function (key) {
safeRemove(key);
});
cb();
};
Store.keys = function (cb) {
cb(void 0, Object.keys(storeObj));
};
Store.addPad = function (href, data) {
filesOp.addPad(href, data);
};
Store.forgetPad = function (href, cb) {
filesOp.forgetPad(href);
cb();
};
var changeHandlers = Store.changeHandlers = [];
Store.change = function (f) {
if (typeof(f) !== 'function') {
throw new Error('[Store.change] callback must be a function');
}
changeHandlers.push(f);
if (changeHandlers.length === 1) {
// start listening for changes
/* TODO: listen for changes in the proxy
window.addEventListener('storage', function (e) {
changeHandlers.forEach(function (f) {
f({
key: e.key,
oldValue: e.oldValue,
newValue: e.newValue,
});
});
});
*/
}
};
var onReady = function (f, proxy, storageKey) {
filesOp = FO.init(proxy, {
storageKey: storageKey
});
storeObj = proxy;
ready = true;
if (typeof(f) === 'function') {
f(void 0, Store);
}
};
var init = function (f, Cryptpad) {
if (!Cryptpad) { return; }
var hash = localStorage.FS_hash;
var secret = Cryptpad.getSecrets(hash);
var listmapConfig = {
data: {},
websocketURL: Cryptpad.getWebsocketURL(),
channel: secret.channel,
readOnly: false,
validateKey: secret.keys.validateKey || undefined,
crypto: Crypto.createEncryptor(secret.keys),
};
var rt = window.rt = Listmap.create(listmapConfig);
rt.proxy.on('create', function (info) {
var realtime = info.realtime;
localStorage.FS_hash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
window.patchText = TextPatcher.create({
realtime: realtime,
logging: true,
});
}).on('ready', function () {
if (JSON.stringify(rt.proxy) === '{}') {
var oldStore = Cryptpad.getStore(true);
oldStore.get(Cryptpad.storageKey, function (err, s) {
rt.proxy.filesData = s;
onReady(f, rt.proxy, Cryptpad.storageKey);
});
return;
}
onReady(f, rt.proxy, Cryptpad.storageKey);
})
.on('disconnect', function () {
//setEditable(false);
Cryptpad.alert(Messages.common_connectionLost);
});
};
Store.ready = function (f, Cryptpad) {
if (Cryptpad.parsePadUrl(window.location.href).type === "file") {
if (typeof(f) === 'function') {
f(void 0, Cryptpad.getStore(true));
}
return;
}
if (ready) {
if (typeof(f) === 'function') {
f(void 0, Store);
}
} else {
init(f, Cryptpad);
}
};
return Store;
});

@ -71,6 +71,12 @@ define(function () {
}
};
Store.addPad = function () {};
Store.forgetPad = function (href, cb) {
};
var changeHandlers = Store.changeHandlers = [];
Store.change = function (f) {

@ -7,10 +7,11 @@ define([
'/bower_components/spin.js/spin.min.js',
'/common/clipboard.js',
'/customize/fsStore.js',
'/customize/user.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Messages, Store, Crypto, Alertify, Spinner, Clipboard, User) {
], function (Config, Messages, Store, Crypto, Alertify, Spinner, Clipboard, FS, User) {
/* This file exposes functionality which is specific to Cryptpad, but not to
any particular pad type. This includes functions for committing metadata
about pads to your local storage for future use and improved usability.
@ -23,6 +24,7 @@ define([
User: User,
};
var store;
var fsStore;
var userProxy;
var userStore;
@ -34,7 +36,8 @@ define([
var getStore = common.getStore = function (legacy) {
if (!legacy && userStore) { return userStore; }
if (store) { return store; }
if (legacy) { return store; }
if (!legacy && fsStore) { return fsStore; }
throw new Error("Store is not ready!");
};
@ -94,7 +97,6 @@ define([
store = Store;
});
var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; };
var fixHTML = common.fixHTML = function (html) {
@ -163,13 +165,13 @@ define([
};
var getHashFromKeys = common.getHashFromKeys = getEditHashFromKeys;
var getSecrets = common.getSecrets = function () {
var getSecrets = common.getSecrets = function (secretHash) {
var secret = {};
if (!/#/.test(window.location.href)) {
if (!secretHash && !/#/.test(window.location.href)) {
secret.keys = Crypto.createEditCryptor();
secret.key = Crypto.createEditCryptor().editKeyStr;
} else {
var hash = window.location.hash.slice(1);
var hash = secretHash || window.location.hash.slice(1);
if (hash.length === 0) {
secret.keys = Crypto.createEditCryptor();
secret.key = Crypto.createEditCryptor().editKeyStr;
@ -380,26 +382,13 @@ define([
var forgetPad = common.forgetPad = function (href, cb, legacy) {
var parsed = parsePadUrl(href);
getRecentPads(function (err, recentPads) {
setRecentPads(recentPads.filter(function (pad) {
var p = parsePadUrl(pad.href);
// find duplicates
if (parsed.hash === p.hash && parsed.type === p.type) {
console.log("Found a duplicate");
return;
}
return true;
}), function (err, data) {
var callback = function (err, data) {
if (err) {
cb(err);
return;
}
getStore(legacy).keys(function (err, keys) {
if (err) {
cb(err);
return;
}
var toRemove = keys.filter(function (k) {
return k.indexOf(parsed.hash) === 0;
});
@ -412,8 +401,12 @@ define([
cb(err, data);
});
});
}, legacy);
}, legacy);
};
if (typeof(getStore(legacy).forgetPad) === "function") {
// TODO implement forgetPad in store.js
getStore(legacy).forgetPad(href, callback);
}
};
// STORAGE
@ -462,7 +455,12 @@ define([
});
if (!contains) {
renamed.push(makePad(href, name));
var data = makePad(href, name);
renamed.push(data);
if (typeof(getStore(legacy).addPad) === "function") {
//TODO implement addPad in store.js
getStore().addPad(href);
}
}
setRecentPads(renamed, function (err, data) {
@ -535,8 +533,8 @@ define([
f(void 0, env);
};
Store.ready(function (err, store) {
common.store = env.store = store;
FS.ready(function (err, store) {
fsStore = common.store = env.store = store;
$(function() {
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
@ -597,7 +595,7 @@ define([
cb();
}); */
});
}, common);
};
/*

@ -54,10 +54,12 @@ li {
border: 1px dotted #bbb;
background: #666;
color: #eee;
margin: -1px;
}
/* TREE */
#tree {
border: 2px solid blue;
box-sizing: border-box;
@ -194,6 +196,10 @@ li {
flex: 1;
}
#content li * {
pointer-events: none;
}
#content li:hover:not(.header) .name {
text-decoration: underline;
}

@ -12,6 +12,7 @@ define([
var NEW_FOLDER_NAME = Messages.fm_newFolder;
var init = module.init = function (files, config) {
FILES_DATA = config.storageKey;
var DEBUG = config.DEBUG || false;
var logging = console.log;
var log = config.log || logging;
@ -192,6 +193,16 @@ define([
return ret;
};
var getFilesDataFiles = function () {
var ret = [];
for (var el in files[FILES_DATA]) {
if (el.href && ret.indexOf(el.href) === -1) {
ret.push(el.href);
}
}
return ret;
};
var removeFileFromRoot = function (root, href) {
if (isFile(root)) { return; }
for (var e in root) {
@ -536,18 +547,39 @@ define([
pushToTrash(key, href, [UNSORTED]);
};
var addPad = exp.addPad = function (href, data) {
if (!getFileData(href)) {
files[FILES_DATA].push(data);
}
var addUnsortedPad = exp.addPad = function (href) {
var unsortedFiles = getUnsortedFiles().slice();
var rootFiles = getRootFiles().slice();
//var trashFiles = getTrashFiles().slice();
if (unsortedFiles.indexOf(href) === -1 && rootFiles.indexOf(href) === -1) {
var trashFiles = getTrashFiles().slice();
if (unsortedFiles.indexOf(href) === -1 && rootFiles.indexOf(href) === -1 && trashFiles.indexOf(href) === -1) {
files[UNSORTED].push(href);
}
};
var checkNewPads = exp.checkNewPads = function () {
var fd = files[FILES_DATA];
var rootFiles = getRootFiles().slice();
var unsortedFiles = getUnsortedFiles().slice();
var trashFiles = getTrashFiles().slice();
fd.forEach(function (el, idx) {
if (!el.href) { return; }
if (rootFiles.indexOf(el.href) === -1
&& unsortedFiles.indexOf(el.href) === -1
&& trashFiles.indexOf(el.href) === -1) {
debug("An element in filesData was not in ROOT, UNSORTED or TRASH.", el);
files[UNSORTED].push(el.href);
}
});
};
var checkRemovedPads = exp.checkRemovedPads = function () {
var fd = files[FILES_DATA];
var rootFiles = getRootFiles().slice();
var unsortedFiles = getUnsortedFiles().slice();
var trashFiles = getTrashFiles().slice();
};
var fixFiles = exp.fixFiles = function () {
// Explore the tree and check that everything is correct:
// * 'root', 'trash' and 'filesData' exist and are objects

@ -21,17 +21,13 @@ define([
//var hash = Cryptpad.getAttribute('FS_hash', cb);
var hash = localStorage.FS_hash;
if (hash) {
window.location.hash = hash;
}
var secret = Cryptpad.getSecrets();
var secret = Cryptpad.getSecrets(hash);
var ROOT = "root";
var ROOT_NAME = Messages.fm_rootName;
var UNSORTED = "unsorted";
var UNSORTED_NAME = Messages.fm_unsortedName;
var FILES_DATA = "filesData";
var FILES_DATA = Cryptpad.storageKey;
var FILES_DATA_NAME = Messages.fm_filesDataName;
var TRASH = "trash";
var TRASH_NAME = Messages.fm_trashName;
@ -44,6 +40,7 @@ define([
var NEW_FOLDER_NAME = Messages.fm_newFolder;
var config = {};
config.storageKey = FILES_DATA;
var DEBUG = config.DEBUG = true;
var debug = config.debug = DEBUG ? console.log : function() {return;};
var logError = config.logError = console.error;
@ -55,7 +52,7 @@ define([
}
};
var filesObject = module.files = {
var filesObject = {
root: {
"Directory 1": {
"Dir A": {
@ -213,7 +210,7 @@ define([
localStorage[LOCALSTORAGE_LAST] = JSON.stringify(path);
};
var initLSOpened = function () {
var initLocalStorage = function () {
try {
var store = JSON.parse(localStorage[LOCALSTORAGE_OPENED]);
if (!$.isArray(store)) {
@ -562,14 +559,13 @@ define([
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
// "dragenter" is fired for an element and all its children
// "dragleave" may be fired when entering a child
// --> we use pointer-events: none in CSS, but we still need a counter to avoid some issues
// --> We store the number of enter/leave and the element entered and we remove the
// highlighting only when we have left everything
var counter = 0;
var dragenterList = [];
$element.on('dragstart', function (e) {
e.stopPropagation();
counter = 0;
dragenterList = [];
onDrag(e.originalEvent, path);
});
@ -585,18 +581,15 @@ define([
$element.on('dragenter', function (e) {
e.preventDefault();
e.stopPropagation();
if (dragenterList.indexOf(e.target) !== -1) { return; }
dragenterList.push(e.target);
counter++;
$element.addClass('droppable');
});
$element.on('dragleave', function (e) {
e.preventDefault();
e.stopPropagation();
var idx = dragenterList.indexOf(e.target);
dragenterList.splice(idx, 1);
counter--;
if (counter <= 0) {
counter = 0;
$element.removeClass('droppable');
}
});
@ -1283,7 +1276,6 @@ define([
var realtime = module.realtime = info.realtime;
var editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
window.location.hash = editHash;
//Cryptpad.setAttribute("FS_hash", editHash, cb, store);
localStorage.FS_hash = editHash;
@ -1303,16 +1295,17 @@ define([
});
});*/
}).on('ready', function () {
module.files = rt.proxy;
if (JSON.stringify(rt.proxy) === '{}') {
var store = Cryptpad.getStore();
var store = Cryptpad.getStore(true);
store.get(Cryptpad.storageKey, function (err, s) {
rt.proxy.filesData = s;
initLSOpened();
rt.proxy[FILES_DATA] = s;
initLocalStorage();
init(rt.proxy);
});
return;
}
initLSOpened();
initLocalStorage();
init(rt.proxy);
})
.on('disconnect', function () {

Loading…
Cancel
Save