Browse Source

Moved scan to outside of receive

LNURLwalletsupport
arcbtc 4 years ago
parent
commit
89022d8948
  1. 36
      lnbits/core/static/js/wallet.js
  2. 581
      lnbits/core/templates/core/wallet.html

36
lnbits/core/static/js/wallet.js

@ -131,7 +131,7 @@ new Vue({
bolt11: '' bolt11: ''
} }
}, },
sendCamera: { theCamera: {
show: false, show: false,
camera: 'auto' camera: 'auto'
}, },
@ -199,11 +199,17 @@ new Vue({
} }
}, },
methods: { methods: {
// closeCamera: function () {
// this.sendCamera.show = false
// },
// showCamera: function () {
// this.sendCamera.show = true
// },
closeCamera: function () { closeCamera: function () {
this.sendCamera.show = false this.theCamera.show = false
}, },
showCamera: function () { showCamera: function () {
this.sendCamera.show = true this.theCamera.show = true
}, },
showChart: function () { showChart: function () {
this.paymentsChart.show = true this.paymentsChart.show = true
@ -240,7 +246,7 @@ new Vue({
}, 10000) }, 10000)
}, },
closeSendDialog: function () { closeSendDialog: function () {
this.sendCamera.show = false // this.sendCamera.show = false
var checker = this.send.paymentChecker var checker = this.send.paymentChecker
setTimeout(function () { setTimeout(function () {
clearInterval(checker) clearInterval(checker)
@ -277,10 +283,26 @@ new Vue({
}) })
}, },
decodeQR: function (res) { decodeQR: function (res) {
this.send.data.bolt11 = res if (res.substring(0, 4) == 'lnurl') {
this.decodeInvoice() console.log(res)
this.sendCamera.show = false var self = this
LNbits.api
.request('GET', '/lnurlscan/' + res, this.g.user.wallets[0].adminkey)
.then(function (response) {
console.log(response.data)
})
.catch(function (error) {
clearInterval(self.checker)
LNbits.utils.notifyApiError(error)
})
} else {
this.send.data.bolt11 = res
this.decodeInvoice()
this.theCamera.show = false
}
}, },
decodeInvoice: function () { decodeInvoice: function () {
if (this.send.data.bolt11.startsWith('lightning:')) { if (this.send.data.bolt11.startsWith('lightning:')) {
this.send.data.bolt11 = this.send.data.bolt11.slice(10) this.send.data.bolt11 = this.send.data.bolt11.slice(10)

581
lnbits/core/templates/core/wallet.html

@ -1,259 +1,360 @@
{% extends "base.html" %} {% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block styles %}
{% from "macros.jinja" import window_vars with context %} <link
rel="stylesheet"
type="text/css"
{% block styles %} href="{{ url_for('static', filename='vendor/vue-qrcode-reader@2.2.0/vue-qrcode-reader.min.css') }}"
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='vendor/vue-qrcode-reader@2.2.0/vue-qrcode-reader.min.css') }}"> />
{% endblock %} {% endblock %} {% block scripts %} {{ window_vars(user, wallet) }}
<script src="{{ url_for('static', filename='vendor/vue-qrcode@1.0.2/vue-qrcode.min.js') }}"></script>
{% assets filters='rjsmin', output='__bundle__/core/chart.js',
'vendor/moment@2.25.1/moment.min.js', 'vendor/chart.js@2.9.3/chart.min.js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %} {% assets filters='rjsmin', output='__bundle__/core/wallet.js',
'vendor/bolt11/utils.js', 'vendor/bolt11/decoder.js',
'vendor/vue-qrcode-reader@2.2.0/vue-qrcode-reader.min.js', 'core/js/wallet.js'
%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %} {% endblock %} {% block page %}
<div class="row q-col-gutter-md">
<div class="col-12 col-md-7 q-gutter-y-md">
<q-card>
<q-card-section>
<h3 class="q-my-none">
<strong>{% raw %}{{ fbalance }}{% endraw %}</strong> sat
</h3>
</q-card-section>
<div class="row q-pb-md q-px-md q-col-gutter-md">
<div class="col">
<q-btn
unelevated
color="deep-purple"
class="full-width"
@click="showSendDialog"
>Send</q-btn
>
</div>
<div class="col">
<q-btn
unelevated
color="deep-purple"
class="full-width"
@click="showReceiveDialog"
>Receive</q-btn
>
</div>
{% block scripts %} <div class="col">
{{ window_vars(user, wallet) }} <q-btn
<script src="{{ url_for('static', filename='vendor/vue-qrcode@1.0.2/vue-qrcode.min.js') }}"></script> unelevated
{% assets filters='rjsmin', output='__bundle__/core/chart.js', color="purple"
'vendor/moment@2.25.1/moment.min.js', icon="photo_camera"
'vendor/chart.js@2.9.3/chart.min.js' %} @click="showCamera"
<script type="text/javascript" src="{{ ASSET_URL }}"></script> >scan
{% endassets %} <q-tooltip>Use camera to scan an invoice/QR</q-tooltip>
{% assets filters='rjsmin', output='__bundle__/core/wallet.js', </q-btn>
'vendor/bolt11/utils.js', </div>
'vendor/bolt11/decoder.js', </div>
'vendor/vue-qrcode-reader@2.2.0/vue-qrcode-reader.min.js', </q-card>
'core/js/wallet.js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% endblock %}
{% block page %} <q-card>
<div class="row q-col-gutter-md"> <q-card-section>
<div class="col-12 col-md-7 q-gutter-y-md"> <div class="row items-center no-wrap q-mb-sm">
<q-card>
<q-card-section>
<h3 class="q-my-none"><strong>{% raw %}{{ fbalance }}{% endraw %}</strong> sat</h3>
</q-card-section>
<div class="row q-pb-md q-px-md q-col-gutter-md">
<div class="col">
<q-btn unelevated
color="purple"
class="full-width"
@click="showSendDialog">Send</q-btn>
</div>
<div class="col"> <div class="col">
<q-btn unelevated <h5 class="text-subtitle1 q-my-none">Transactions</h5>
color="deep-purple"
class="full-width"
@click="showReceiveDialog">Receive</q-btn>
</div> </div>
</div> <div class="col-auto">
</q-card> <q-btn flat color="grey" @click="exportCSV">Export to CSV</q-btn>
<!--<q-btn v-if="pendingPaymentsExist" dense flat round icon="update" color="grey" @click="checkPendingPayments">
<q-card>
<q-card-section>
<div class="row items-center no-wrap q-mb-sm">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Transactions</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportCSV">Export to CSV</q-btn>
<!--<q-btn v-if="pendingPaymentsExist" dense flat round icon="update" color="grey" @click="checkPendingPayments">
<q-tooltip>Check pending</q-tooltip> <q-tooltip>Check pending</q-tooltip>
</q-btn>--> </q-btn>-->
<q-btn dense flat round icon="show_chart" color="grey" @click="showChart"> <q-btn
<q-tooltip>Show chart</q-tooltip> dense
</q-btn> flat
</div> round
icon="show_chart"
color="grey"
@click="showChart"
>
<q-tooltip>Show chart</q-tooltip>
</q-btn>
</div> </div>
<q-input v-if="payments.length > 10" filled dense clearable </div>
v-model="paymentsTable.filter" <q-input
debounce="300" placeholder="Search by memo, amount" class="q-mb-md"> v-if="payments.length > 10"
</q-input> filled
<q-table dense flat dense
:data="filteredPayments" clearable
row-key="payhash" v-model="paymentsTable.filter"
:columns="paymentsTable.columns" debounce="300"
:pagination.sync="paymentsTable.pagination"> placeholder="Search by memo, amount"
{% raw %} class="q-mb-md"
<template v-slot:header="props"> >
<q-tr :props="props"> </q-input>
<q-th auto-width></q-th> <q-table
<q-th dense
v-for="col in props.cols" flat
:key="col.name" :data="filteredPayments"
:props="props">{{ col.label }}</q-th> row-key="payhash"
</q-tr> :columns="paymentsTable.columns"
</template> :pagination.sync="paymentsTable.pagination"
<template v-slot:body="props"> >
<q-tr :props="props"> {% raw %}
<q-td auto-width class="lnbits__q-table__icon-td"> <template v-slot:header="props">
<q-icon v-if="props.row.isPaid" size="14px" <q-tr :props="props">
:name="(props.row.sat < 0) ? 'call_made' : 'call_received'" <q-th auto-width></q-th>
:color="(props.row.sat < 0) ? 'pink' : 'green'"></q-icon> <q-th v-for="col in props.cols" :key="col.name" :props="props"
<q-icon v-else name="settings_ethernet" color="grey"> >{{ col.label }}</q-th
<q-tooltip>Pending</q-tooltip> >
</q-icon> </q-tr>
</q-td> </template>
<q-td key="memo" :props="props"> <template v-slot:body="props">
{{ props.row.memo }} <q-tr :props="props">
</q-td> <q-td auto-width class="lnbits__q-table__icon-td">
<q-td auto-width key="date" :props="props"> <q-icon
{{ props.row.date }} v-if="props.row.isPaid"
</q-td> size="14px"
<q-td auto-width key="sat" :props="props"> :name="(props.row.sat < 0) ? 'call_made' : 'call_received'"
{{ props.row.fsat }} :color="(props.row.sat < 0) ? 'pink' : 'green'"
</q-td> ></q-icon>
</q-tr> <q-icon v-else name="settings_ethernet" color="grey">
</template> <q-tooltip>Pending</q-tooltip>
{% endraw %} </q-icon>
</q-table> </q-td>
</q-card-section> <q-td key="memo" :props="props">
</q-card> {{ props.row.memo }}
</div> </q-td>
<q-td auto-width key="date" :props="props">
{{ props.row.date }}
</q-td>
<q-td auto-width key="sat" :props="props">
{{ props.row.fsat }}
</q-td>
</q-tr>
</template>
{% endraw %}
</q-table>
</q-card-section>
</q-card>
</div>
<div class="col-12 col-md-5 q-gutter-y-md"> <div class="col-12 col-md-5 q-gutter-y-md">
<q-card> <q-card>
<q-card-section> <q-card-section>
<q-btn flat color="grey" @click="exportCSV" class="float-right">Renew keys</q-btn> <q-btn flat color="grey" @click="exportCSV" class="float-right"
<h6 class="text-subtitle1 q-mt-none q-mb-sm">LNbits wallet</h6> >Renew keys</q-btn
<strong>Wallet name: </strong><em>{{ wallet.name }}</em><br> >
<strong>Wallet ID: </strong><em>{{ wallet.id }}</em><br> <h6 class="text-subtitle1 q-mt-none q-mb-sm">LNbits wallet</h6>
<strong>Admin key: </strong><em>{{ wallet.adminkey }}</em><br> <strong>Wallet name: </strong><em>{{ wallet.name }}</em><br />
<strong>Invoice/read key: </strong><em>{{ wallet.inkey }}</em> <strong>Wallet ID: </strong><em>{{ wallet.id }}</em><br />
</q-card-section> <strong>Admin key: </strong><em>{{ wallet.adminkey }}</em><br />
<q-card-section class="q-pa-none"> <strong>Invoice/read key: </strong><em>{{ wallet.inkey }}</em>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<q-list>
{% include "core/_api_docs.html" %}
<q-separator></q-separator> <q-separator></q-separator>
<q-list> <q-expansion-item
{% include "core/_api_docs.html" %} group="extras"
<q-separator></q-separator> icon="remove_circle"
<q-expansion-item label="Delete wallet"
group="extras" >
icon="remove_circle" <q-card>
label="Delete wallet"> <q-card-section>
<q-card> <p>
<q-card-section> This whole wallet will be deleted, the funds will be
<p>This whole wallet will be deleted, the funds will be <strong>UNRECOVERABLE</strong>.</p> <strong>UNRECOVERABLE</strong>.
<q-btn unelevated </p>
color="red-10" <q-btn
@click="deleteWallet('{{ wallet.id }}', '{{ user.id }}')">Delete wallet</q-btn> unelevated
</q-card-section> color="red-10"
</q-card> @click="deleteWallet('{{ wallet.id }}', '{{ user.id }}')"
</q-expansion-item> >Delete wallet</q-btn
</q-list> >
</q-card-section> </q-card-section>
</q-card> </q-card>
</div> </q-expansion-item>
</q-list>
</q-card-section>
</q-card>
</div> </div>
</div>
<q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog"> <q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog">
<q-card v-if="!receive.paymentReq" class="q-pa-lg q-pt-xl lnbits__dialog-card"> <q-card
<q-form @submit="createInvoice" class="q-gutter-md"> v-if="!receive.paymentReq"
<q-input filled dense class="q-pa-lg q-pt-xl lnbits__dialog-card"
v-model.number="receive.data.amount" >
type="number" <q-form @submit="createInvoice" class="q-gutter-md">
label="Amount (sat) *"></q-input> <q-input
<q-input filled dense filled
v-model.trim="receive.data.memo" dense
label="Memo" v-model.number="receive.data.amount"
placeholder="LNbits invoice"></q-input> type="number"
<div v-if="receive.status == 'pending'" class="row q-mt-lg"> label="Amount (sat) *"
<q-btn unelevated ></q-input>
color="deep-purple" <q-input
:disable="receive.data.amount == null || receive.data.amount <= 0" filled
type="submit">Create invoice</q-btn> dense
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn> v-model.trim="receive.data.memo"
</div> label="Memo"
<q-spinner v-if="receive.status == 'loading'" color="deep-purple" size="2.55em"></q-spinner> placeholder="LNbits invoice"
</q-form> ></q-input>
</q-card> <div v-if="receive.status == 'pending'" class="row q-mt-lg">
<q-card v-else class="q-pa-lg q-pt-xl lnbits__dialog-card"> <q-btn
<div class="text-center q-mb-lg"> unelevated
<a :href="'lightning:' + receive.paymentReq"> color="deep-purple"
<q-responsive :ratio="1" class="q-mx-xl"> :disable="receive.data.amount == null || receive.data.amount <= 0"
<qrcode :value="receive.paymentReq" :options="{width: 340}" class="rounded-borders"></qrcode> type="submit"
</q-responsive> >Create invoice</q-btn
</a> >
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div> </div>
<div class="row q-mt-lg"> <q-spinner
<q-btn outline color="grey" @click="copyText(receive.paymentReq)">Copy invoice</q-btn> v-if="receive.status == 'loading'"
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn> color="deep-purple"
</div> size="2.55em"
</q-card> ></q-spinner>
</q-dialog> </q-form>
</q-card>
<q-card v-else class="q-pa-lg q-pt-xl lnbits__dialog-card">
<div class="text-center q-mb-lg">
<a :href="'lightning:' + receive.paymentReq">
<q-responsive :ratio="1" class="q-mx-xl">
<qrcode
:value="receive.paymentReq"
:options="{width: 340}"
class="rounded-borders"
></qrcode>
</q-responsive>
</a>
</div>
<div class="row q-mt-lg">
<q-btn outline color="grey" @click="copyText(receive.paymentReq)"
>Copy invoice</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
</div>
</q-card>
</q-dialog>
<q-dialog v-model="send.show" position="top" @hide="closeSendDialog"> <q-dialog v-model="send.show" position="top" @hide="closeSendDialog">
<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="!send.invoice"> <div v-if="!send.invoice">
<q-form v-if="!sendCamera.show" @submit="decodeInvoice" class="q-gutter-md"> <q-form @submit="decodeInvoice" class="q-gutter-md">
<q-input filled dense <q-input
v-model.trim="send.data.bolt11" filled
type="textarea" dense
label="Paste an invoice *"> v-model.trim="send.data.bolt11"
<template v-slot:after> type="textarea"
<q-btn round dense flat icon="photo_camera" @click="showCamera"> label="Paste an invoice *"
<q-tooltip>Use camera to scan an invoice</q-tooltip> >
</q-btn> </q-input>
</template> <div class="row q-mt-lg">
</q-input> <q-btn
<div class="row q-mt-lg"> unelevated
<q-btn unelevated
color="deep-purple"
:disable="send.data.bolt11 == ''"
type="submit">Read invoice</q-btn>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div>
</q-form>
<div v-else>
<q-responsive :ratio="1">
<qrcode-stream @decode="decodeQR" class="rounded-borders"></qrcode-stream>
</q-responsive>
<div class="row q-mt-lg">
<q-btn @click="closeCamera" flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div>
</div>
</div>
<div v-else>
{% raw %}
<h6 class="q-my-none">{{ send.invoice.fsat }} sat</h6>
<q-separator class="q-my-sm"></q-separator>
<p style="word-break: break-all">
<strong>Memo:</strong> {{ send.invoice.description }}<br>
<strong>Expire date:</strong> {{ send.invoice.expireDate }}<br>
<strong>Hash:</strong> {{ send.invoice.hash }}
</p>
{% endraw %}
<div v-if="canPay" class="row q-mt-lg">
<q-btn unelevated
color="deep-purple" color="deep-purple"
@click="payInvoice">Send satoshis</q-btn> :disable="send.data.bolt11 == ''"
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn> type="submit"
>Read invoice</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
</div> </div>
<div v-else class="row q-mt-lg"> </q-form>
<q-btn unelevated disabled color="yellow" text-color="black">Not enough funds!</q-btn> <div v-else>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn> <q-responsive :ratio="1">
<qrcode-stream
@decode="decodeQR"
class="rounded-borders"
></qrcode-stream>
</q-responsive>
<div class="row q-mt-lg">
<q-btn @click="closeCamera" flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
</div> </div>
</div> </div>
</q-card> </div>
</q-dialog> <div v-else>
{% raw %}
<h6 class="q-my-none">{{ send.invoice.fsat }} sat</h6>
<q-separator class="q-my-sm"></q-separator>
<p style="word-break: break-all;">
<strong>Memo:</strong> {{ send.invoice.description }}<br />
<strong>Expire date:</strong> {{ send.invoice.expireDate }}<br />
<strong>Hash:</strong> {{ send.invoice.hash }}
</p>
{% endraw %}
<div v-if="canPay" class="row q-mt-lg">
<q-btn unelevated color="deep-purple" @click="payInvoice"
>Send satoshis</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div>
<div v-else class="row q-mt-lg">
<q-btn unelevated disabled color="yellow" text-color="black"
>Not enough funds!</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div>
</div>
</q-card>
</q-dialog>
<q-dialog v-model="paymentsChart.show" position="top"> <q-dialog v-model="theCamera.show" position="top">
<q-card class="q-pa-sm" style="width: 800px; max-width: unset"> <q-card class="q-pa-lg q-pt-xl">
<q-card-section> <div class="text-center q-mb-lg">
<canvas ref="canvas" width="600" height="400"></canvas> <qrcode-stream @decode="decodeQR" class="rounded-borders"></qrcode-stream>
</q-card-section> </div>
</q-card> <div class="row q-mt-lg">
</q-dialog> <q-btn @click="closeCamera" flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-card>
</q-dialog>
{% if service_fee > 0 %} <q-dialog v-model="paymentsChart.show" position="top">
<div ref="disclaimer"></div> <q-card class="q-pa-sm" style="width: 800px; max-width: unset;">
<q-dialog v-model="disclaimerDialog.show"> <q-card-section>
<q-card class="q-pa-lg"> <canvas ref="canvas" width="600" height="400"></canvas>
<h6 class="q-my-md text-deep-purple">Warning</h6> </q-card-section>
<p>Login functionality to be released in v0.2, for now, <strong>make sure you bookmark this page for future access to your wallet</strong>!</p> </q-card>
<p>This service is in BETA, and we hold no responsibility for people losing access to funds. To encourage you to run your own LNbits installation, any balance on {% raw %}{{ disclaimerDialog.location.host }}{% endraw %} will incur a charge of <strong>{{ service_fee }}% service fee</strong> per week.</p> </q-dialog>
<div class="row q-mt-lg">
<q-btn outline color="grey" @click="copyText(disclaimerDialog.location.href)">Copy wallet URL</q-btn> {% if service_fee > 0 %}
<q-btn v-close-popup flat color="grey" class="q-ml-auto">I understand</q-btn> <div ref="disclaimer"></div>
</div> <q-dialog v-model="disclaimerDialog.show">
</q-card> <q-card class="q-pa-lg">
</q-dialog> <h6 class="q-my-md text-deep-purple">Warning</h6>
{% endif %} <p>
{% endblock %} Login functionality to be released in v0.2, for now,
<strong
>make sure you bookmark this page for future access to your
wallet</strong
>!
</p>
<p>
This service is in BETA, and we hold no responsibility for people losing
access to funds. To encourage you to run your own LNbits installation, any
balance on {% raw %}{{ disclaimerDialog.location.host }}{% endraw %} will
incur a charge of <strong>{{ service_fee }}% service fee</strong> per
week.
</p>
<div class="row q-mt-lg">
<q-btn
outline
color="grey"
@click="copyText(disclaimerDialog.location.href)"
>Copy wallet URL</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>I understand</q-btn
>
</div>
</q-card>
</q-dialog>
{% endif %} {% endblock %}

Loading…
Cancel
Save