FLO_WebAppStore/FLO_AppStore.html
2019-03-23 02:34:40 +05:30

522 lines
20 KiB
HTML

<html>
<head>
<title>FLO AppStore</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Titillium+Web" rel="stylesheet">
</head>
<body onload="rePaint()" onresize="rePaint()">
<style>
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}
@import url('https://fonts.googleapis.com/css?family=Titillium+Web');
/*These settings will go to all divs */
#rootDiv {
box-sizing: border-box;
position:relative;
top:0px;
font-family: 'Titillium Web', Arial, sans-serif;
font-weight: 300;
font-size: 1.05em;
margin: 0;
text-align:justify;
}
.baseDiv {
border-color: #e3e3e3;
border-style: solid;
border-width: 1px;
margin-left: -1px;
margin-top: -1px;
}
i {
font-size: 1em;
font-weight: 400;
padding: 0 0 15px;
line-height: 36px;
}
h1 {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 28px;
font-weight: 400;
padding: 0 0 15px;
}
a{
text-decoration: none;
}
.appname{
font-size: 36px;
color: #FFFFFF;
text-align: center;
padding: 10px;
}
.appdescription{
font-size: 20px;
color: #FFFFFF;
text-align: center;
padding: 10px;
}
</style>
<!--Entire Document is mounted here -->
<div id="rootDiv"></div>
<script>
const mainnet = `https://livenet.flocha.in`;
const testnet = `https://testnet.flocha.in`;
let server = mainnet;
floapps = []
</script>
<script id="userNonPresentationData">
//User Data Section. Keep things that will fetch user non-presentation data here
//Do not put presentation elements here. Presentation elements will need rePainting when screens are resized. Put them in next script tag UserPresentationCode under function rePaintUserData()
function userDataStartUp(){
console.log("StartUp");
var waitForGlobal = function(param, callback) {
if (!window[param]) {
callback();
} else {
setTimeout(function() {
waitForGlobal(param, callback);
}, 100);
}
};
getDatafromAPI().then(function (res) {
getDataFromIDB().then(function (response) {
floapps = response;
screenAlpha.totalBoxes = floapps.length+1;
oneTimeTasks();
rePaint();
}).catch(function (error) {
console.log(error.message);
});
}).catch(function (error) {
console.log(error.message);
});
function ajax(method, uri){
var request = new XMLHttpRequest();
var url = `${server}/${uri}`
console.log(url)
var result;
request.open(method,url , false);
request.onload = function () {
if (request.readyState == 4 && request.status == 200)
result = this.response;
else {
console.log('error');
result = false;
}
};
request.send();
console.log(result);
return result;
}
function storedata(appdata){
return new Promise(
function(resolve, reject) {
var idb = indexedDB.open("FLO_AppStore");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction('apps', "readwrite").objectStore('apps');
objectRequest = obs.put(appdata);
objectRequest.onerror = function(event) {
reject(Error('Error occured: Unable to store data'));
};
objectRequest.onsuccess = function(event) {
resolve('Data saved OK');
db.close();
};
};
}
);
}
function getDatafromAPI(){
return new Promise(
function(resolve, reject) {
var addrList = ["FT9qkvuWXWBDRhHd42tDr5nMYFSx7bEhV7"]
var idb = indexedDB.open("FLO_AppStore");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event) {
var objectStore = event.target.result.createObjectStore("apps", { keyPath: "id" });
objectStore.createIndex("name", "name", { unique: false });
objectStore.createIndex("icon", "icon", { unique: false });
objectStore.createIndex("url", "url", { unique: false });
objectStore.createIndex("description", "description", { unique: false });
var objectStore2 = event.target.result.createObjectStore("lastTx");
};
idb.onsuccess = function(event) {
var db = event.target.result;
window["wait"] = addrList.length;
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
addrList.forEach(function(addr){
console.log(addr);
var lastTxReq = lastTx.get(addr);
var lasttx;
lastTxReq.onsuccess = function(event){
lasttx = event.target.result
if(lasttx === undefined){
lasttx = 0;
}
var response = ajax("GET",`api/addrs/${addr}/txs`);
var nRequired = JSON.parse(response).totalItems - lasttx;
console.log(nRequired);
while(true && nRequired){
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
response = JSON.parse(response);
if (nRequired + lasttx != response.totalItems ){
nRequired = response.totalItems - lasttx;
continue;
}
response.items.reverse().forEach(function(tx){
try {
if (tx.vin[0].addr != addr)
return;
appdata = JSON.parse(tx.floData).Dapp
if(appdata.description === undefined)
appdata.description = 'NIL';
if(appdata.type == 'Webapp')
data = {id : appdata.id, name : appdata.name, icon : appdata.icon, url:appdata.url, description:appdata.description};
storedata(data).then(function (response) {
}).catch(function (error) {
console.log(error.message);
});
} catch (e) {
//console.log(e)
}
});
var idb2 = indexedDB.open("FLO_AppStore");
idb2.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb2.onsuccess = function(event) {
var dbt = event.target.result;
var obs = dbt.transaction('lastTx', "readwrite").objectStore('lastTx');
obs.put(response.totalItems,addr);
dbt.close();
};
break;
}
window["wait"]--;
};
});
waitForGlobal("wait",function(){
db.close();
console.log('retrived data from API');
resolve('retrived data from API');
});
};
});
}
function getDataFromIDB(){
return new Promise(
function(resolve, reject) {
var idb = indexedDB.open("FLO_AppStore");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction('apps', "readwrite").objectStore('apps');
appdetails = [];
var cursorRequest = obs.openCursor();
cursorRequest.onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
appdetails.push(cursor.value);
cursor.continue();
}else {
resolve(appdetails);
}
};
db.close();
};
}
);
}
}
userDataStartUp();
//This function will be called by framework for you
function userDataNeedingNoRePaint(){
}
</script>
<script id="SystemConfiguration">
var screenAlpha ={};
//Main configuration for number of boxes in grid. You only have to define minimum width, minimum height and total number of boxes. Positioning will be taken care of by the code
screenAlpha.boxMinimumWidth = 300;
screenAlpha.boxMinimumHeight = 300;
screenAlpha.totalBoxes = 0;
//Turn them false when layout job is done
screenAlpha.lastUserDivShouldCoverWholeLine = false;
screenAlpha.showBaseDivNumber = false ;
screenAlpha.showBaseDivBackground = true;
screenAlpha.showLastOverLayDivBackground = true;
//Styling Information for base Div grid, and overlay Div grid
screenAlpha.baseDivGridBackground = "white";
screenAlpha.OverlayDivGridBackground =["pink","#DBB1CD","#E8B5CE","pink","#F0EAD6",]
screenAlpha.OverlayDivOpacity ="0.8";
</script>
<script id="UserPresentationCode">
/*
1. You can create your own overlay divs, and put user HTML/Javascript code inside it. Give it space by calling createUserDiv(baseDivNumber,howManyAdjacentDivs,heightMultiplier)
2. Keep static calculations outside rePainting zone in <script id="script_userNonPresentationData"> section
3. Keep all the screen specific display in <script id="script_UserPresentationData"> zone
4. All user presentation code should strictly be inside the function rePaintUserData()
*/
function rePaintUserData(){
//createUserDiv(baseDivNumber,howManyAdjacentDivs,heightMultiplier)
/*
//Creates a user div which spans the entire line with id div_overlay_2 which be used to style and put content inside the div. Positioning has been taken care of
createUserDiv(6,"full_line",1);
//Creates a user div which spans 2 adjacent divs or end of line if those adjacent divs are could not be placed. The height is 3 row of divs. Div id is div_overlay_7
createUserDiv(15,2,3);
// You get last overly div ID for free if screenAlpha.lastUserDivShouldCoverWholeLine = true;
if(screenAlpha.lastBaseDivNumber) document.getElementById("div_overlay_"+screenAlpha.lastBaseDivNumber).innerHTML="Last overlay DIV takes the whole row if configured that way";
*/
var x0 = createUserDiv(0);
// x0.style.backgroundColor = "#222";
x0.innerHTML = `<h1>FLO App Store <i class="fab fa-bitcoin"></i></h1>`;
for(var i=0;i<floapps.length;i++){
var grid = createUserDiv(i+1);
grid.innerHTML = `<a href=${floapps[i].url} target="_blank"><div class="appname">${floapps[i].name}</div><div class="appdescription">${floapps[i].description}</div></a>`
}
//On repainting .. it creates that number again .. and updates getLastUserDivNumber ..
} // Main function end
</script>
<script id="script_last">
//Positioning section
//Keep this script tag section as the last tag
//Do not touch these settings
screenAlpha.widthAdjustment = 18;
screenAlpha.heightAdjustment = 20;
screenAlpha.baseDivIdList = [];
screenAlpha.userDivIdList = [];
screenAlpha.lastBaseDivNumber = screenAlpha.totalBoxes -1;
screenAlpha.lastUserDivNumber = 0;
//One time tasks not needing repainting
function oneTimeTasks(){
createAllBaseDivs(screenAlpha.totalBoxes);
userDataNeedingNoRePaint();
}
function createAllBaseDivs(totalBoxes){
var index;
for (index = 0; index < totalBoxes; index++) {
var divId = "div_"+index;
createSingleBaseDiv(divId);
screenAlpha.baseDivIdList.push(divId);
}
}
function createSingleBaseDiv(divId){
var divCreated = document.createElement("div");
divCreated.id=divId;
divCreated.style.position = "absolute";
if(screenAlpha.showBaseDivBackground) {
divCreated.classList.add("baseDiv");
}
rootDiv.appendChild(divCreated);
}
//Tasks needing repainting
function rePaint(){
screenAlpha.boxDetails = boxesPerRowData(screenAlpha.boxMinimumWidth,screenAlpha.boxMinimumHeight);
rootDivSetDimensions("rootDiv");
positionTheBaseDivs();
if(screenAlpha.lastUserDivShouldCoverWholeLine ) lastBaseDivOverlay();
if(screenAlpha.showBaseDivBackground) {
document.getElementById("rootDiv").style.backgroundColor = screenAlpha.baseDivGridBackground;
}
rePaintUserData();
}
function rootDivSetDimensions (rootElementId){
var divSelected = document.getElementById(rootElementId);
divSelected.style.width = (window.innerWidth-screenAlpha.widthAdjustment);
divSelected.style.height = Math.ceil(screenAlpha.totalBoxes/screenAlpha.boxDetails.numberOfBoxesInRow)*screenAlpha.boxMinimumHeight;
}
function boxesPerRowData(boxMinimumWidth, boxMinimumHeight){
var boxDetails = {};
var numberOfBoxesInRow = Math.floor((window.innerWidth-screenAlpha.widthAdjustment)/boxMinimumWidth);
var spillOverPerRow = (window.innerWidth-screenAlpha.widthAdjustment) - numberOfBoxesInRow*boxMinimumWidth;
if (numberOfBoxesInRow == 0) {numberOfBoxesInRow = 1}; //to solve Divide by Zero problem
var spillOverPerBox = spillOverPerRow/numberOfBoxesInRow;
var boxEffectiveWidth = boxMinimumWidth + spillOverPerBox;
boxDetails.numberOfBoxesInRow = numberOfBoxesInRow;
boxDetails.boxEffectiveWidth = boxEffectiveWidth;
screenAlpha.numberOfBoxesInRow = numberOfBoxesInRow;
screenAlpha.boxEffectiveWidth = boxEffectiveWidth;
return boxDetails;
}
function topAndLeftPositionOfBaseDivs(divNumber){
heightPositionMultiplier = Math.floor(divNumber/screenAlpha.boxDetails.numberOfBoxesInRow);
widthPositionMultiplier = divNumber % screenAlpha.boxDetails.numberOfBoxesInRow;
topPosition = screenAlpha.boxMinimumHeight*heightPositionMultiplier;
leftPosition = screenAlpha.boxDetails.boxEffectiveWidth*widthPositionMultiplier;
screenAlpha["div_"+divNumber+"_topPosition"] = topPosition;
screenAlpha["div_"+divNumber+"_leftPosition"] = leftPosition;
}
function positionTheBaseDivs(){
var index;
for (index = 0; index < screenAlpha.baseDivIdList.length; index++) {
topAndLeftPositionOfBaseDivs(index);
var divId = "div_"+index;
document.getElementById(divId).style.top=screenAlpha["div_"+index+"_topPosition"]+"px";
document.getElementById(divId).style.left=screenAlpha["div_"+index+"_leftPosition"]+"px";
document.getElementById(divId).style.width=screenAlpha.boxDetails.boxEffectiveWidth+"px";
document.getElementById(divId).style.height = screenAlpha.boxMinimumHeight+"px";
if(screenAlpha.showBaseDivNumber) document.getElementById(divId).innerHTML = index;
}
}
function createUserDiv(baseDivNumber,howManyAdjacentDivs=1,heightMultiplier=1){
var topPosition = screenAlpha["div_"+baseDivNumber+"_topPosition"];
if (howManyAdjacentDivs == "full_line") {
var divWidth = screenAlpha.boxEffectiveWidth*screenAlpha.numberOfBoxesInRow;
var leftPosition = "0";
}
else
{
var originalLeftPosition = screenAlpha["div_"+baseDivNumber+"_leftPosition"];
//Obtain the lowest width of 3 possibilities for overlay
var divWidth1 = screenAlpha.boxEffectiveWidth*screenAlpha.numberOfBoxesInRow;
var divWidth2 = howManyAdjacentDivs*screenAlpha.boxEffectiveWidth;
var divWidth3 = divWidth1 - screenAlpha["div_"+baseDivNumber+"_leftPosition"];
var divWidthTemp = (divWidth1 > divWidth2) ? divWidth2 : divWidth1;
var divWidth = (divWidthTemp > divWidth3) ? divWidth3 : divWidthTemp;
}
var divHeight = screenAlpha.boxMinimumHeight*heightMultiplier;
var divId="div_overlay_"+baseDivNumber;
if (!document.getElementById(divId)){
var overlayDiv = document.createElement("div");
overlayDiv.id=divId;
overlayDiv.style.position = "absolute";
document.getElementById("rootDiv").appendChild(overlayDiv)
}
var overlayDiv = document.getElementById(divId);
overlayDiv.style.top = topPosition+"px";screenAlpha[divId+"_top"]=topPosition;
if(howManyAdjacentDivs == "full_line") {screenAlpha[divId+"_left"]=0 } else {overlayDiv.style.left=originalLeftPosition+"px";screenAlpha[divId+"_left"]=originalLeftPosition};
overlayDiv.style.width=divWidth+"px";screenAlpha[divId+"_width"]=divWidth;
overlayDiv.style.height=divHeight+"px";screenAlpha[divId+"_height"]=divHeight;
if(screenAlpha.showLastOverLayDivBackground) {
overlayDiv.style.backgroundColor=screenAlpha.OverlayDivGridBackground[baseDivNumber%screenAlpha.OverlayDivGridBackground.length];
overlayDiv.style.opacity=screenAlpha.OverlayDivOpacity;
if(screenAlpha.showBaseDivNumber) {
overlayDiv.innerHTML="<span style='position:relative;left:20px'>Overlay Div Number "+baseDivNumber+"</span>";}
}
if(!screenAlpha.userDivIdList.includes(divId)) {
screenAlpha.userDivIdList.push(divId);
}
return document.getElementById("div_overlay_"+baseDivNumber);
}
function getUserDivDimensions(userDivNumber){
var x = {};
x.height = screenAlpha["div_overlay_"+userDivNumber+"_height"];
x.width = screenAlpha["div_overlay_"+userDivNumber+"_width"];
x.top = screenAlpha["div_overlay_"+userDivNumber+"_top"];
x.left = screenAlpha["div_overlay_"+userDivNumber+"_left"];
return x;
}
function lastBaseDivOverlay(){
//Last div will take over the whole line if the screenAlpha.lastUserDivShouldCoverWholeLine configuration allows is
var lastBaseDivNumber = screenAlpha.totalBoxes - 1 ;
createUserDiv(lastBaseDivNumber,"full_line",1)
}
function getLastUserDivNumber(){
function removeLargest(arr) {
var min = Math.max.apply(null, arr);
return arr.filter((e) => {return e != min});
}
var extractNumbers = screenAlpha.userDivIdList.map(x => {return parseInt(x.replace("div_overlay_",""))});
if (screenAlpha.lastUserDivShouldCoverWholeLine) extractNumbers = removeLargest(extractNumbers);
if (typeof extractNumbers !== 'undefined' && extractNumbers.length > 0) { var highestValue = extractNumbers.reduce((a,b)=>{return a>b?a:b;});} else {highestValue = 0};
// This condition is screwing me
// if (highestValue >= screenAlpha.lastUserDivNumber) {return "All base divs are taken" } else {return highestValue+1};
return highestValue+1
}
//End of positioning code
</script>
</body>
</html>