Compare commits

..

No commits in common. "b70b2211aba0a4c776ffe0ede38d09072deb3dea" and "30c9d4d4e8a620d19ae77ecad619285b890aad69" have entirely different histories.

10 changed files with 199 additions and 642 deletions

View File

@ -1,32 +0,0 @@
name: Workflow push to Dappbundle
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Executing remote command
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.R_HOST }}
username: ${{ secrets.P_USERNAME }}
password: ${{ secrets.P_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
script: |
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle" ]; then
echo "Folder exists. Skipping Git clone."
else
echo "Folder does not exist. Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/ && git clone https://github.com/ranchimall/dappbundle.git
fi
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" ]; then
echo "Repository exists. Remove folder "
rm -r "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}"
fi
echo "Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle && git clone https://github.com/ranchimall/${{ github.event.repository.name }}
cd "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" && rm -rf .gitattributes .git .github .gitignore
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/ && git add . && git commit -m "Workflow updating files of ${{ github.event.repository.name }}" && git push "https://ranchimalldev:${{ secrets.RM_ACCESS_TOKEN }}@github.com/ranchimall/dappbundle.git"

View File

@ -1069,7 +1069,6 @@ sm-copy {
}
#preview_page p {
font-size: 1rem;
white-space: pre-line;
}
#preview_page p * {
font-size: inherit;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
(function (EXPORTS) { //floCloudAPI v2.4.5a
(function (EXPORTS) { //floCloudAPI v2.4.3a
/* FLO Cloud operations to send/request application data*/
'use strict';
const floCloudAPI = EXPORTS;
@ -195,24 +195,14 @@
floCloudAPI.init = function startCloudProcess(nodes) {
return new Promise((resolve, reject) => {
try {
// accept only plain-ish objects
nodes = (nodes && typeof nodes === 'object' && !Array.isArray(nodes)) ? nodes : {};
supernodes = nodes;
// reset liveness bookkeeping for the new set
if (_inactive && typeof _inactive.clear === 'function') _inactive.clear();
// (re)build the bucket with current IDs
kBucket = new K_Bucket(DEFAULT.SNStorageID, Object.keys(supernodes));
resolve('Cloud init successful');
} catch (error) {
reject(error);
}
});
};
})
}
Object.defineProperty(floCloudAPI, 'kBucket', {
get: () => kBucket
@ -237,27 +227,24 @@
function ws_activeConnect(snID, reverse = false) {
return new Promise((resolve, reject) => {
// Safe guard: uninitialized kBucket, empty list, or all inactive
if (!kBucket || !kBucket.list || !kBucket.list.length || _inactive.size === kBucket.list.length)
if (_inactive.size === kBucket.list.length)
return reject('Cloud offline');
if (!(snID in supernodes)) {
var closest = kBucket.closestNode(proxyID(snID));
if (!closest) return reject('Cloud offline'); // no candidate to try
snID = closest;
}
if (!(snID in supernodes))
snID = kBucket.closestNode(proxyID(snID));
ws_connect(snID)
.then(node => resolve(node))
.catch(error => {
var nxtNode = reverse ? kBucket.prevNode(snID) : kBucket.nextNode(snID);
if (!nxtNode || nxtNode === snID) return reject('Cloud offline'); // nothing else to try
ws_activeConnect(nxtNode, reverse).then(resolve).catch(reject);
});
});
if (reverse)
var nxtNode = kBucket.prevNode(snID);
else
var nxtNode = kBucket.nextNode(snID);
ws_activeConnect(nxtNode, reverse)
.then(node => resolve(node))
.catch(error => reject(error))
})
})
}
function fetch_API(snID, data) {
return new Promise((resolve, reject) => {
if (_inactive.has(snID))
@ -278,28 +265,25 @@
function fetch_ActiveAPI(snID, data, reverse = false) {
return new Promise((resolve, reject) => {
// Safe guard: uninitialized kBucket, empty list, or all inactive
if (!kBucket || !kBucket.list || !kBucket.list.length || _inactive.size === kBucket.list.length)
if (_inactive.size === kBucket.list.length)
return reject('Cloud offline');
if (!(snID in supernodes)) {
var closest = kBucket.closestNode(proxyID(snID));
if (!closest) return reject('Cloud offline'); // no candidate available
snID = closest;
}
if (!(snID in supernodes))
snID = kBucket.closestNode(proxyID(snID));
fetch_API(snID, data)
.then(resolve)
.then(result => resolve(result))
.catch(error => {
_inactive.add(snID);
var nxtNode = reverse ? kBucket.prevNode(snID) : kBucket.nextNode(snID);
if (!nxtNode || nxtNode === snID) return reject('Cloud offline'); // nothing else to try
fetch_ActiveAPI(nxtNode, data, reverse).then(resolve).catch(reject);
});
});
_inactive.add(snID)
if (reverse)
var nxtNode = kBucket.prevNode(snID);
else
var nxtNode = kBucket.nextNode(snID);
fetch_ActiveAPI(nxtNode, data, reverse)
.then(result => resolve(result))
.catch(error => reject(error));
})
})
}
function singleRequest(floID, data_obj, method = "POST") {
return new Promise((resolve, reject) => {
let data;
@ -390,31 +374,13 @@
const util = floCloudAPI.util = {};
//Updating encoding/Decoding to modern standards
const encodeMessage = util.encodeMessage = function (message) {
const bytes = new TextEncoder().encode(JSON.stringify(message));
let bin = "";
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
return btoa(bin);
};
return btoa(unescape(encodeURIComponent(JSON.stringify(message))))
}
const decodeMessage = util.decodeMessage = function (message) {
try {
// try modern decode first
const bin = atob(message);
const bytes = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
return JSON.parse(new TextDecoder().decode(bytes));
} catch (e1) {
try {
// fallback to legacy decode
return JSON.parse(decodeURIComponent(escape(atob(message))));
} catch (e2) {
// final fallback: return raw string to avoid hard crash
return message;
}
}
};
return JSON.parse(decodeURIComponent(escape(atob(message))))
}
const filterKey = util.filterKey = function (type, options = {}) {
return type + (options.comment ? ':' + options.comment : '') +
@ -502,59 +468,21 @@
function storeGeneral(fk, dataSet) {
try {
if (!dataSet || typeof dataSet !== "object") return;
// Ensure containers exist
if (typeof generalData[fk] !== "object" || generalData[fk] === null)
generalData[fk] = {};
if (typeof lastVC[fk] !== "number")
lastVC[fk] = 0;
// Merge data and track latest log_time
let updated = false;
let newLast = lastVC[fk];
for (const vc in dataSet) {
const rec = dataSet[vc];
// Skip bad records
if (!rec || typeof rec !== "object") continue;
// Assign only if changed reference (cheap check)
if (generalData[fk][vc] !== rec) {
generalData[fk][vc] = rec;
updated = true;
}
if (typeof rec.log_time === "number" && rec.log_time > newLast) {
newLast = rec.log_time;
updated = true;
}
console.log(dataSet)
if (typeof generalData[fk] !== "object")
generalData[fk] = {}
for (let vc in dataSet) {
generalData[fk][vc] = dataSet[vc];
if (dataSet[vc].log_time > lastVC[fk])
lastVC[fk] = dataSet[vc].log_time;
}
if (!updated) return; // nothing new, avoid IDB writes
lastVC[fk] = newLast;
// --- Debounce writes per fk to avoid IDB thrash ---
storeGeneral._pending = storeGeneral._pending || Object.create(null);
const pend = storeGeneral._pending;
clearTimeout(pend[fk]);
pend[fk] = setTimeout(() => {
try {
// Fire-and-forget; callers dont wait on these
compactIDB.writeData("lastVC", lastVC[fk], fk);
compactIDB.writeData("generalData", generalData[fk], fk);
} catch (e) {
console.error(e);
}
}, 50);
compactIDB.writeData("lastVC", lastVC[fk], fk)
compactIDB.writeData("generalData", generalData[fk], fk)
} catch (error) {
console.error(error);
console.error(error)
}
}
function objectifier(data) {
if (!Array.isArray(data))
data = [data];
@ -623,7 +551,7 @@
}
//request any data from supernode cloud
const _requestApplicationData = function (type, options = {}) {
const requestApplicationData = floCloudAPI.requestApplicationData = function (type, options = {}) {
return new Promise((resolve, reject) => {
var request = {
receiverID: options.receiverID || DEFAULT.adminID,
@ -654,17 +582,6 @@
})
}
floCloudAPI.requestApplicationData = function (type, options = {}) {
return new Promise((resolve, reject) => {
let single_request_mode = !(options.callback instanceof Function);
_requestApplicationData(type, options).then(data => {
if (single_request_mode)
resolve(objectifier(data))
else resolve(data);
}).catch(error => reject(error))
})
}
/*(NEEDS UPDATE)
//delete data from supernode cloud (received only)
floCloudAPI.deleteApplicationData = function(vectorClocks, options = {}) {
@ -692,39 +609,49 @@
})
}
*/
//edit comment of data in supernode cloud (sender only)
floCloudAPI.editApplicationData = function (vectorClock, comment_edit, options = {}) {
/*(NEEDS UPDATE)
//edit comment of data in supernode cloud (mutable comments only)
floCloudAPI.editApplicationData = function(vectorClock, newComment, oldData, options = {}) {
return new Promise((resolve, reject) => {
//request the data from cloud for resigning
let req_options = Object.assign({}, options);
req_options.atVectorClock = vectorClock;
_requestApplicationData(undefined, req_options).then(result => {
if (!result.length)
return reject("Data not found");
let data = result[0];
if (data.senderID !== user.id)
return reject("Only sender can edit comment");
data.comment = comment_edit;
let hashcontent = ["receiverID", "time", "application", "type", "message", "comment"]
.map(d => data[d]).join("|");
let re_sign = user.sign(hashcontent);
var request = {
receiverID: options.receiverID || DEFAULT.adminID,
let p0
if (!oldData) {
options.atVectorClock = vectorClock;
options.callback = false;
p0 = requestApplicationData(false, options)
} else
p0 = Promise.resolve({
vectorClock: {
...oldData
}
})
p0.then(d => {
if (d.senderID != user.id)
return reject("Invalid requestorID")
else if (!d.comment.startsWith("EDIT:"))
return reject("Data immutable")
let data = {
requestorID: user.id,
pubKey: user.public,
receiverID: d.receiverID,
time: Date.now(),
vectorClock: vectorClock,
edit: comment_edit,
re_sign: re_sign
application: d.application,
edit: {
vectorClock: vectorClock,
comment: newComment
}
}
let request_hash = ["time", "vectorClock", "edit", "re_sign"].map(d => request[d]).join("|");
request.sign = user.sign(request_hash);
singleRequest(request.receiverID, request)
.then(result => resolve(result))
d.comment = data.edit.comment;
let hashcontent = ["receiverID", "time", "application", "type", "message",
"comment"
]
.map(x => d[x]).join("|")
data.edit.sign = user.sign(hashcontent)
singleRequest(data.receiverID, data)
.then(result => resolve("Data comment updated"))
.catch(error => reject(error))
}).catch(error => reject(error))
})
})
}
*/
//tag data in supernode cloud (subAdmin access only)
floCloudAPI.tagApplicationData = function (vectorClock, tag, options = {}) {
@ -792,11 +719,11 @@
storeGeneral(fk, d);
options.callback(d, e)
}
_requestApplicationData(type, new_options)
requestApplicationData(type, new_options)
.then(result => resolve(result))
.catch(error => reject(error))
} else {
_requestApplicationData(type, options).then(dataSet => {
requestApplicationData(type, options).then(dataSet => {
storeGeneral(fk, objectifier(dataSet))
resolve(dataSet)
}).catch(error => reject(error))
@ -821,7 +748,7 @@
}
delete options.callback;
}
_requestApplicationData(objectName, options).then(dataSet => {
requestApplicationData(objectName, options).then(dataSet => {
updateObject(objectName, objectifier(dataSet));
delete options.comment;
options.lowerVectorClock = lastVC[objectName] + 1;
@ -829,11 +756,11 @@
if (callback) {
let new_options = Object.create(options);
new_options.callback = callback;
_requestApplicationData(objectName, new_options)
requestApplicationData(objectName, new_options)
.then(result => resolve(result))
.catch(error => reject(error))
} else {
_requestApplicationData(objectName, options).then(dataSet => {
requestApplicationData(objectName, options).then(dataSet => {
updateObject(objectName, objectifier(dataSet))
resolve(appObjects[objectName])
}).catch(error => reject(error))
@ -884,67 +811,6 @@
})
}
//upload file
floCloudAPI.uploadFile = function (fileBlob, type, options = {}) {
return new Promise((resolve, reject) => {
if (!(fileBlob instanceof File) && !(fileBlob instanceof Blob))
return reject("file must be instance of File/Blob");
fileBlob.arrayBuffer().then(arraybuf => {
let file_data = { type: fileBlob.type, name: fileBlob.name };
file_data.content = Crypto.util.bytesToBase64(new Uint8Array(arraybuf));
if (options.encrypt) {
let encryptionKey = options.encrypt === true ?
floGlobals.settings.encryptionKey : options.encrypt
file_data = floCrypto.encryptData(JSON.stringify(file_data), encryptionKey)
}
sendApplicationData(file_data, type, options)
.then(({ vectorClock, receiverID, type, application }) => resolve({ vectorClock, receiverID, type, application }))
.catch(error => reject(error))
}).catch(error => reject(error))
})
}
//download file
floCloudAPI.downloadFile = function (vectorClock, options = {}) {
return new Promise((resolve, reject) => {
options.atVectorClock = vectorClock;
_requestApplicationData(options.type, options).then(result => {
if (!result.length)
return reject("File not found");
result = result[0];
try {
let file_data = decodeMessage(result.message);
//file is encrypted: decryption required
if (file_data instanceof Object && "secret" in file_data) {
if (!options.decrypt)
return reject("Data is encrypted");
let decryptionKey = (options.decrypt === true) ? Crypto.AES.decrypt(user_private, aes_key) : options.decrypt;
if (!Array.isArray(decryptionKey))
decryptionKey = [decryptionKey];
let flag = false;
for (let key of decryptionKey) {
try {
let tmp = floCrypto.decryptData(file_data, key);
file_data = JSON.parse(tmp);
flag = true;
break;
} catch (error) { }
}
if (!flag)
return reject("Unable to decrypt file: Invalid private key");
}
//reconstruct the file
let arraybuf = new Uint8Array(Crypto.util.base64ToBytes(file_data.content))
result.file = new File([arraybuf], file_data.name, { type: file_data.type });
resolve(result)
} catch (error) {
console.error(error);
reject("Data is not a file");
}
}).catch(error => reject(error))
})
}
/*
Functions:
findDiff(original, updatedObj) returns an object with the added, deleted and updated differences
@ -1186,4 +1052,4 @@
})();
})('object' === typeof module ? module.exports : window.floCloudAPI = {});
})('object' === typeof module ? module.exports : window.floCloudAPI = {});

View File

@ -1,4 +1,4 @@
(function (EXPORTS) { //floDapps v2.4.1
(function (EXPORTS) { //floDapps v2.4.0
/* General functions for FLO Dapps*/
'use strict';
const floDapps = EXPORTS;
@ -144,7 +144,7 @@
}
});
var subAdmins = [], trustedIDs = [], settings = {};
var subAdmins, trustedIDs, settings;
Object.defineProperties(floGlobals, {
subAdmins: {
get: () => subAdmins
@ -172,7 +172,12 @@
//general
lastTx: {},
//supernode (cloud list)
supernodes: {}
supernodes: {
indexes: {
uri: null,
pubKey: null
}
}
}
var obs_a = {
//login credentials
@ -249,154 +254,103 @@
const startUpFunctions = [];
startUpFunctions.push(function readSupernodeListFromAPI() {
return new Promise((resolve) => {
return new Promise((resolve, reject) => {
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
const CLOUD_KEY = "floCloudAPI#" + floCloudAPI.SNStorageID;
// Fallback: init from cached nodes (never reject)
const initFromCache = (tag) =>
compactIDB.readData("supernodes", CLOUD_KEY, DEFAULT.root)
.then(nodes => {
nodes = nodes || {};
return floCloudAPI.init(nodes)
.then(r => resolve(`${tag} (from cache)\n${r}`))
.catch(() => resolve(`${tag} (cache present, init skipped)`));
})
.catch(() => resolve(`${tag} (no cache)`));
compactIDB.readData("lastTx", CLOUD_KEY, DEFAULT.root).then(lastTx => {
const query_options = { sentOnly: true, pattern: floCloudAPI.SNStorageName };
if (typeof lastTx === 'number') // backward support (tx count)
compactIDB.readData("lastTx", floCloudAPI.SNStorageID, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: floCloudAPI.SNStorageName };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx === 'string') // last txid
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
// Try online; if it fails, fall back to cache
//fetch data from flosight
floBlockchainAPI.readData(floCloudAPI.SNStorageID, query_options).then(result => {
compactIDB.readData("supernodes", CLOUD_KEY, DEFAULT.root).then(nodes => {
nodes = nodes || {};
for (let i = result.data.length - 1; i >= 0; i--) {
const content = JSON.parse(result.data[i])[floCloudAPI.SNStorageName];
if (!content || typeof content !== 'object') continue;
if (content.removeNodes)
for (let sn in content.removeNodes) delete nodes[sn];
if (content.newNodes)
for (let sn in content.newNodes) nodes[sn] = content.newNodes[sn];
if (content.updateNodes)
for (let sn in content.updateNodes)
if (sn in nodes) nodes[sn].uri = content.updateNodes[sn];
}
Promise.all([
compactIDB.writeData("lastTx", result.lastItem, CLOUD_KEY, DEFAULT.root),
compactIDB.writeData("supernodes", nodes, CLOUD_KEY, DEFAULT.root)
]).then(() => {
floCloudAPI.init(nodes)
.then(r => resolve("Loaded Supernode list\n" + r))
.catch(() => resolve("Loaded Supernode list (init deferred)"));
}).catch(() => resolve("Supernode list updated (persist partial)"));
}).catch(() => initFromCache("Supernode list read failed"));
}).catch(() => initFromCache("Supernode network fetch failed"));
}).catch(() => initFromCache("Supernode lastTx read failed"));
});
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[floCloudAPI.SNStorageName];
for (let sn in content.removeNodes)
compactIDB.removeData("supernodes", sn, DEFAULT.root);
for (let sn in content.newNodes)
compactIDB.writeData("supernodes", content.newNodes[sn], sn, DEFAULT.root);
for (let sn in content.updateNodes)
compactIDB.readData("supernodes", sn, DEFAULT.root).then(r => {
r = r || {}
r.uri = content.updateNodes[sn];
compactIDB.writeData("supernodes", r, sn, DEFAULT.root);
});
}
compactIDB.writeData("lastTx", result.lastItem, floCloudAPI.SNStorageID, DEFAULT.root);
compactIDB.readAllData("supernodes", DEFAULT.root).then(nodes => {
floCloudAPI.init(nodes)
.then(result => resolve("Loaded Supernode list\n" + result))
.catch(error => reject(error))
})
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function readAppConfigFromAPI() {
return new Promise((resolve) => {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return resolve("No configs for this app");
// small helper: load cached directives into memory and resolve
const loadFromIDB = (msg) => Promise.all([
compactIDB.readAllData("subAdmins"),
compactIDB.readAllData("trustedIDs"),
compactIDB.readAllData("settings")
]).then(([sub, trust, set]) => {
subAdmins = Object.keys(sub || {}); // arrays of IDs
trustedIDs = Object.keys(trust || {});
settings = set || {};
resolve(msg);
}).catch(() => {
// safe defaults if cache missing
subAdmins = []; trustedIDs = []; settings = {};
resolve(msg + " (no local cache)");
});
// If cloud is disabled, use cached config and move on
if (!startUpOptions.cloud)
return loadFromIDB("Read app configuration from local cache (offline)");
const lastKey = `${DEFAULT.application}|${DEFAULT.adminID}`;
// Try to read lastTx; on failure, just use cache (dont block startup)
compactIDB.readData("lastTx", lastKey, DEFAULT.root).then(lastTx => {
const query_options = { sentOnly: true, pattern: DEFAULT.application };
if (typeof lastTx === 'number') query_options.ignoreOld = lastTx;
else if (typeof lastTx === 'string') query_options.after = lastTx;
// Fetch deltas from chain; on failure, fall back to cache
compactIDB.readData("lastTx", `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: DEFAULT.application };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
//fetch data from flosight
floBlockchainAPI.readData(DEFAULT.adminID, query_options).then(result => {
for (let i = result.data.length - 1; i >= 0; i--) {
const content = JSON.parse(result.data[i])[DEFAULT.application];
if (!content || typeof content !== "object") continue;
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[DEFAULT.application];
if (!content || typeof content !== "object")
continue;
if (Array.isArray(content.removeSubAdmin))
for (let j = 0; j < content.removeSubAdmin.length; j++)
for (var j = 0; j < content.removeSubAdmin.length; j++)
compactIDB.removeData("subAdmins", content.removeSubAdmin[j]);
if (Array.isArray(content.addSubAdmin))
for (let k = 0; k < content.addSubAdmin.length; k++)
for (var k = 0; k < content.addSubAdmin.length; k++)
compactIDB.writeData("subAdmins", true, content.addSubAdmin[k]);
if (Array.isArray(content.removeTrustedID))
for (let j = 0; j < content.removeTrustedID.length; j++)
for (var j = 0; j < content.removeTrustedID.length; j++)
compactIDB.removeData("trustedIDs", content.removeTrustedID[j]);
if (Array.isArray(content.addTrustedID))
for (let k = 0; k < content.addTrustedID.length; k++)
for (var k = 0; k < content.addTrustedID.length; k++)
compactIDB.writeData("trustedIDs", true, content.addTrustedID[k]);
if (content.settings)
for (let l in content.settings)
compactIDB.writeData("settings", content.settings[l], l);
compactIDB.writeData("settings", content.settings[l], l)
}
// persist last item marker (best effort)
compactIDB.writeData("lastTx", result.lastItem, lastKey, DEFAULT.root).catch(() => {});
// load fresh values from IDB into memory and finish
loadFromIDB("Read app configuration from blockchain");
}).catch(() => {
// network failed → boot from cache
loadFromIDB("Read app configuration from local cache (network fail)");
});
}).catch(() => {
// couldn't read lastTx → still boot from cache
loadFromIDB("Read app configuration from local cache (no lastTx)");
});
});
compactIDB.writeData("lastTx", result.lastItem, `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root);
compactIDB.readAllData("subAdmins").then(result => {
subAdmins = Object.keys(result);
compactIDB.readAllData("trustedIDs").then(result => {
trustedIDs = Object.keys(result);
compactIDB.readAllData("settings").then(result => {
settings = result;
resolve("Read app configuration from blockchain");
})
})
})
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function loadDataFromAppIDB() {
return new Promise((resolve, reject) => {
const loadData = ["appObjects", "generalData", "lastVC"];
// If cloud is disabled AND no IDB stores are expected, skip early
if (!startUpOptions.cloud && (!initIndexedDB.appObs || Object.keys(initIndexedDB.appObs).length === 0))
return resolve("No cloud and no local data to load");
// Otherwise, read from IDB
Promise.all(loadData.map(item => compactIDB.readAllData(item)))
.then(results => {
for (let i = 0; i < loadData.length; i++)
floGlobals[loadData[i]] = results[i];
resolve("Loaded Data from app IDB");
})
.catch(error => reject(error));
});
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
var loadData = ["appObjects", "generalData", "lastVC"]
var promises = []
for (var i = 0; i < loadData.length; i++)
promises[i] = compactIDB.readAllData(loadData[i])
Promise.all(promises).then(results => {
for (var i = 0; i < loadData.length; i++)
floGlobals[loadData[i]] = results[i]
resolve("Loaded Data from app IDB")
}).catch(error => reject(error))
})
});
var keyInput = type => new Promise((resolve, reject) => {
@ -888,4 +842,4 @@
.catch(error => reject(error))
}).catch(error => reject(error))
});
})('object' === typeof module ? module.exports : window.floDapps = {});
})('object' === typeof module ? module.exports : window.floDapps = {});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long