From 414aa6c304c7ba107263d766f124746501b65bb7 Mon Sep 17 00:00:00 2001 From: sairaj mote Date: Mon, 22 Jan 2024 02:19:14 +0530 Subject: [PATCH] code refactoring and bug fixes --- index.html | 133 ++++++++-------------------------------- index.min.html | 10 +-- scripts/floDapps.min.js | 1 + 3 files changed, 31 insertions(+), 113 deletions(-) create mode 100644 scripts/floDapps.min.js diff --git a/index.html b/index.html index 1d0916c..44c3c9f 100644 --- a/index.html +++ b/index.html @@ -1210,10 +1210,6 @@ clone.querySelector('.article-card__read-time').textContent = `${readTime} Min read` clone.querySelector('.article-card__published').textContent = relativeTime.from(published) clone.querySelector('.article-card__image').src = heroImage ? `./images/${heroImage.thumbnail}` : '' - // getImage(articleID).then(image => { - // if (image.thumbnail) - // clone.querySelector('.article-card__image').src = image.thumbnail - // }) return clone }, trendingArticleCard(details) { @@ -1235,10 +1231,6 @@ clone.querySelector('.trending-article__published').textContent = relativeTime.from(published) clone.querySelector('.trending-article__summary').textContent = summary clone.querySelector('.trending-article__image').src = heroImage ? `./images/${heroImage.thumbnail}` : '' - // getImage(articleID).then(image => { - // if (image.thumbnail) - // clone.querySelector('.trending-article__image').src = image.thumbnail - // }) return clone }, requestCard(details) { @@ -1259,7 +1251,6 @@ const clone = getRef('article_row_template').content.cloneNode(true).firstElementChild clone.dataset.articleId = articleID clone.querySelector('.article-card__title').textContent = title - // clone.querySelector('.article-row__published').textContent = relativeTime.from(published) clone.querySelector('.article-row__votes').textContent = votes return clone }, @@ -1294,20 +1285,14 @@ const allImages = await compactIDB.readAllData('images') // Render trending article card sortedByVotes.slice(0, 4).forEach(articleDetail => { - frag.append(render.trendingArticleCard({ - ...articleDetail, - // heroImage: allImages[articleDetail.uid] ? allImages[articleDetail.uid].heroImage.thumbnail : '' - })) + frag.append(render.trendingArticleCard(articleDetail)) }) getRef('trending_article_container').innerHTML = '' getRef('trending_article_container').append(frag) // render latest articles const sortedArticles = sortedByVotes.slice(4).sort((a, b) => b.published - a.published) sortedArticles.slice(0, 6).forEach(articleDetail => { - frag.append(render.articleCard({ - ...articleDetail, - // heroImage: allImages[articleDetail.uid] ? allImages[articleDetail.uid].heroImage.thumbnail : '' - })) + frag.append(render.articleCard(articleDetail)) }) getRef('latest_articles_list').innerHTML = '' getRef('latest_articles_list').append(frag) @@ -1398,16 +1383,12 @@ } }, async explorePage(params) { - // const allImages = await compactIDB.readAllData('images') const { type, query } = params const frag = document.createDocumentFragment() const sortedByTime = getArrayOfObj(floGlobals.appObjects.rmTimes.articles).sort((a, b) => b.published - a.published) if (type === 'recent') { sortedByTime.forEach(articleDetail => { - frag.append(render.trendingArticleCard({ - ...articleDetail, - // heroImage: allImages[articleDetail.uid] ? allImages[articleDetail.uid].heroImage.thumbnail : '' - })) + frag.append(render.trendingArticleCard(articleDetail)) }) getRef('explore_heading').textContent = 'Explore all' } else { @@ -1415,10 +1396,7 @@ const fuse = new Fuse(sortedByTime, options) const searchResult = fuse.search(query).map(v => v.item) searchResult.forEach(articleDetail => { - frag.append(render.trendingArticleCard({ - ...articleDetail, - // heroImage: allImages[articleDetail.uid] ? allImages[articleDetail.uid].heroImage.thumbnail : '' - })) + frag.append(render.trendingArticleCard(articleDetail)) }) getRef('explore_heading').textContent = `${type === 'category' ? 'Explore' : 'Related to'} ${query}` } @@ -1592,6 +1570,9 @@ isSearchOn = false } } + if (!getRef('search_suggestions').classList.contains('hide')) { + getRef('search_suggestions').classList.add('hide') + } } getRef('search_articles').addEventListener('input', debounce((e) => { const searchKey = e.target.value.trim() @@ -1723,7 +1704,7 @@ let tempVoteCount = 0 getRef('upvote_button').addEventListener('mouseup', function () { - if (typeof myFloID !== 'undefined') { + if (typeof floDapps.user.id !== 'undefined') { tempVoteCount++; const animOptions = { fill: 'forwards', @@ -1777,7 +1758,7 @@ }) }) getRef('upvote_button').addEventListener('click', debounce(() => { - if (typeof myFloID !== 'undefined') { + if (typeof floDapps.user.id !== 'undefined') { floCloudAPI.sendApplicationData({ voteCount: tempVoteCount, }, `article_${pagesData.params.articleID}_votes`) @@ -2032,24 +2013,16 @@ } floGlobals.appObjects.adminData.articleVotes[articleID] = { votes: {} } } - floGlobals.appObjects.rmTimes.articles[articleID].categories = categories - floGlobals.appObjects.rmTimes.articles[articleID].contributors = contributors - floGlobals.appObjects.rmTimes.articles[articleID].title = title - floGlobals.appObjects.rmTimes.articles[articleID].tags = tags - floGlobals.appObjects.rmTimes.articles[articleID].readTime = readTime - floGlobals.appObjects.rmTimes.articles[articleID].summary = summary - floGlobals.appObjects.rmTimes.articles[articleID].heroImage = heroImage - // if (heroImage.hasOwnProperty('full')) { - // try { - // compactIDB.writeData('images', { heroImage }, articleID) - // const response = await floCloudAPI.sendApplicationData(heroImage, 'images') - // for (const key in response) { - // floGlobals.appObjects.rmTimes.articles[articleID].heroImage = response[key].vectorClock - // } - // } catch (err) { - // console.log(err) - // } - // } + floGlobals.appObjects.rmTimes.articles[articleID] = { + ...floGlobals.appObjects.rmTimes.articles[articleID], + title, + categories, + summary, + tags, + contributors, + heroImage, + readTime, + } Promise.all([ floCloudAPI.updateObjectData('rmTimes'), floCloudAPI.updateObjectData('adminData'), @@ -2126,9 +2099,7 @@ async function setArticleMetaData(details, articleID) { const { categories, title, tags, summary, published, contributors, heroImage } = details - // const articleImages = await compactIDB.readData('images', articleID) if (heroImage && heroImage.hasOwnProperty('full')) { - // getRef('preview_image').src = `./images/${heroImage}` getRef('select_full_image').value = heroImage.full; getRef('select_thumbnail_image').value = heroImage.thumbnail; } else { @@ -2203,21 +2174,7 @@ getConfirmation('Update article meta data?').then(async res => { if (res) { showLoader('UPDATING...') - // const { title, categories, summary, published, tags, contributors, heroImage } = getArticleMetaData() - console.log(getArticleMetaData()) floGlobals.appObjects.rmTimes.articles[articleID] = { ...floGlobals.appObjects.rmTimes.articles[articleID], ...getArticleMetaData() } - // if (heroImage.hasOwnProperty('full')) { - // try { - // compactIDB.writeData('images', { heroImage }, articleID) - // const response = await floCloudAPI.sendApplicationData(heroImage, 'images') - // for (const key in response) { - // floGlobals.appObjects.rmTimes.articles[articleID].heroImage = response[key].vectorClock - // } - // } catch (e) { - // notify(`Error uploading image`, 'error') - // console.error(e) - // } - // } floCloudAPI.updateObjectData('rmTimes').then(() => { notify(`Updated article meta data`, 'success') closePopup() @@ -2419,46 +2376,6 @@ }) } } - - let currentSelectedImage = {} - // getRef('select_image').addEventListener('change', function (e) { - // currentSelectedImage = {} - // if (this.files.length === 0) return - // const selectedFile = this.files[0] - // const reader = new FileReader(); - // reader.onload = function (e) { - // // show selected image in the preview - // getRef('preview_image').src = e.target.result; - // getRef('preview_image').addEventListener('load', function (event) { - // // Dynamically create a canvas element - // const canvas = createElement("canvas"); - // const context = canvas.getContext("2d"); - // const originalWidth = getRef('preview_image').width; - // const originalHeight = getRef('preview_image').height; - // const resizingFactor = parseFloat((1 / (originalWidth / 600)).toFixed(2)); - - // const canvasWidth = originalWidth * resizingFactor; - // const canvasHeight = originalHeight * resizingFactor; - - // canvas.width = canvasWidth; - // canvas.height = canvasHeight; - - // context.drawImage( - // getRef('preview_image'), - // 0, - // 0, - // originalWidth * resizingFactor, - // originalHeight * resizingFactor - // ); - // currentSelectedImage['thumbnail'] = canvas.toDataURL(selectedFile.type); - // }, { once: true }); - // currentSelectedImage.name = selectedFile.name - // currentSelectedImage.type = selectedFile.type - // currentSelectedImage.full = e.target.result - // } - // reader.readAsDataURL(this.files[0]); - // }) -
Cancel OK

