Cashu: UI upgrades and fixes (#1453)
* Cashu: UI updates and automatic mint activation * welcome dialog * welcome dialog * UI updates
This commit is contained in:
parent
9d2008d45c
commit
970a0ce1d0
1 changed files with 224 additions and 79 deletions
|
|
@ -3,7 +3,7 @@ endraw %} {% endblock %} {% block footer %}{% endblock %} {% block
|
||||||
page_container %}
|
page_container %}
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
<q-page>
|
<q-page>
|
||||||
<div class="row q-col-gutter-md justify-center q-pt-sm q-pb-md">
|
<div class="row q-col-gutter-y-md justify-center q-pt-sm q-pb-md">
|
||||||
<div class="col-12 col-sm-11 col-md-8 text-center q-gutter-y-md">
|
<div class="col-12 col-sm-11 col-md-8 text-center q-gutter-y-md">
|
||||||
<q-card class="q-my-md q-py-sm">
|
<q-card class="q-my-md q-py-sm">
|
||||||
<q-card-section class="q-mt-sm q-py-xs">
|
<q-card-section class="q-mt-sm q-py-xs">
|
||||||
|
|
@ -18,11 +18,18 @@ page_container %}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row q-mt-sm q-mb-none">
|
<div class="row q-mt-xs q-mb-none" v-if="mints.length > 0">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a>
|
<a class="text-weight-light">
|
||||||
All mints: {% raw %}{{ getTotalBalance }} {{tickerShort}} {%
|
Balance on all mints: {% raw %}
|
||||||
endraw %}</a
|
<b>{{ getTotalBalance }} {{tickerShort}} </b>{% endraw %}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-mt-none q-mb-none" v-if="activeMintURL">
|
||||||
|
<div class="col-12">
|
||||||
|
<a class="text-weight-light">
|
||||||
|
Mint: {% raw %}{{ getActiveMintUrlShort()}} {% endraw %}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -35,7 +42,7 @@ page_container %}
|
||||||
<div class="row items-center no-wrap q-mb-sm">
|
<div class="row items-center no-wrap q-mb-sm">
|
||||||
<div class="col-6 col-sm-5 col-md-4 q-px-xs">
|
<div class="col-6 col-sm-5 col-md-4 q-px-xs">
|
||||||
<q-btn
|
<q-btn
|
||||||
size="12px"
|
size="0.75rem"
|
||||||
rectangle
|
rectangle
|
||||||
unelevated
|
unelevated
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|
@ -50,7 +57,7 @@ page_container %}
|
||||||
<div class="col-0 col-sm-2 col-md-4"></div>
|
<div class="col-0 col-sm-2 col-md-4"></div>
|
||||||
<div class="col-6 col-sm-5 col-md-4 q-px-xs">
|
<div class="col-6 col-sm-5 col-md-4 q-px-xs">
|
||||||
<q-btn
|
<q-btn
|
||||||
size="12px"
|
size="0.75rem"
|
||||||
rectangle
|
rectangle
|
||||||
unelevated
|
unelevated
|
||||||
align="between"
|
align="between"
|
||||||
|
|
@ -85,10 +92,10 @@ page_container %}
|
||||||
<q-list padding>
|
<q-list padding>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label overline>Cashu mints</q-item-label>
|
<q-item-label overline>Mints</q-item-label>
|
||||||
<q-item-label caption
|
<q-item-label caption
|
||||||
>You can use use multiple Cashu mints in this wallet.
|
>You can connect your wallet to multiple Cashu mints.
|
||||||
Add the mint URL and select the mint you want to
|
Enter a mint URL and select the mint your want to
|
||||||
use.</q-item-label
|
use.</q-item-label
|
||||||
>
|
>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
@ -213,14 +220,15 @@ page_container %}
|
||||||
>
|
>
|
||||||
<q-tooltip>Pending</q-tooltip>
|
<q-tooltip>Pending</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-badge
|
<q-icon
|
||||||
size="lg"
|
name="sync"
|
||||||
color="secondary"
|
size="xs"
|
||||||
class="q-mr-md cursor-pointer"
|
color="grey"
|
||||||
|
class="q-mr-xs cursor-pointer"
|
||||||
@click="checkInvoice(props.row.hash)"
|
@click="checkInvoice(props.row.hash)"
|
||||||
>
|
>
|
||||||
Check
|
<q-tooltip>Check status</q-tooltip>
|
||||||
</q-badge>
|
</q-icon>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.row.status === 'paid'">
|
<div v-if="props.row.status === 'paid'">
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -258,6 +266,9 @@ page_container %}
|
||||||
<q-td key="hash" :props="props">
|
<q-td key="hash" :props="props">
|
||||||
<div>{{props.row.hash}}</div>
|
<div>{{props.row.hash}}</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
<q-td key="mint" :props="props">
|
||||||
|
<div>{{props.row.mint}}</div>
|
||||||
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
|
|
@ -288,14 +299,15 @@ page_container %}
|
||||||
>
|
>
|
||||||
<q-tooltip>Pending</q-tooltip>
|
<q-tooltip>Pending</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-badge
|
<q-icon
|
||||||
size="lg"
|
name="sync"
|
||||||
color="secondary"
|
size="xs"
|
||||||
class="q-mr-md cursor-pointer"
|
color="grey"
|
||||||
|
class="q-mr-xs cursor-pointer"
|
||||||
@click="checkTokenSpendable(props.row.token)"
|
@click="checkTokenSpendable(props.row.token)"
|
||||||
>
|
>
|
||||||
Check
|
<q-tooltip>Check status</q-tooltip>
|
||||||
</q-badge>
|
</q-icon>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.row.status === 'paid'">
|
<div v-if="props.row.status === 'paid'">
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -344,7 +356,7 @@ page_container %}
|
||||||
<div class="col-4 q-pt-none">
|
<div class="col-4 q-pt-none">
|
||||||
<q-btn
|
<q-btn
|
||||||
class="full-width gt-sm"
|
class="full-width gt-sm"
|
||||||
size="14px"
|
size="1.0rem"
|
||||||
icon-right="bolt"
|
icon-right="bolt"
|
||||||
icon="file_download"
|
icon="file_download"
|
||||||
align="between"
|
align="between"
|
||||||
|
|
@ -359,16 +371,17 @@ page_container %}
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-mx-xs q-px-none"
|
class="q-mx-xs q-px-none"
|
||||||
size="10px"
|
size="0.5rem"
|
||||||
rectangle
|
rectangle
|
||||||
color="warning"
|
color="warning"
|
||||||
icon="warning"
|
icon="warning"
|
||||||
outline
|
outline
|
||||||
@click="showDisclaimerDialog"
|
@click="showDisclaimerDialog"
|
||||||
></q-btn>
|
><q-tooltip>Warning</q-tooltip></q-btn
|
||||||
|
>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-mx-xs q-px-none"
|
class="q-mx-xs q-px-none"
|
||||||
size="10px"
|
size="0.5rem"
|
||||||
outline
|
outline
|
||||||
rectangle
|
rectangle
|
||||||
color="warning"
|
color="warning"
|
||||||
|
|
@ -382,7 +395,7 @@ page_container %}
|
||||||
<q-btn
|
<q-btn
|
||||||
class="full-width gt-sm"
|
class="full-width gt-sm"
|
||||||
@click="showParseDialog"
|
@click="showParseDialog"
|
||||||
size="14px"
|
size="1.0rem"
|
||||||
icon-right="bolt"
|
icon-right="bolt"
|
||||||
icon="file_upload"
|
icon="file_upload"
|
||||||
align="between"
|
align="between"
|
||||||
|
|
@ -396,6 +409,7 @@ page_container %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- // BOTTOM BAR -->
|
||||||
<div class="q-col-gutter">
|
<div class="q-col-gutter">
|
||||||
<q-tabs
|
<q-tabs
|
||||||
class="lt-md fixed-bottom q-px-none q-py-md left-0 right-0 bg-primary text-white shadow-2 z-top q-px-0"
|
class="lt-md fixed-bottom q-px-none q-py-md left-0 right-0 bg-primary text-white shadow-2 z-top q-px-0"
|
||||||
|
|
@ -410,7 +424,7 @@ page_container %}
|
||||||
>
|
>
|
||||||
</q-tab>
|
</q-tab>
|
||||||
<q-tab
|
<q-tab
|
||||||
class="col-2"
|
class="col-2 q-pb-md"
|
||||||
icon="photo_camera"
|
icon="photo_camera"
|
||||||
v-if="hasCamera"
|
v-if="hasCamera"
|
||||||
@click="showCamera"
|
@click="showCamera"
|
||||||
|
|
@ -429,14 +443,15 @@ page_container %}
|
||||||
<q-dialog v-model="payInvoiceData.show" @hide="closeParseDialog">
|
<q-dialog v-model="payInvoiceData.show" @hide="closeParseDialog">
|
||||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||||
<div v-if="payInvoiceData.invoice">
|
<div v-if="payInvoiceData.invoice">
|
||||||
<h6 v-if="'{{LNBITS_DENOMINATION}}' != 'sats'" class="q-my-none">
|
<!-- <h6 v-if="'{{LNBITS_DENOMINATION}}' != 'sats'" class="q-my-none">
|
||||||
{% raw %} {{
|
{% raw %} {{
|
||||||
parseFloat(String(payInvoiceData.invoice.fsat).replaceAll(",",
|
parseFloat(String(payInvoiceData.invoice.fsat).replaceAll(",",
|
||||||
"")) / 100 }} {% endraw %} {{LNBITS_DENOMINATION}} {% raw %}
|
"")) / 100 }} {% endraw %} asdasdasd {{LNBITS_DENOMINATION}} {%
|
||||||
</h6>
|
raw %}
|
||||||
<h6 v-else class="q-my-none">
|
</h6> -->
|
||||||
|
<h6 class="q-my-none">
|
||||||
{{ payInvoiceData.invoice.fsat }}{% endraw %}
|
{{ payInvoiceData.invoice.fsat }}{% endraw %}
|
||||||
{{LNBITS_DENOMINATION}} {% raw %}
|
{{LNBITS_DENOMINATION}} {% raw %} asdasdsd
|
||||||
</h6>
|
</h6>
|
||||||
<q-separator class="q-my-sm"></q-separator>
|
<q-separator class="q-my-sm"></q-separator>
|
||||||
<p class="text-wrap">
|
<p class="text-wrap">
|
||||||
|
|
@ -649,6 +664,66 @@ page_container %}
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
|
<q-dialog
|
||||||
|
class="z-top"
|
||||||
|
persistent
|
||||||
|
v-model="welcomeDialog.show"
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
<q-card class="q-pa-lg z-top">
|
||||||
|
<q-toolbar>
|
||||||
|
<q-avatar>
|
||||||
|
<img
|
||||||
|
src="https://raw.githubusercontent.com/cashubtc/cashu-ui/main/ui/icons/circle/128x128.png"
|
||||||
|
/>
|
||||||
|
</q-avatar>
|
||||||
|
<q-toolbar-title
|
||||||
|
><span class="text-weight-bold">Cashu</span>
|
||||||
|
wallet</q-toolbar-title
|
||||||
|
>
|
||||||
|
</q-toolbar>
|
||||||
|
<q-card-section>
|
||||||
|
<p>Please take a moment to read the following information.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Open this wallet on your device's native browser</strong>
|
||||||
|
Cashu stores your ecash on your device locally. For the best
|
||||||
|
experience, use this wallet with your device's native web browser
|
||||||
|
(for example Safari for iOS, Chrome for Android).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Add to home screen.</strong>
|
||||||
|
Add Cashu to your home screen as a progressive web app (PWA). On
|
||||||
|
Android Chrome, click the hamburger menu at the upper right. On
|
||||||
|
iOS Safari, click the share button. Now press the Add to Home
|
||||||
|
screen button.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>This software is in BETA!</strong> We hold no
|
||||||
|
responsibility for people losing access to funds. Use at your own
|
||||||
|
risk! Ecash is a bearer asset, meaning losing access to this
|
||||||
|
wallet will mean you will lose the funds. This wallet stores ecash
|
||||||
|
tokens in its database. If you lose the link or delete your your
|
||||||
|
data without backing up, you will lose your tokens. Press the
|
||||||
|
Backup button to download a copy of your tokens.
|
||||||
|
</p>
|
||||||
|
<div class="row q-mt-lg">
|
||||||
|
<q-btn outline color="grey" @click="copyText(baseURL)"
|
||||||
|
>Copy wallet URL</q-btn
|
||||||
|
>
|
||||||
|
<q-btn
|
||||||
|
v-close-popup
|
||||||
|
flat
|
||||||
|
color="primary"
|
||||||
|
class="q-ml-auto"
|
||||||
|
@click="setWelcomeDialogSeen()"
|
||||||
|
>Continue</q-btn
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="disclaimerDialog.show">
|
<q-dialog v-model="disclaimerDialog.show">
|
||||||
<q-card class="q-pa-lg">
|
<q-card class="q-pa-lg">
|
||||||
<h6 class="q-my-md text-primary">Warning</h6>
|
<h6 class="q-my-md text-primary">Warning</h6>
|
||||||
|
|
@ -668,7 +743,7 @@ page_container %}
|
||||||
Home screen button.
|
Home screen button.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>This service is in BETA!</strong> We hold no responsibility
|
<strong>This software is in BETA!</strong> We hold no responsibility
|
||||||
for people losing access to funds. Use at your own risk!
|
for people losing access to funds. Use at your own risk!
|
||||||
</p>
|
</p>
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
|
|
@ -706,12 +781,12 @@ page_container %}
|
||||||
class="q-mb-lg"
|
class="q-mb-lg"
|
||||||
@keyup.enter="requestMintButton"
|
@keyup.enter="requestMintButton"
|
||||||
></q-input>
|
></q-input>
|
||||||
<q-input
|
<!-- <q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="invoiceData.memo"
|
v-model.trim="invoiceData.memo"
|
||||||
label="Memo"
|
label="Memo"
|
||||||
></q-input>
|
></q-input> -->
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center q-mb-lg">
|
<div v-else class="text-center q-mb-lg">
|
||||||
<a class="text-secondary" :href="'lightning:' + invoiceData.bolt11">
|
<a class="text-secondary" :href="'lightning:' + invoiceData.bolt11">
|
||||||
|
|
@ -770,19 +845,19 @@ page_container %}
|
||||||
class="q-mb-lg"
|
class="q-mb-lg"
|
||||||
@keyup.enter="sendTokens"
|
@keyup.enter="sendTokens"
|
||||||
></q-input>
|
></q-input>
|
||||||
<q-input
|
<!-- <q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="sendData.memo"
|
v-model.trim="sendData.memo"
|
||||||
label="Memo"
|
label="Memo"
|
||||||
></q-input>
|
></q-input> -->
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center q-mb-lg">
|
<div v-else class="text-center q-mb-lg">
|
||||||
<div class="text-center q-mb-lg">
|
<div class="text-center q-mb-lg" v-if="sendData.tokens.length < 2">
|
||||||
<!-- <a class="text-secondary" :href="'cashu:' + sendData.tokensBase64"> -->
|
<!-- <a class="text-secondary" :href="'cashu:' + sendData.tokensBase64"> -->
|
||||||
<q-responsive :ratio="1" class="q-mx-xl">
|
<q-responsive :ratio="1" class="q-mx-xl">
|
||||||
<qrcode
|
<qrcode
|
||||||
:value="walletURL + '&recv_token=' + sendData.tokensBase64"
|
:value="baseURL + '&recv_token=' + sendData.tokensBase64"
|
||||||
:options="{width: 340}"
|
:options="{width: 340}"
|
||||||
class="rounded-borders"
|
class="rounded-borders"
|
||||||
>
|
>
|
||||||
|
|
@ -818,7 +893,8 @@ page_container %}
|
||||||
>
|
>
|
||||||
<q-btn
|
<q-btn
|
||||||
color="primary"
|
color="primary"
|
||||||
@click="copyText(walletURL + '&recv_token=' + sendData.tokensBase64)"
|
outline
|
||||||
|
@click="copyText(baseURL + '&recv_token=' + sendData.tokensBase64)"
|
||||||
>Copy link</q-btn
|
>Copy link</q-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -851,12 +927,6 @@ page_container %}
|
||||||
|
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
<q-btn @click="redeem" color="primary">Receive</q-btn>
|
<q-btn @click="redeem" color="primary">Receive</q-btn>
|
||||||
<q-btn
|
|
||||||
unelevated
|
|
||||||
icon="content_copy"
|
|
||||||
class="q-mx-0"
|
|
||||||
@click="copyText(receiveData.tokensBase64)"
|
|
||||||
></q-btn>
|
|
||||||
<q-btn
|
<q-btn
|
||||||
unelevated
|
unelevated
|
||||||
icon="photo_camera"
|
icon="photo_camera"
|
||||||
|
|
@ -878,13 +948,15 @@ page_container %}
|
||||||
controls your funds. Make sure that you trust the operator of this
|
controls your funds. Make sure that you trust the operator of this
|
||||||
mint.
|
mint.
|
||||||
</p>
|
</p>
|
||||||
<q-field outlined dense>
|
<q-input
|
||||||
<template v-slot:control>
|
outlined
|
||||||
<div class="self-center full-width no-outline" tabindex="0">
|
readonly
|
||||||
{% raw %}{{ mintToAdd }} {% endraw %}
|
v-model="mintToAdd"
|
||||||
</div>
|
label="Mint URL"
|
||||||
</template>
|
type="textarea"
|
||||||
</q-field>
|
autogrow
|
||||||
|
class="q-mb-xs"
|
||||||
|
></q-input>
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
<q-btn
|
<q-btn
|
||||||
outline
|
outline
|
||||||
|
|
@ -1112,6 +1184,13 @@ page_container %}
|
||||||
label: 'Hash',
|
label: 'Hash',
|
||||||
field: 'hash',
|
field: 'hash',
|
||||||
sortable: false
|
sortable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mint',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Mint',
|
||||||
|
field: 'mint',
|
||||||
|
sortable: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
pagination: {
|
pagination: {
|
||||||
|
|
@ -1171,6 +1250,9 @@ page_container %}
|
||||||
paymentsChart: {
|
paymentsChart: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
|
welcomeDialog: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
disclaimerDialog: {
|
disclaimerDialog: {
|
||||||
show: false,
|
show: false,
|
||||||
location: window.location,
|
location: window.location,
|
||||||
|
|
@ -1230,6 +1312,7 @@ page_container %}
|
||||||
removeMint: function (url) {
|
removeMint: function (url) {
|
||||||
this.mints = this.mints.filter(m => m.url != url)
|
this.mints = this.mints.filter(m => m.url != url)
|
||||||
localStorage.setItem('cashu.mints', JSON.stringify(this.mints))
|
localStorage.setItem('cashu.mints', JSON.stringify(this.mints))
|
||||||
|
// todo: we always reset to the first mint, improve this
|
||||||
this.activateMint(this.mints[0].url)
|
this.activateMint(this.mints[0].url)
|
||||||
this.notifySuccess('Mint removed.')
|
this.notifySuccess('Mint removed.')
|
||||||
},
|
},
|
||||||
|
|
@ -1244,7 +1327,26 @@ page_container %}
|
||||||
}
|
}
|
||||||
return balance
|
return balance
|
||||||
},
|
},
|
||||||
activateMint: async function (url, verbose = false) {
|
getActiveMintUrlShort: function () {
|
||||||
|
url = this.activeMintURL.replace('https://', '')
|
||||||
|
|
||||||
|
const cut_param = 40
|
||||||
|
if (url.length > cut_param && url.indexOf('/') != -1) {
|
||||||
|
url =
|
||||||
|
url.substring(0, url.indexOf('/') + 1) +
|
||||||
|
'...' +
|
||||||
|
url.substring(url.length - cut_param / 2, url.length)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
},
|
||||||
|
activateMint: async function (url, verbose = false, stop_workers = true) {
|
||||||
|
if (url == this.activeMintURL) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (stop_workers) {
|
||||||
|
// we need to stop workers because they will reset the activeMint again
|
||||||
|
this.clearAllWorkers()
|
||||||
|
}
|
||||||
let presiouvURL = this.activeMintURL
|
let presiouvURL = this.activeMintURL
|
||||||
try {
|
try {
|
||||||
this.activeMintURL = url
|
this.activeMintURL = url
|
||||||
|
|
@ -1253,13 +1355,13 @@ page_container %}
|
||||||
this.activeProofs = this.proofs.filter(p =>
|
this.activeProofs = this.proofs.filter(p =>
|
||||||
this.keysets.includes(p.id)
|
this.keysets.includes(p.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
this.notifySuccess('Mint added.')
|
this.notifySuccess('Mint added.')
|
||||||
}
|
}
|
||||||
|
console.log('### activateMint: Mint activated: ', this.activeMintURL)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.activeMintURL = presiouvURL
|
this.activeMintURL = presiouvURL
|
||||||
this.notifyError('Could not add mint.')
|
this.notifyError('Could not connect to mint.')
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1324,6 +1426,18 @@ page_container %}
|
||||||
this.camera.show = false
|
this.camera.show = false
|
||||||
this.focusInput('pasteInput')
|
this.focusInput('pasteInput')
|
||||||
},
|
},
|
||||||
|
showWelcomeDialog: function () {
|
||||||
|
if (localStorage.getItem('cashu.welcomeDialogSeen') != 'seen') {
|
||||||
|
this.welcomeDialog.show = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setWelcomeDialogSeen: function () {
|
||||||
|
localStorage.setItem('cashu.welcomeDialogSeen', 'seen')
|
||||||
|
// kick of notification that no mints are present
|
||||||
|
// we have to do this because we disabled this notification since it
|
||||||
|
// covers the dialog
|
||||||
|
this.showNoMintsWarning()
|
||||||
|
},
|
||||||
showDisclaimerDialog: function () {
|
showDisclaimerDialog: function () {
|
||||||
this.disclaimerDialog.show = true
|
this.disclaimerDialog.show = true
|
||||||
},
|
},
|
||||||
|
|
@ -1391,9 +1505,9 @@ page_container %}
|
||||||
// } else if (req.indexOf('cashu:') !== 1) {
|
// } else if (req.indexOf('cashu:') !== 1) {
|
||||||
// this.receiveData.tokensBase64 = req.slice(req.indexOf('cashu:'))
|
// this.receiveData.tokensBase64 = req.slice(req.indexOf('cashu:'))
|
||||||
// reqtype = 'cashu'
|
// reqtype = 'cashu'
|
||||||
} else if (req.indexOf('W3siaWQ') !== 1) {
|
} else if (req.indexOf('eyJwcm') !== 1) {
|
||||||
// very dirty way of parsing cashu tokens
|
// very dirty way of parsing cashu tokens
|
||||||
this.receiveData.tokensBase64 = req.slice(req.indexOf('W3siaWQ'))
|
this.receiveData.tokensBase64 = req.slice(req.indexOf('eyJwcm'))
|
||||||
reqtype = 'cashu'
|
reqtype = 'cashu'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1532,11 +1646,10 @@ page_container %}
|
||||||
this.invoiceCheckWorker()
|
this.invoiceCheckWorker()
|
||||||
},
|
},
|
||||||
|
|
||||||
showTokenDialog: function (token) {
|
showTokenDialog: function (tokensBase64) {
|
||||||
console.log('##### showTokenDialog')
|
console.log('##### showTokenDialog')
|
||||||
// TODO: this must be decoded and desiarlized!
|
this.sendData.tokens = JSON.parse(atob(tokensBase64)).proofs
|
||||||
this.sendData.tokens = _.clone(token)
|
this.sendData.tokensBase64 = _.clone(tokensBase64)
|
||||||
this.sendData.tokensBase64 = _.clone(token)
|
|
||||||
this.showSendTokens = true
|
this.showSendTokens = true
|
||||||
// kick off token check worker
|
// kick off token check worker
|
||||||
this.checkTokenSpendableWorker()
|
this.checkTokenSpendableWorker()
|
||||||
|
|
@ -1672,7 +1785,8 @@ page_container %}
|
||||||
this.invoicesCashu.push({
|
this.invoicesCashu.push({
|
||||||
..._.clone(this.invoiceData),
|
..._.clone(this.invoiceData),
|
||||||
date: currentDateStr(),
|
date: currentDateStr(),
|
||||||
status: 'pending'
|
status: 'pending',
|
||||||
|
mint: this.activeMintURL
|
||||||
})
|
})
|
||||||
this.storeinvoicesCashu()
|
this.storeinvoicesCashu()
|
||||||
this.tab = 'invoices'
|
this.tab = 'invoices'
|
||||||
|
|
@ -2030,7 +2144,8 @@ page_container %}
|
||||||
hash: this.payInvoiceData.data.hash,
|
hash: this.payInvoiceData.data.hash,
|
||||||
memo: this.payInvoiceData.data.memo,
|
memo: this.payInvoiceData.data.memo,
|
||||||
date: currentDateStr(),
|
date: currentDateStr(),
|
||||||
status: 'paid'
|
status: 'paid',
|
||||||
|
mint: this.activeMintURL
|
||||||
})
|
})
|
||||||
this.storeinvoicesCashu()
|
this.storeinvoicesCashu()
|
||||||
this.tab = 'invoices'
|
this.tab = 'invoices'
|
||||||
|
|
@ -2170,10 +2285,13 @@ page_container %}
|
||||||
console.log('### checkInvoice.hash', payment_hash)
|
console.log('### checkInvoice.hash', payment_hash)
|
||||||
const invoice = this.invoicesCashu.find(i => i.hash === payment_hash)
|
const invoice = this.invoicesCashu.find(i => i.hash === payment_hash)
|
||||||
try {
|
try {
|
||||||
|
if (invoice.mint != null) {
|
||||||
|
this.activateMint(invoice.mint, false, false)
|
||||||
|
}
|
||||||
proofs = await this.mint(invoice.amount, invoice.hash, verbose)
|
proofs = await this.mint(invoice.amount, invoice.hash, verbose)
|
||||||
return proofs
|
return proofs
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Invoice still pending')
|
console.log('Invoice still pending', invoice.hash)
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -2208,8 +2326,14 @@ page_container %}
|
||||||
checks whether a base64-encoded token (from the history table) has been spent already.
|
checks whether a base64-encoded token (from the history table) has been spent already.
|
||||||
if it is spent, the appropraite entry in the history table is set to paid.
|
if it is spent, the appropraite entry in the history table is set to paid.
|
||||||
*/
|
*/
|
||||||
const tokenJson = atob(token)
|
const tokenJson = JSON.parse(atob(token))
|
||||||
const proofs = JSON.parse(tokenJson).proofs
|
const proofs = tokenJson.proofs
|
||||||
|
|
||||||
|
if (tokenJson.mints != null && tokenJson.mints[0].url != null) {
|
||||||
|
// todo: we activate only the first mint in the token
|
||||||
|
this.activateMint(tokenJson.mints[0].url)
|
||||||
|
}
|
||||||
|
|
||||||
const spendable = await this.checkProofsSpendable(proofs)
|
const spendable = await this.checkProofsSpendable(proofs)
|
||||||
let paid = false
|
let paid = false
|
||||||
if (spendable.includes(false)) {
|
if (spendable.includes(false)) {
|
||||||
|
|
@ -2224,7 +2348,7 @@ page_container %}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
this.notify('Token still pending', (color = 'grey'))
|
this.notify('Token still pending', (color = 'grey'))
|
||||||
}
|
}
|
||||||
this.sendData.tokens = token
|
// this.sendData.tokens = token
|
||||||
}
|
}
|
||||||
return paid
|
return paid
|
||||||
},
|
},
|
||||||
|
|
@ -2328,12 +2452,30 @@ page_container %}
|
||||||
throw new Error(`Mint error: ${response.error}`)
|
throw new Error(`Mint error: ${response.error}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
showNoMintsWarning: function () {
|
||||||
|
if (!this.activeMintURL) {
|
||||||
|
this.walletURL = this.baseURL
|
||||||
|
// we have to check whether the welcome dialog was pressed away because
|
||||||
|
// otherwise quasar falsely covers the welcome dialog with this notify
|
||||||
|
if (localStorage.getItem('cashu.welcomeDialogSeen') == 'seen') {
|
||||||
|
this.notifyWarning(
|
||||||
|
'You are not connected to any mints yet.',
|
||||||
|
'Add a new mint URL in the settings.',
|
||||||
|
30000
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tab = 'settings'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
notifySuccess: async function (message, position = 'top') {
|
notifySuccess: async function (message, position = 'top') {
|
||||||
this.$q.notify({
|
this.$q.notify({
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
message: message,
|
message: message,
|
||||||
position: position,
|
position: position,
|
||||||
|
progress: true,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
icon: 'close',
|
icon: 'close',
|
||||||
|
|
@ -2349,6 +2491,7 @@ page_container %}
|
||||||
message: message,
|
message: message,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
position: 'top',
|
position: 'top',
|
||||||
|
progress: true,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
icon: 'close',
|
icon: 'close',
|
||||||
|
|
@ -2365,10 +2508,11 @@ page_container %}
|
||||||
message: message,
|
message: message,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
position: 'top',
|
position: 'top',
|
||||||
|
progress: true,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
icon: 'close',
|
icon: 'close',
|
||||||
color: 'white',
|
color: 'black',
|
||||||
handler: () => {}
|
handler: () => {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -2515,15 +2659,7 @@ page_container %}
|
||||||
activeMintURL = localStorage.getItem('cashu.activeMintURL')
|
activeMintURL = localStorage.getItem('cashu.activeMintURL')
|
||||||
this.addMint(activeMintURL)
|
this.addMint(activeMintURL)
|
||||||
}
|
}
|
||||||
if (!this.activeMintURL) {
|
this.showNoMintsWarning()
|
||||||
this.walletURL = this.baseURL
|
|
||||||
this.notifyWarning(
|
|
||||||
'You are not connected to any mints yet.',
|
|
||||||
'Add a new mint URL in the settings.',
|
|
||||||
20000
|
|
||||||
)
|
|
||||||
this.tab = 'settings'
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: remove:
|
// todo: remove:
|
||||||
if (!this.mintId.length) {
|
if (!this.mintId.length) {
|
||||||
|
|
@ -2533,6 +2669,8 @@ page_container %}
|
||||||
console.log('Mint URL ' + this.activeMintURL)
|
console.log('Mint URL ' + this.activeMintURL)
|
||||||
console.log('Wallet URL ' + this.walletURL)
|
console.log('Wallet URL ' + this.walletURL)
|
||||||
|
|
||||||
|
const startupMintUrl = this.activeMintURL
|
||||||
|
|
||||||
// get name
|
// get name
|
||||||
if (params.get('mint_name')) {
|
if (params.get('mint_name')) {
|
||||||
this.mintName = params.get('mint_name')
|
this.mintName = params.get('mint_name')
|
||||||
|
|
@ -2608,6 +2746,13 @@ page_container %}
|
||||||
this.checkPendingTokens().catch(err => {
|
this.checkPendingTokens().catch(err => {
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// reset to the mint from settings after workers have run
|
||||||
|
if (startupMintUrl != null) {
|
||||||
|
this.activateMint(startupMintUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showWelcomeDialog()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue