/* global _, Vue, moment, LNbits, EventHub, decryptLnurlPayAES */ Vue.component('lnbits-fsat', { props: { amount: { type: Number, default: 0 } }, template: '{{ fsat }}', computed: { fsat: function () { return LNbits.utils.formatSat(this.amount) } } }) Vue.component('lnbits-wallet-list', { data: function () { return { user: null, activeWallet: null, activeBalance: [], showForm: false, walletName: '', LNBITS_DENOMINATION: LNBITS_DENOMINATION } }, template: ` {{ wallet.name }} {{ parseFloat(String(wallet.live_fsat).replaceAll(",", "")) / 100 }} {{ LNBITS_DENOMINATION }} {{ wallet.live_fsat }} {{ LNBITS_DENOMINATION }} `, computed: { wallets: function () { var bal = this.activeBalance return this.user.wallets.map(function (obj) { obj.live_fsat = bal.length && bal[0] === obj.id ? LNbits.utils.formatSat(bal[1]) : obj.fsat return obj }) } }, methods: { createWallet: function () { LNbits.href.createWallet(this.walletName, this.user.id) }, updateWalletBalance: function (payload) { this.activeBalance = payload } }, created: function () { if (window.user) { this.user = LNbits.map.user(window.user) } if (window.wallet) { this.activeWallet = LNbits.map.wallet(window.wallet) } EventHub.$on('update-wallet-balance', this.updateWalletBalance) } }) Vue.component('lnbits-extension-list', { data: function () { return { extensions: [], user: null } }, template: ` {{ extension.name }}
`, computed: { userExtensions: function () { if (!this.user) return [] var path = window.location.pathname var userExtensions = this.user.extensions return this.extensions .filter(function (obj) { return userExtensions.indexOf(obj.code) !== -1 }) .map(function (obj) { obj.isActive = path.startsWith(obj.url) return obj }) } }, created: function () { if (window.extensions) { this.extensions = window.extensions .map(function (data) { return LNbits.map.extension(data) }) .sort(function (a, b) { return a.name.localeCompare(b.name) }) } if (window.user) { this.user = LNbits.map.user(window.user) } } }) Vue.component('lnbits-admin-ui', { props: ['showNode'], data: function () { return { extensions: [], user: null } }, template: ` Admin `, created: function () { if (window.user) { this.user = LNbits.map.user(window.user) } } }) Vue.component('lnbits-payment-details', { props: ['payment'], mixins: [windowMixin], data: function () { return { LNBITS_DENOMINATION: LNBITS_DENOMINATION } }, template: `
#{{ payment.tag }}
: {{ payment.date }} ({{ payment.dateFrom }})
: {{ payment.expirydate }} ({{ payment.expirydateFrom }})
: {{ (payment.amount / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}
: {{ (payment.fee / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}
: {{ payment.payment_hash }}
: {{ payment.memo }}
: {{ payment.webhook }}:  {{ webhookStatusText }}
: {{ payment.preimage }}
extra {{ entry.key }}: {{ entry.value }}
Success action:
`, computed: { hasPreimage() { return ( this.payment.preimage && this.payment.preimage !== '0000000000000000000000000000000000000000000000000000000000000000' ) }, hasSuccessAction() { return ( this.hasPreimage && this.payment.extra && this.payment.extra.success_action ) }, webhookStatusColor() { return this.payment.webhook_status >= 300 || this.payment.webhook_status < 0 ? 'red-10' : !this.payment.webhook_status ? 'cyan-7' : 'green-10' }, webhookStatusText() { return this.payment.webhook_status ? this.payment.webhook_status : 'not sent yet' }, hasTag() { return this.payment.extra && !!this.payment.extra.tag }, extras() { if (!this.payment.extra) return [] let extras = _.omit(this.payment.extra, ['tag', 'success_action']) return Object.keys(extras).map(key => ({key, value: extras[key]})) } } }) Vue.component('lnbits-lnurlpay-success-action', { props: ['payment', 'success_action'], data() { return { decryptedValue: this.success_action.ciphertext } }, template: `

{{ success_action.message || success_action.description }}

{{ decryptedValue }}

{{ success_action.url }}

`, mounted: function () { if (this.success_action.tag !== 'aes') return null decryptLnurlPayAES(this.success_action, this.payment.preimage).then( value => { this.decryptedValue = value } ) } }) Vue.component('lnbits-notifications-btn', { mixins: [windowMixin], props: ['pubkey'], data() { return { isSupported: false, isSubscribed: false, isPermissionGranted: false, isPermissionDenied: false } }, template: ` Subscribe to notifications Unsubscribe from notifications Notifications are disabled,
please enable or reset permissions
Notifications are not supported
`, methods: { // converts base64 to Array buffer urlB64ToUint8Array(base64String) { const padding = '='.repeat((4 - (base64String.length % 4)) % 4) const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/') const rawData = atob(base64) const outputArray = new Uint8Array(rawData.length) for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i) } return outputArray }, toggleNotifications() { this.isSubscribed ? this.unsubscribe() : this.subscribe() }, saveUserSubscribed(user) { let subscribedUsers = JSON.parse( this.$q.localStorage.getItem('lnbits.webpush.subscribedUsers') ) || [] if (!subscribedUsers.includes(user)) subscribedUsers.push(user) this.$q.localStorage.set( 'lnbits.webpush.subscribedUsers', JSON.stringify(subscribedUsers) ) }, removeUserSubscribed(user) { let subscribedUsers = JSON.parse( this.$q.localStorage.getItem('lnbits.webpush.subscribedUsers') ) || [] subscribedUsers = subscribedUsers.filter(arr => arr !== user) this.$q.localStorage.set( 'lnbits.webpush.subscribedUsers', JSON.stringify(subscribedUsers) ) }, isUserSubscribed(user) { let subscribedUsers = JSON.parse( this.$q.localStorage.getItem('lnbits.webpush.subscribedUsers') ) || [] return subscribedUsers.includes(user) }, subscribe() { var self = this // catch clicks from disabled type='a' button (https://github.com/quasarframework/quasar/issues/9258) if (!this.isSupported || this.isPermissionDenied) { return } // ask for notification permission Notification.requestPermission() .then(permission => { this.isPermissionGranted = permission === 'granted' this.isPermissionDenied = permission === 'denied' }) .catch(function (e) { console.log(e) }) // create push subscription navigator.serviceWorker.ready.then(registration => { navigator.serviceWorker.getRegistration().then(registration => { registration.pushManager .getSubscription() .then(function (subscription) { if ( subscription === null || !self.isUserSubscribed(self.g.user.id) ) { const applicationServerKey = self.urlB64ToUint8Array( self.pubkey ) const options = {applicationServerKey, userVisibleOnly: true} registration.pushManager .subscribe(options) .then(function (subscription) { LNbits.api .request( 'POST', '/api/v1/webpush', self.g.user.wallets[0].adminkey, { subscription: JSON.stringify(subscription) } ) .then(function (response) { self.saveUserSubscribed(response.data.user) self.isSubscribed = true }) .catch(function (error) { LNbits.utils.notifyApiError(error) }) }) } }) .catch(function (e) { console.log(e) }) }) }) }, unsubscribe() { var self = this navigator.serviceWorker.ready .then(registration => { registration.pushManager.getSubscription().then(subscription => { if (subscription) { LNbits.api .request( 'DELETE', '/api/v1/webpush?endpoint=' + btoa(subscription.endpoint), self.g.user.wallets[0].adminkey ) .then(function () { self.removeUserSubscribed(self.g.user.id) self.isSubscribed = false }) .catch(function (error) { LNbits.utils.notifyApiError(error) }) } }) }) .catch(function (e) { console.log(e) }) }, checkSupported: function () { let https = window.location.protocol === 'https:' let serviceWorkerApi = 'serviceWorker' in navigator let notificationApi = 'Notification' in window let pushApi = 'PushManager' in window this.isSupported = https && serviceWorkerApi && notificationApi && pushApi if (!this.isSupported) { console.log( 'Notifications disabled because requirements are not met:', { HTTPS: https, 'Service Worker API': serviceWorkerApi, 'Notification API': notificationApi, 'Push API': pushApi } ) } return this.isSupported }, updateSubscriptionStatus: async function () { var self = this await navigator.serviceWorker.ready .then(registration => { registration.pushManager.getSubscription().then(subscription => { self.isSubscribed = !!subscription && self.isUserSubscribed(self.g.user.id) }) }) .catch(function (e) { console.log(e) }) } }, created: function () { this.isPermissionDenied = Notification.permission === 'denied' if (this.checkSupported()) { this.updateSubscriptionStatus() } } })