Loading RanchiMall Times

Explore

No related articles

FLO address

Articles contributed

No articles written

Article by

In this article

Pick something to read
Analytics Requests Writers CC

No articles

No requests

No writers

Approve FLO IDs

Add FLO IDs that are allowed to submit article publishing requests from CC.

Add

No approved FLO IDs

Sign in

Liking an article supports and encourages the creators.

Sign In

New here? Generate your FLO credentials below to continue

FLO credentials

You can use FLO credentials with RanchiMall Times and all RanchiMall FLO apps.

FLO address
Private key
Sign in with these credentials Keep your private key secure and don't share with anyone. Once lost there is no way to recover private key.
Copy link
Title
Select category
Hero image
Summary
Add tags
contributors
FLO address
Name
Bio
Add writer

Settings

BTC integrated with FLO

You can use your FLO private key to perform transactions on the BTC network within our app ecosystem. The private key is the same for both.

My FLO address
My Bitcoin address
Sign out
Admin dashboard
Cancel OK

Loading RanchiMall Times

Explore

No related articles

FLO address

Articles contributed

No articles written

Article by

In this article

Pick something to read
Analytics Requests Writers CC

No articles

No requests

No writers

Approve FLO IDs

Add FLO IDs that are allowed to submit article publishing requests from CC.

