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 name="description"
|
||||
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.gstatic.com" crossorigin>
|
||||
<link
|
||||
@ -1625,20 +1625,20 @@
|
||||
</fieldset>
|
||||
</template>
|
||||
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
|
||||
<script src="scripts/components.js"></script>
|
||||
<script src="scripts/std_ui.js"></script>
|
||||
<script src="scripts/lib.js"></script>
|
||||
<script src="scripts/floCrypto.js"></script>
|
||||
<script src="scripts/floBlockchainAPI.js"></script>
|
||||
<script src="scripts/compactIDB.js"></script>
|
||||
<script src="scripts/floCloudAPI.js"></script>
|
||||
<script src="scripts/floDapps.js"></script>
|
||||
<script src="scripts/fn_pay.js"></script>
|
||||
<script src="scripts/fn_ui.js"></script>
|
||||
<script src="scripts/floTokenAPI.js"></script>
|
||||
<script src="scripts/floExchangeAPI.js"></script>
|
||||
<script src="scripts/lib_btc.js"></script>
|
||||
<script src="scripts/qrcode.min.js"></script>
|
||||
<script src="scripts/components.js" defer></script>
|
||||
<script src="scripts/std_ui.js" defer></script>
|
||||
<script src="scripts/lib.js" defer></script>
|
||||
<script src="scripts/floCrypto.js" defer></script>
|
||||
<script src="scripts/floBlockchainAPI.js" defer></script>
|
||||
<script src="scripts/compactIDB.js" defer></script>
|
||||
<script src="scripts/floCloudAPI.js" defer></script>
|
||||
<script src="scripts/floDapps.js" defer></script>
|
||||
<script src="scripts/fn_pay.js" defer></script>
|
||||
<script src="scripts/fn_ui.js" defer></script>
|
||||
<script src="scripts/floTokenAPI.js" defer></script>
|
||||
<script src="scripts/floExchangeAPI.js" defer></script>
|
||||
<script src="scripts/lib_btc.js" defer></script>
|
||||
<script src="scripts/qrcode.min.js" defer></script>
|
||||
<script id="onLoadStartUp">
|
||||
let isShowingFloID = false;
|
||||
async function onLoadStartUp() {
|
||||
|
||||
@ -611,7 +611,7 @@ async function completeTokenToCashRequest(request) {
|
||||
}
|
||||
|
||||
function getFloIdTitle(floID) {
|
||||
return floGlobals.savedIds[floID] ? floGlobals.savedIds[floID].title : floID;
|
||||
return floGlobals.contacts[floID] || floID;
|
||||
}
|
||||
|
||||
function formatAmount(amount = 0, currency = 'inr') {
|
||||
@ -628,8 +628,7 @@ const cashierRejectionErrors = {
|
||||
}
|
||||
|
||||
const render = {
|
||||
savedId(floID, details,ref) {
|
||||
const { title } = details;
|
||||
savedId(floID, title,ref) {
|
||||
return html.for(ref,floID)`
|
||||
<li class="saved-id grid interact" tabindex="0" data-flo-id="${floID}">
|
||||
<button class="interact edit-saved icon-only" title="Edit name">
|
||||
@ -866,8 +865,8 @@ const render = {
|
||||
}
|
||||
},
|
||||
async savedIds() {
|
||||
await organizeSyncedData('savedIds');
|
||||
renderElem(getRef('saved_ids_list'), html`${getArrayOfSavedIds().map(({floID, details}) => render.savedId(floID, details, getRef('saved_ids_list')))}`)
|
||||
// await organizeSyncedData('savedIds');
|
||||
renderElem(getRef('saved_ids_list'), html`${getArrayOfSavedIds().map(({floID, title}) => render.savedId(floID, title, getRef('saved_ids_list')))}`)
|
||||
},
|
||||
conditionalSteps() {
|
||||
if (getRef('topup_wallet__qr_wrapper').open) {
|
||||
@ -996,22 +995,21 @@ getRef('to_amount').addEventListener('input', e => {
|
||||
|
||||
function getArrayOfSavedIds() {
|
||||
const arr = [];
|
||||
for (const key in floGlobals.savedIds) {
|
||||
for (const key in floGlobals.contacts) {
|
||||
arr.push({
|
||||
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() {
|
||||
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');
|
||||
const title = getRef('flo_id_title_to_save').value.trim();
|
||||
floGlobals.savedIds[floID] = { title }
|
||||
buttonLoader('save_flo_id_button', true);
|
||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
||||
floDapps.storeContact(floID,title).then(() => {
|
||||
render.savedIds()
|
||||
notify(`Saved ${floID}`, 'success');
|
||||
closePopup();
|
||||
@ -1047,8 +1045,7 @@ function saveIdChanges() {
|
||||
let title = getRef('get_new_title').value.trim();
|
||||
if (title == '')
|
||||
title = 'Unknown';
|
||||
floGlobals.savedIds[floID] = { title }
|
||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
||||
floDapps.storeContact(floID,title).then(() => {
|
||||
render.savedIds()
|
||||
closePopup();
|
||||
}).catch(error => {
|
||||
@ -1060,13 +1057,13 @@ function deleteSavedId() {
|
||||
confirmText: 'Delete',
|
||||
}).then(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)
|
||||
toDelete.remove();
|
||||
delete floGlobals.savedIds[getRef('edit_saved_id').value];
|
||||
closePopup();
|
||||
syncUserData('savedIds', floGlobals.savedIds).then(() => {
|
||||
notify(`Deleted saved ID`, 'success');
|
||||
compactIDB.removeData('contacts',floID, floDapps.user.db_name).then(() => {
|
||||
notify(`Deleted flo address`, 'success');
|
||||
}).catch(error => {
|
||||
notify(error, 'error');
|
||||
});
|
||||
@ -1085,7 +1082,7 @@ savedIdsObserver.observe(getRef('saved_ids_list'), {
|
||||
function insertElementAlphabetically(name, elementToInsert) {
|
||||
const elementInserted = [...getRef('saved_ids_list').children].some(child => {
|
||||
const floID = child.dataset.floId;
|
||||
if (floGlobals.savedIds[floID].title.localeCompare(name) > 0) {
|
||||
if (floGlobals.contacts[floID].localeCompare(name) > 0) {
|
||||
child.before(elementToInsert)
|
||||
return true
|
||||
}
|
||||
@ -1100,7 +1097,7 @@ getRef('search_saved_ids_picker').addEventListener('input', debounce(async e =>
|
||||
const searchKey = e.target.value.trim();
|
||||
let allSavedIds = getArrayOfSavedIds();
|
||||
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)
|
||||
}
|
||||
renderElem(getRef('saved_ids_picker_list'), html`${allSavedIds.map(({ floID, details }) => render.savedIdPickerCard(floID, details))}`)
|
||||
@ -1420,12 +1417,6 @@ function calculateBtcFees() {
|
||||
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 => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.type === 'childList') {
|
||||
|
||||
@ -848,105 +848,38 @@ mobileQuery.addEventListener('change', handleMobileChange)
|
||||
handleMobileChange(mobileQuery)
|
||||
|
||||
function showChildElement(id, index, options = {}) {
|
||||
const { mobileView = false, entry, exit } = options
|
||||
const animOptions = {
|
||||
duration: 150,
|
||||
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'));
|
||||
if (visibleElement === parent.children[index]) return;
|
||||
if (visibleElement) {
|
||||
if (exit) {
|
||||
visibleElement.animate(exit, animOptions).onfinish = () => {
|
||||
return new Promise((resolve) => {
|
||||
const { mobileView = false, entry, exit } = options
|
||||
const animOptions = {
|
||||
duration: 150,
|
||||
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'));
|
||||
if (visibleElement === parent.children[index]) return;
|
||||
visibleElement.getAnimations().forEach(anim => anim.cancel())
|
||||
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')
|
||||
parent.children[index].classList.remove(mobileView ? 'hide-on-mobile' : 'hidden')
|
||||
if (entry)
|
||||
parent.children[index].animate(entry, animOptions)
|
||||
resolve()
|
||||
}
|
||||
} else {
|
||||
visibleElement.classList.add(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
|
||||
function randomString(length) {
|
||||
let result = '';
|
||||
@ -975,3 +908,8 @@ function conditionalClassToggle(el, className, condition) {
|
||||
else
|
||||
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