contacts are stored as shared contacts
This commit is contained in:
parent
80ca63fdf8
commit
dd8c8cd21c
30
index.html
30
index.html
@ -7,7 +7,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="description"
|
<meta name="description"
|
||||||
content="This webapp allows monitoring FLO addresses and performing transactions based on blockchain.">
|
content="This webapp allows monitoring FLO addresses and performing transactions based on blockchain.">
|
||||||
<link rel="shortcut icon" href="flo-favicon.png" type="image/png">
|
<link rel="shortcut icon" href="flo-favicon.png" type="image/png">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link
|
<link
|
||||||
@ -1625,20 +1625,20 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
</template>
|
</template>
|
||||||
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
|
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
|
||||||
<script src="scripts/components.js"></script>
|
<script src="scripts/components.js" defer></script>
|
||||||
<script src="scripts/std_ui.js"></script>
|
<script src="scripts/std_ui.js" defer></script>
|
||||||
<script src="scripts/lib.js"></script>
|
<script src="scripts/lib.js" defer></script>
|
||||||
<script src="scripts/floCrypto.js"></script>
|
<script src="scripts/floCrypto.js" defer></script>
|
||||||
<script src="scripts/floBlockchainAPI.js"></script>
|
<script src="scripts/floBlockchainAPI.js" defer></script>
|
||||||
<script src="scripts/compactIDB.js"></script>
|
<script src="scripts/compactIDB.js" defer></script>
|
||||||
<script src="scripts/floCloudAPI.js"></script>
|
<script src="scripts/floCloudAPI.js" defer></script>
|
||||||
<script src="scripts/floDapps.js"></script>
|
<script src="scripts/floDapps.js" defer></script>
|
||||||
<script src="scripts/fn_pay.js"></script>
|
<script src="scripts/fn_pay.js" defer></script>
|
||||||
<script src="scripts/fn_ui.js"></script>
|
<script src="scripts/fn_ui.js" defer></script>
|
||||||
<script src="scripts/floTokenAPI.js"></script>
|
<script src="scripts/floTokenAPI.js" defer></script>
|
||||||
<script src="scripts/floExchangeAPI.js"></script>
|
<script src="scripts/floExchangeAPI.js" defer></script>
|
||||||
<script src="scripts/lib_btc.js"></script>
|
<script src="scripts/lib_btc.js" defer></script>
|
||||||
<script src="scripts/qrcode.min.js"></script>
|
<script src="scripts/qrcode.min.js" defer></script>
|
||||||
<script id="onLoadStartUp">
|
<script id="onLoadStartUp">
|
||||||
let isShowingFloID = false;
|
let isShowingFloID = false;
|
||||||
async function onLoadStartUp() {
|
async function onLoadStartUp() {
|
||||||
|
|||||||
@ -611,7 +611,7 @@ async function completeTokenToCashRequest(request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getFloIdTitle(floID) {
|
function getFloIdTitle(floID) {
|
||||||
return floGlobals.savedIds[floID] ? floGlobals.savedIds[floID].title : floID;
|
return floGlobals.contacts[floID] || floID;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAmount(amount = 0, currency = 'inr') {
|
function formatAmount(amount = 0, currency = 'inr') {
|
||||||
@ -628,8 +628,7 @@ const cashierRejectionErrors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const render = {
|
const render = {
|
||||||
savedId(floID, details,ref) {
|
savedId(floID, title,ref) {
|
||||||
const { title } = details;
|
|
||||||
return html.for(ref,floID)`
|
return html.for(ref,floID)`
|
||||||
<li class="saved-id grid interact" tabindex="0" data-flo-id="${floID}">
|
<li class="saved-id grid interact" tabindex="0" data-flo-id="${floID}">
|
||||||
<button class="interact edit-saved icon-only" title="Edit name">
|
<button class="interact edit-saved icon-only" title="Edit name">
|
||||||
@ -866,8 +865,8 @@ const render = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async savedIds() {
|
async savedIds() {
|
||||||
await organizeSyncedData('savedIds');
|
// await organizeSyncedData('savedIds');
|
||||||
renderElem(getRef('saved_ids_list'), html`${getArrayOfSavedIds().map(({floID, details}) => render.savedId(floID, details, getRef('saved_ids_list')))}`)
|
renderElem(getRef('saved_ids_list'), html`${getArrayOfSavedIds().map(({floID, title}) => render.savedId(floID, title, getRef('saved_ids_list')))}`)
|
||||||
},
|
},
|
||||||
conditionalSteps() {
|
conditionalSteps() {
|
||||||
if (getRef('topup_wallet__qr_wrapper').open) {
|
if (getRef('topup_wallet__qr_wrapper').open) {
|
||||||
@ -996,22 +995,21 @@ getRef('to_amount').addEventListener('input', e => {
|
|||||||
|
|
||||||
function getArrayOfSavedIds() {
|
function getArrayOfSavedIds() {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
for (const key in floGlobals.savedIds) {
|
for (const key in floGlobals.contacts) {
|
||||||
arr.push({
|
arr.push({
|
||||||
floID: key,
|
floID: key,
|
||||||
details: floGlobals.savedIds[key]
|
title: floGlobals.contacts[key]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return arr.sort((a, b) => a.details.title.localeCompare(b.details.title));
|
return arr.sort((a, b) => a.title.localeCompare(b.title));
|
||||||
}
|
}
|
||||||
async function saveFloId() {
|
async function saveFloId() {
|
||||||
const floID = getRef('flo_id_to_save').value.trim();
|
const floID = getRef('flo_id_to_save').value.trim();
|
||||||
if (floGlobals.savedIds.hasOwnProperty(floID))
|
if (floGlobals.contacts.hasOwnProperty(floID))
|
||||||
return notify('This FLO ID is already saved', 'error');
|
return notify('This FLO ID is already saved', 'error');
|
||||||
const title = getRef('flo_id_title_to_save').value.trim();
|
const title = getRef('flo_id_title_to_save').value.trim();
|
||||||
floGlobals.savedIds[floID] = { title }
|
|
||||||
buttonLoader('save_flo_id_button', true);
|
buttonLoader('save_flo_id_button', true);
|
||||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
floDapps.storeContact(floID,title).then(() => {
|
||||||
render.savedIds()
|
render.savedIds()
|
||||||
notify(`Saved ${floID}`, 'success');
|
notify(`Saved ${floID}`, 'success');
|
||||||
closePopup();
|
closePopup();
|
||||||
@ -1047,8 +1045,7 @@ function saveIdChanges() {
|
|||||||
let title = getRef('get_new_title').value.trim();
|
let title = getRef('get_new_title').value.trim();
|
||||||
if (title == '')
|
if (title == '')
|
||||||
title = 'Unknown';
|
title = 'Unknown';
|
||||||
floGlobals.savedIds[floID] = { title }
|
floDapps.storeContact(floID,title).then(() => {
|
||||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
|
||||||
render.savedIds()
|
render.savedIds()
|
||||||
closePopup();
|
closePopup();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@ -1060,13 +1057,13 @@ function deleteSavedId() {
|
|||||||
confirmText: 'Delete',
|
confirmText: 'Delete',
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
const toDelete = getRef('saved_ids_list').querySelector(`.saved-id[data-flo-id="${getRef('edit_saved_id').value}"]`);
|
const floID = getRef('edit_saved_id').value;
|
||||||
|
const toDelete = getRef('saved_ids_list').querySelector(`.saved-id[data-flo-id="${floID}`);
|
||||||
if (toDelete)
|
if (toDelete)
|
||||||
toDelete.remove();
|
toDelete.remove();
|
||||||
delete floGlobals.savedIds[getRef('edit_saved_id').value];
|
|
||||||
closePopup();
|
closePopup();
|
||||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
compactIDB.removeData('contacts',floID, floDapps.user.db_name).then(() => {
|
||||||
notify(`Deleted saved ID`, 'success');
|
notify(`Deleted flo address`, 'success');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
notify(error, 'error');
|
notify(error, 'error');
|
||||||
});
|
});
|
||||||
@ -1085,7 +1082,7 @@ savedIdsObserver.observe(getRef('saved_ids_list'), {
|
|||||||
function insertElementAlphabetically(name, elementToInsert) {
|
function insertElementAlphabetically(name, elementToInsert) {
|
||||||
const elementInserted = [...getRef('saved_ids_list').children].some(child => {
|
const elementInserted = [...getRef('saved_ids_list').children].some(child => {
|
||||||
const floID = child.dataset.floId;
|
const floID = child.dataset.floId;
|
||||||
if (floGlobals.savedIds[floID].title.localeCompare(name) > 0) {
|
if (floGlobals.contacts[floID].localeCompare(name) > 0) {
|
||||||
child.before(elementToInsert)
|
child.before(elementToInsert)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -1100,7 +1097,7 @@ getRef('search_saved_ids_picker').addEventListener('input', debounce(async e =>
|
|||||||
const searchKey = e.target.value.trim();
|
const searchKey = e.target.value.trim();
|
||||||
let allSavedIds = getArrayOfSavedIds();
|
let allSavedIds = getArrayOfSavedIds();
|
||||||
if (searchKey !== '') {
|
if (searchKey !== '') {
|
||||||
const fuse = new Fuse(allSavedIds, { keys: ['floID', 'details.title'] })
|
const fuse = new Fuse(allSavedIds, { keys: ['floID', 'title'] })
|
||||||
allSavedIds = fuse.search(searchKey).map(v => v.item)
|
allSavedIds = fuse.search(searchKey).map(v => v.item)
|
||||||
}
|
}
|
||||||
renderElem(getRef('saved_ids_picker_list'), html`${allSavedIds.map(({ floID, details }) => render.savedIdPickerCard(floID, details))}`)
|
renderElem(getRef('saved_ids_picker_list'), html`${allSavedIds.map(({ floID, details }) => render.savedIdPickerCard(floID, details))}`)
|
||||||
@ -1420,12 +1417,6 @@ function calculateBtcFees() {
|
|||||||
console.error(e)
|
console.error(e)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePrivateKeyVisibility(input) {
|
|
||||||
const target = input.closest('sm-input')
|
|
||||||
target.type = target.type === 'password' ? 'text' : 'password';
|
|
||||||
target.focusIn()
|
|
||||||
}
|
|
||||||
const txParticipantsObserver = new MutationObserver(mutations => {
|
const txParticipantsObserver = new MutationObserver(mutations => {
|
||||||
mutations.forEach(mutation => {
|
mutations.forEach(mutation => {
|
||||||
if (mutation.type === 'childList') {
|
if (mutation.type === 'childList') {
|
||||||
|
|||||||
@ -848,105 +848,38 @@ mobileQuery.addEventListener('change', handleMobileChange)
|
|||||||
handleMobileChange(mobileQuery)
|
handleMobileChange(mobileQuery)
|
||||||
|
|
||||||
function showChildElement(id, index, options = {}) {
|
function showChildElement(id, index, options = {}) {
|
||||||
const { mobileView = false, entry, exit } = options
|
return new Promise((resolve) => {
|
||||||
const animOptions = {
|
const { mobileView = false, entry, exit } = options
|
||||||
duration: 150,
|
const animOptions = {
|
||||||
easing: 'ease',
|
duration: 150,
|
||||||
fill: 'forwards'
|
easing: 'ease',
|
||||||
}
|
fill: 'forwards'
|
||||||
const parent = typeof id === 'string' ? document.getElementById(id) : id;
|
}
|
||||||
const visibleElement = [...parent.children].find(elem => !elem.classList.contains(mobileView ? 'hide-on-mobile' : 'hidden'));
|
const parent = typeof id === 'string' ? document.getElementById(id) : id;
|
||||||
if (visibleElement === parent.children[index]) return;
|
const visibleElement = [...parent.children].find(elem => !elem.classList.contains(mobileView ? 'hide-on-mobile' : 'hidden'));
|
||||||
if (visibleElement) {
|
if (visibleElement === parent.children[index]) return;
|
||||||
if (exit) {
|
visibleElement.getAnimations().forEach(anim => anim.cancel())
|
||||||
visibleElement.animate(exit, animOptions).onfinish = () => {
|
parent.children[index].getAnimations().forEach(anim => anim.cancel())
|
||||||
|
if (visibleElement) {
|
||||||
|
if (exit) {
|
||||||
|
visibleElement.animate(exit, animOptions).onfinish = () => {
|
||||||
|
visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||||
|
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||||
|
if (entry)
|
||||||
|
parent.children[index].animate(entry, animOptions).onfinish = () => resolve()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden')
|
visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||||
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||||
if (entry)
|
resolve()
|
||||||
parent.children[index].animate(entry, animOptions)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
visibleElement.classList.add(mobileView ? 'hide-on-mobile' : 'hidden')
|
|
||||||
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||||
|
parent.children[index].animate(entry, animOptions).onfinish = () => resolve()
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
|
||||||
parent.children[index].animate(entry, animOptions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reactivity system
|
|
||||||
class ReactiveState {
|
|
||||||
constructor() {
|
|
||||||
this.state = {}
|
|
||||||
}
|
|
||||||
setState(key, value, callback) {
|
|
||||||
if (this.state[key].value === value) return
|
|
||||||
this.state[key].value = value
|
|
||||||
this.state[key].refs.forEach(ref => {
|
|
||||||
ref.textContent = value
|
|
||||||
})
|
|
||||||
if (callback)
|
|
||||||
callback(value)
|
|
||||||
}
|
|
||||||
getState(key) {
|
|
||||||
return this.state[key].value
|
|
||||||
}
|
|
||||||
subscribe(key, dom) {
|
|
||||||
if (!this.state.hasOwnProperty(key)) {
|
|
||||||
this.state[key] = {
|
|
||||||
refs: new Set(),
|
|
||||||
value: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.state[key].refs.add(dom)
|
|
||||||
dom.textContent = this.state[key].value
|
|
||||||
}
|
|
||||||
unsubscribe(key, dom) {
|
|
||||||
this.state[key].refs.delete(dom)
|
|
||||||
}
|
|
||||||
createState(defaultValue, key, callback) {
|
|
||||||
if (!key)
|
|
||||||
key = Math.random().toString(36).substr(2, 9);
|
|
||||||
if (!this.state.hasOwnProperty(key)) {
|
|
||||||
this.state[key] = {
|
|
||||||
refs: new Set()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setState(key, defaultValue, callback)
|
|
||||||
return [
|
|
||||||
() => this.getState(key),
|
|
||||||
value => this.setState(key, value, callback)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const reactiveState = new ReactiveState()
|
|
||||||
function createState(defaultValue, key, callback) {
|
|
||||||
return reactiveState.createState(defaultValue, key, callback)
|
|
||||||
}
|
|
||||||
const smState = document.createElement('template')
|
|
||||||
smState.innerHTML = `
|
|
||||||
<style>
|
|
||||||
font-size: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
font-family: inherit;
|
|
||||||
</style>
|
|
||||||
`
|
|
||||||
class SmState extends HTMLElement {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.appendChild(smState.content.cloneNode(true));
|
|
||||||
}
|
|
||||||
connectedCallback() {
|
|
||||||
reactiveState.subscribe(this.getAttribute('sid'), this)
|
|
||||||
}
|
|
||||||
disconnectedCallback() {
|
|
||||||
reactiveState.unsubscribe(this.getAttribute('sid'), this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.customElements.define('r-s', SmState);
|
|
||||||
|
|
||||||
|
|
||||||
// generate random string with numbers and capital and small letters
|
// generate random string with numbers and capital and small letters
|
||||||
function randomString(length) {
|
function randomString(length) {
|
||||||
let result = '';
|
let result = '';
|
||||||
@ -975,3 +908,8 @@ function conditionalClassToggle(el, className, condition) {
|
|||||||
else
|
else
|
||||||
el.classList.remove(className);
|
el.classList.remove(className);
|
||||||
}
|
}
|
||||||
|
function togglePrivateKeyVisibility(input) {
|
||||||
|
const target = input.closest('sm-input')
|
||||||
|
target.type = target.type === 'password' ? 'text' : 'password';
|
||||||
|
target.focusIn()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user