Add

No approved FLO IDs

Sign in

Liking an article supports and encourages the creators.

Sign In

New here? Generate your FLO credentials below to continue

FLO credentials

You can use FLO credentials with RanchiMall Times and all RanchiMall FLO apps.

FLO address
Private key
Sign in with these credentials Keep your private key secure and don't share with anyone. Once lost there is no way to recover private key.
Copy link
Title
Select category
Hero image
Summary
Add tags
contributors
FLO address
Name
Bio
Add writer

Settings

BTC integrated with FLO

You can use your FLO private key to perform transactions on the BTC network within our app ecosystem. The private key is the same for both.

My FLO address
My Bitcoin address
Sign out
Admin dashboard
\ No newline at end of file +
${floDapps.user.id}
+ `),isShowingFloID=!0)}),6e4),floGlobals.isSubAdmin=floGlobals.subAdmins.includes(floDapps.user.id),floGlobals.isSubAdmin?(floGlobals.subAdminData={},getRef("publishing_requests").addEventListener("click",handleRequestClick),getRef("article_analytics").addEventListener("click",handleAnalyticsClick),getRef("writers_list").addEventListener("click",handleWritersClick),getRef("approved_ids").addEventListener("click",handleApprovedIDsClick),document.querySelectorAll(".admin-option").forEach((L=>L.classList.remove("hide")))):(getRef("publishing_requests").removeEventListener("click",handleRequestClick),getRef("article_analytics").removeEventListener("click",handleAnalyticsClick),getRef("writers_list").removeEventListener("click",handleWritersClick),getRef("approved_ids").removeEventListener("click",handleApprovedIDsClick),document.querySelectorAll(".admin-option").forEach((L=>L.classList.add("hide")))),console.log(L)})).catch((L=>console.error(L)))} \ No newline at end of file diff --git a/scripts/floDapps.min.js b/scripts/floDapps.min.js new file mode 100644 index 0000000..152132c --- /dev/null +++ b/scripts/floDapps.min.js @@ -0,0 +1 @@ +!function(EXPORTS){"use strict";const floDapps="object"===typeof module?module.exports:window.floDapps={},DEFAULT={root:"floDapps",application:floGlobals.application,adminID:floGlobals.adminID};var user_priv_raw,aes_key,user_priv_wrap;Object.defineProperties(floDapps,{application:{get:()=>DEFAULT.application},adminID:{get:()=>DEFAULT.adminID},root:{get:()=>DEFAULT.root}});const raw_user={get private(){if(!user_priv_raw)throw"User not logged in";return Crypto.AES.decrypt(user_priv_raw,aes_key)}};var user_id,user_public,user_private;const user=floDapps.user={get id(){if(!user_id)throw"User not logged in";return user_id},get public(){if(!user_public)throw"User not logged in";return user_public},get private(){if(user_private)return user_private instanceof Function?user_private():Crypto.AES.decrypt(user_private,aes_key);throw"User not logged in"},sign:message=>floCrypto.signData(message,raw_user.private),decrypt:data=>floCrypto.decryptData(data,raw_user.private),encipher:message=>Crypto.AES.encrypt(message,raw_user.private),decipher:data=>Crypto.AES.decrypt(data,raw_user.private),get db_name(){return"floDapps#"+floCrypto.toFloID(user.id)},lock(){user_private=user_priv_wrap},async unlock(){await user.private===raw_user.private&&(user_private=user_priv_raw)},get_contact(id){if(!user.contacts)throw"Contacts not available";if(user.contacts[id])return user.contacts[id];{let id_raw=floCrypto.decodeAddr(id).hex;for(let i in user.contacts)if(floCrypto.decodeAddr(i).hex==id_raw)return user.contacts[i]}},get_pubKey(id){if(!user.pubKeys)throw"Contacts not available";if(user.pubKeys[id])return user.pubKeys[id];{let id_raw=floCrypto.decodeAddr(id).hex;for(let i in user.pubKeys)if(floCrypto.decodeAddr(i).hex==id_raw)return user.pubKeys[i]}},clear(){user_id=user_public=user_private=void 0,user_priv_raw=aes_key=void 0,delete user.contacts,delete user.pubKeys,delete user.messages}};var subAdmins,trustedIDs,settings;function initIndexedDB(){return new Promise(((resolve,reject)=>{var obs_a={credentials:{},subAdmins:{},trustedIDs:{},settings:{},appObjects:{},generalData:{},lastVC:{}};initIndexedDB.appObs=initIndexedDB.appObs||{};for(let o in initIndexedDB.appObs)o in obs_a||(obs_a[o]=initIndexedDB.appObs[o]);Promise.all([compactIDB.initDB(DEFAULT.application,obs_a),compactIDB.initDB(DEFAULT.root,{lastTx:{},supernodes:{}})]).then((result=>{compactIDB.setDefaultDB(DEFAULT.application),resolve("IndexedDB App Storage Initated Successfully")})).catch((error=>reject(error)))}))}Object.defineProperties(window,{myFloID:{get:()=>{try{return user.id}catch{return}}},myUserID:{get:()=>{try{return user.id}catch{return}}},myPubKey:{get:()=>{try{return user.public}catch{return}}},myPrivKey:{get:()=>{try{return user.private}catch{return}}}}),Object.defineProperties(floGlobals,{subAdmins:{get:()=>subAdmins},trustedIDs:{get:()=>trustedIDs},settings:{get:()=>settings},contacts:{get:()=>user.contacts},pubKeys:{get:()=>user.pubKeys},messages:{get:()=>user.messages}});const startUpOptions={cloud:!0,app_config:!0};floDapps.startUpOptions={set app_config(val){!0!==val&&!1!==val||(startUpOptions.app_config=val)},get app_config(){return startUpOptions.app_config},set cloud(val){!0!==val&&!1!==val||(startUpOptions.cloud=val)},get cloud(){return startUpOptions.cloud}};const startUpFunctions=[];startUpFunctions.push((function(){return new Promise(((resolve,reject)=>{if(!startUpOptions.cloud)return resolve("No cloud for this app");const CLOUD_KEY="floCloudAPI#"+floCloudAPI.SNStorageID;compactIDB.readData("lastTx",CLOUD_KEY,DEFAULT.root).then((lastTx=>{var query_options={sentOnly:!0,pattern:floCloudAPI.SNStorageName};"number"==typeof lastTx?query_options.ignoreOld=lastTx:"string"==typeof lastTx&&(query_options.after=lastTx),floBlockchainAPI.readData(floCloudAPI.SNStorageID,query_options).then((result=>{compactIDB.readData("supernodes",CLOUD_KEY,DEFAULT.root).then((nodes=>{nodes=nodes||{};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)delete nodes[sn];for(let sn in content.newNodes)nodes[sn]=content.newNodes[sn];for(let sn in content.updateNodes)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((result=>resolve("Loaded Supernode list\n"+result))).catch((error=>reject(error)))})).catch((error=>reject(error)))})).catch((error=>reject(error)))}))})).catch((error=>reject(error)))}))})),startUpFunctions.push((function(){return new Promise(((resolve,reject)=>{if(!startUpOptions.app_config)return resolve("No configs for this app");compactIDB.readData("lastTx",`${DEFAULT.application}|${DEFAULT.adminID}`,DEFAULT.root).then((lastTx=>{var query_options={sentOnly:!0,pattern:DEFAULT.application};"number"==typeof lastTx?query_options.ignoreOld=lastTx:"string"==typeof lastTx&&(query_options.after=lastTx),floBlockchainAPI.readData(DEFAULT.adminID,query_options).then((result=>{for(var i=result.data.length-1;i>=0;i--){var content=JSON.parse(result.data[i])[DEFAULT.application];if(content&&"object"==typeof content){if(Array.isArray(content.removeSubAdmin))for(var j=0;j{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(){return new Promise(((resolve,reject)=>{if(!startUpOptions.cloud)return resolve("No cloud for this app");for(var loadData=["appObjects","generalData","lastVC"],promises=[],i=0;i{for(var i=0;ireject(error)))}))}));var keyInput=type=>new Promise(((resolve,reject)=>{let inputVal=prompt(`Enter ${type}: `);null===inputVal?reject(null):resolve(inputVal)}));function getCredentials(){const writeSharesToIDB=(shares,i=0,resultIndexes=[])=>new Promise((resolve=>{if(i>=shares.length)return resolve(resultIndexes);var n=floCrypto.randInt(0,1e5);compactIDB.addData("credentials",shares[i],n).then((res=>{resultIndexes.push(n),writeSharesToIDB(shares,i+1,resultIndexes).then((result=>resolve(result)))})).catch((error=>{writeSharesToIDB(shares,i,resultIndexes).then((result=>resolve(result)))}))})),getPrivateKeyCredentials=()=>new Promise(((resolve,reject)=>{var privKey,indexArr=localStorage.getItem(`${DEFAULT.application}#privKey`);indexArr?(indexArr=>new Promise(((resolve,reject)=>{for(var promises=[],i=0;i{var secret=floCrypto.retrieveShamirSecret(shares);secret?resolve(secret):reject("Shares are insufficient or incorrect")})).catch((error=>{clearCredentials(),location.reload()}))})))(JSON.parse(indexArr)).then((result=>resolve(result))).catch((error=>reject(error))):keyInput("PRIVATE_KEY").then((result=>{if(!result)return reject("Empty Private Key");var floID=floCrypto.getFloID(result);if(!floID||!floCrypto.validateFloID(floID))return reject("Invalid Private Key");privKey=result})).catch((error=>{console.log(error,"Generating Random Keys"),privKey=floCrypto.generateNewID().privKey})).finally((_=>{if(privKey){var threshold=floCrypto.randInt(10,20),shares=floCrypto.createShamirsSecretShares(privKey,threshold,threshold);writeSharesToIDB(shares).then((resultIndexes=>{localStorage.setItem(`${DEFAULT.application}#privKey`,JSON.stringify(resultIndexes));var randomPrivKey=floCrypto.generateNewID().privKey,randomThreshold=floCrypto.randInt(10,20),randomShares=floCrypto.createShamirsSecretShares(randomPrivKey,randomThreshold,randomThreshold);writeSharesToIDB(randomShares),resolve(privKey)}))}}))})),checkIfPinRequired=key=>new Promise(((resolve,reject)=>{52==key.length?resolve(key):keyInput("PIN/Password").then((pwd=>{try{let privKey=Crypto.AES.decrypt(key,pwd);resolve(privKey)}catch(error){reject("Access Denied: Incorrect PIN/Password")}})).catch((error=>reject("Access Denied: PIN/Password required")))}));return new Promise(((resolve,reject)=>{getPrivateKeyCredentials().then((key=>{checkIfPinRequired(key).then((privKey=>{try{user_public=floCrypto.getPubKeyHex(privKey),user_id=floCrypto.getAddress(privKey),startUpOptions.cloud&&floCloudAPI.user(user_id,privKey),user_priv_wrap=()=>checkIfPinRequired(key);let n=floCrypto.randInt(12,20);aes_key=floCrypto.randString(n),user_priv_raw=Crypto.AES.encrypt(privKey,aes_key),user_private=user_priv_wrap,resolve("Login Credentials loaded successful")}catch(error){console.log(error),reject("Corrupted Private Key")}})).catch((error=>reject(error)))})).catch((error=>reject(error)))}))}var startUpLog=(status,log)=>status?console.log(log):console.error(log);const callStartUpFunction=i=>new Promise(((resolve,reject)=>{startUpFunctions[i]().then((result=>{callStartUpFunction.completed+=1,startUpLog(!0,`${result}\nCompleted ${callStartUpFunction.completed}/${callStartUpFunction.total} Startup functions`),resolve(!0)})).catch((error=>{callStartUpFunction.failed+=1,startUpLog(!1,`${error}\nFailed ${callStartUpFunction.failed}/${callStartUpFunction.total} Startup functions`),reject(!1)}))}));var _midFunction;const callAndLog=p=>new Promise(((res,rej)=>{p.then((r=>{startUpLog(!0,r),res(r)})).catch((e=>{startUpLog(!1,e),rej(e)}))}));floDapps.launchStartUp=function(){return new Promise(((resolve,reject)=>{initIndexedDB().then((log=>{console.log(log),callStartUpFunction.total=startUpFunctions.length,callStartUpFunction.completed=0,callStartUpFunction.failed=0;let p1=new Promise(((res,rej)=>{Promise.all(startUpFunctions.map(((f,i)=>callStartUpFunction(i)))).then((r=>{callAndLog(new Promise(((res,rej)=>{_midFunction instanceof Function?_midFunction().then((r=>res("Mid startup function completed"))).catch((e=>rej("Mid startup function failed"))):res("No mid startup function")}))).then((r=>res(!0))).catch((e=>rej(!1)))}))})),p2=new Promise(((res,rej)=>{callAndLog(getCredentials()).then((r=>{callAndLog(new Promise(((resolve,reject)=>{compactIDB.initDB(user.db_name,{contacts:{},pubKeys:{},messages:{}}).then((result=>{resolve("UserDB Initated Successfully")})).catch((error=>reject("Init userDB failed")))}))).then((r=>{callAndLog(new Promise(((resolve,reject)=>{for(var loadData=["contacts","pubKeys","messages"],promises=[],i=0;i{for(var i=0;ireject("Load userDB failed")))}))).then((r=>res(!0))).catch((e=>rej(!1)))})).catch((e=>rej(!1)))})).catch((e=>rej(!1)))}));Promise.all([p1,p2]).then((r=>resolve("App Startup finished successful"))).catch((e=>reject("App Startup failed")))})).catch((error=>{startUpLog(!1,error),reject("App database initiation failed")}))}))},floDapps.addStartUpFunction=fn=>fn instanceof Function&&!startUpFunctions.includes(fn)&&startUpFunctions.push(fn),floDapps.setMidStartup=fn=>fn instanceof Function&&(_midFunction=fn),floDapps.setCustomStartupLogger=fn=>fn instanceof Function&&(startUpLog=fn),floDapps.setCustomPrivKeyInput=fn=>fn instanceof Function&&(keyInput=fn),floDapps.setAppObjectStores=appObs=>initIndexedDB.appObs=appObs,floDapps.storeContact=function(floID,name){return new Promise(((resolve,reject)=>{if(!floCrypto.validateAddr(floID))return reject("Invalid floID!");compactIDB.writeData("contacts",name,floID,user.db_name).then((result=>{user.contacts[floID]=name,resolve("Contact stored")})).catch((error=>reject(error)))}))},floDapps.storePubKey=function(floID,pubKey){return new Promise(((resolve,reject)=>floID in user.pubKeys?resolve("pubKey already stored"):floCrypto.validateAddr(floID)?floCrypto.verifyPubKey(pubKey,floID)?void compactIDB.writeData("pubKeys",pubKey,floID,user.db_name).then((result=>{user.pubKeys[floID]=pubKey,resolve("pubKey stored")})).catch((error=>reject(error))):reject("Incorrect pubKey"):reject("Invalid floID!")))},floDapps.sendMessage=function(floID,message){return new Promise(((resolve,reject)=>{let options={receiverID:floID,application:DEFAULT.root,comment:DEFAULT.application};floID in user.pubKeys&&(message=floCrypto.encryptData(JSON.stringify(message),user.pubKeys[floID])),floCloudAPI.sendApplicationData(message,"Message",options).then((result=>resolve(result))).catch((error=>reject(error)))}))},floDapps.requestInbox=function(callback){return new Promise(((resolve,reject)=>{let lastVC=Object.keys(user.messages).sort().pop(),options={receiverID:user.id,application:DEFAULT.root,lowerVectorClock:lastVC+1},privKey=raw_user.private;options.callback=(d,e)=>{for(let v in d){try{d[v].message instanceof Object&&"secret"in d[v].message&&(d[v].message=floCrypto.decryptData(d[v].message,privKey))}catch(error){}compactIDB.writeData("messages",d[v],v,user.db_name),user.messages[v]=d[v]}callback instanceof Function&&callback(d,e)},floCloudAPI.requestApplicationData("Message",options).then((result=>resolve(result))).catch((error=>reject(error)))}))},floDapps.manageAppConfig=function(adminPrivKey,addList,rmList,settings){return new Promise(((resolve,reject)=>{if(!startUpOptions.app_config)return reject("No configs for this app");if(Array.isArray(addList)&&addList.length||(addList=void 0),Array.isArray(rmList)&&rmList.length||(rmList=void 0),settings&&"object"==typeof settings&&Object.keys(settings).length||(settings=void 0),!addList&&!rmList&&!settings)return reject("No configuration change");var floData={[DEFAULT.application]:{addSubAdmin:addList,removeSubAdmin:rmList,settings:settings}},floID=floCrypto.getFloID(adminPrivKey);floID!=DEFAULT.adminID?reject("Access Denied for Admin privilege"):floBlockchainAPI.writeData(floID,JSON.stringify(floData),adminPrivKey).then((result=>resolve(["Updated App Configuration",result]))).catch((error=>reject(error)))}))},floDapps.manageAppTrustedIDs=function(adminPrivKey,addList,rmList){return new Promise(((resolve,reject)=>{if(!startUpOptions.app_config)return reject("No configs for this app");if(Array.isArray(addList)&&addList.length||(addList=void 0),Array.isArray(rmList)&&rmList.length||(rmList=void 0),!addList&&!rmList)return reject("No change in list");var floData={[DEFAULT.application]:{addTrustedID:addList,removeTrustedID:rmList}},floID=floCrypto.getFloID(adminPrivKey);floID!=DEFAULT.adminID?reject("Access Denied for Admin privilege"):floBlockchainAPI.writeData(floID,JSON.stringify(floData),adminPrivKey).then((result=>resolve(["Updated App Configuration",result]))).catch((error=>reject(error)))}))};const clearCredentials=floDapps.clearCredentials=function(){return new Promise(((resolve,reject)=>{compactIDB.clearData("credentials",DEFAULT.application).then((result=>{localStorage.removeItem(`${DEFAULT.application}#privKey`),user.clear(),resolve("privKey credentials deleted!")})).catch((error=>reject(error)))}))};floDapps.deleteUserData=function(credentials=!1){return new Promise(((resolve,reject)=>{let p=[];p.push(compactIDB.deleteDB(user.db_name)),credentials&&p.push(clearCredentials()),Promise.all(p).then((result=>resolve("User database(local) deleted"))).catch((error=>reject(error)))}))},floDapps.deleteAppData=function(){return new Promise(((resolve,reject)=>{compactIDB.deleteDB(DEFAULT.application).then((result=>{localStorage.removeItem(`${DEFAULT.application}#privKey`),user.clear(),compactIDB.removeData("lastTx",`${DEFAULT.application}|${DEFAULT.adminID}`,DEFAULT.root).then((result=>resolve("App database(local) deleted"))).catch((error=>reject(error)))})).catch((error=>reject(error)))}))},floDapps.securePrivKey=function(pwd){return new Promise((async(resolve,reject)=>{let indexArr=localStorage.getItem(`${DEFAULT.application}#privKey`);if(!indexArr)return reject("PrivKey not found");indexArr=JSON.parse(indexArr);let encryptedKey=Crypto.AES.encrypt(await user.private,pwd),threshold=indexArr.length,shares=floCrypto.createShamirsSecretShares(encryptedKey,threshold,threshold),promises=[];for(var i=0;iresolve("Private Key Secured"))).catch((error=>reject(error)))}))},floDapps.verifyPin=function(pin=null){return new Promise(((resolve,reject)=>{var indexArr=localStorage.getItem(`${DEFAULT.application}#privKey`);console.info(indexArr),indexArr||reject("No login credentials found"),function(indexArr){return new Promise(((resolve,reject)=>{for(var promises=[],i=0;i{var secret=floCrypto.retrieveShamirSecret(shares);console.info(shares,secret),secret?resolve(secret):reject("Shares are insufficient or incorrect")})).catch((error=>{clearCredentials(),location.reload()}))}))}(JSON.parse(indexArr)).then((key=>{if(52==key.length)null===pin?resolve("Private key not secured"):reject("Private key not secured");else{if(null===pin)return reject("PIN/Password required");try{Crypto.AES.decrypt(key,pin);resolve("PIN/Password verified")}catch(error){reject("Incorrect PIN/Password")}}})).catch((error=>reject(error)))}))};const getNextGeneralData=floDapps.getNextGeneralData=function(type,vectorClock=null,options={}){var fk=floCloudAPI.util.filterKey(type,options);vectorClock=vectorClock||getNextGeneralData[fk]||"0";var filteredResult={};if(floGlobals.generalData[fk])for(let d in floGlobals.generalData[fk])d>vectorClock&&(filteredResult[d]=JSON.parse(JSON.stringify(floGlobals.generalData[fk][d])));else if(options.comment){let comment=options.comment;delete options.comment;let fk=floCloudAPI.util.filterKey(type,options);for(let d in floGlobals.generalData[fk])d>vectorClock&&floGlobals.generalData[fk][d].comment==comment&&(filteredResult[d]=JSON.parse(JSON.stringify(floGlobals.generalData[fk][d])))}if(options.decrypt){let decryptionKey=!0===options.decrypt?raw_user.private:options.decrypt;Array.isArray(decryptionKey)||(decryptionKey=[decryptionKey]);for(let f in filteredResult){let data=filteredResult[f];try{if(data.message instanceof Object&&"secret"in data.message)for(let key of decryptionKey)try{let tmp=floCrypto.decryptData(data.message,key);data.message=JSON.parse(tmp);break}catch(error){}}catch(error){}}}return getNextGeneralData[fk]=Object.keys(filteredResult).sort().pop(),filteredResult},syncData=floDapps.syncData={};syncData.oldDevice=()=>new Promise(((resolve,reject)=>{let sync={contacts:user.contacts,pubKeys:user.pubKeys,messages:user.messages},message=Crypto.AES.encrypt(JSON.stringify(sync),raw_user.private),options={receiverID:user.id,application:DEFAULT.root};floCloudAPI.sendApplicationData(message,"syncData",options).then((result=>resolve(result))).catch((error=>reject(error)))})),syncData.newDevice=()=>new Promise(((resolve,reject)=>{var options={receiverID:user.id,senderID:user.id,application:DEFAULT.root,mostRecent:!0};floCloudAPI.requestApplicationData("syncData",options).then((response=>{let vc=Object.keys(response).sort().pop(),sync=JSON.parse(Crypto.AES.decrypt(response[vc].message,raw_user.private)),promises=[];["contacts","pubKeys","messages"].forEach((c=>{for(let i in sync[c])key=i,val=sync[c][i],obs=c,promises.push(compactIDB.writeData(obs,val,key,user.db_name)),user[c][i]=sync[c][i];var key,val,obs})),Promise.all(promises).then((results=>resolve("Sync data successful"))).catch((error=>reject(error)))})).catch((error=>reject(error)))}))}(); \ No newline at end of file