mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-25 23:21:21 +01:00
529 lines
13 KiB
JavaScript
529 lines
13 KiB
JavaScript
window.app.component(QrcodeVue)
|
|
|
|
window.app.component('lnbits-extension-rating', {
|
|
template: '#lnbits-extension-rating',
|
|
name: 'lnbits-extension-rating',
|
|
props: ['rating']
|
|
})
|
|
|
|
window.app.component('lnbits-fsat', {
|
|
template: '<span>{{ fsat }}</span>',
|
|
props: {
|
|
amount: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
computed: {
|
|
fsat() {
|
|
return LNbits.utils.formatSat(this.amount)
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-wallet-list', {
|
|
template: '#lnbits-wallet-list',
|
|
props: ['balance'],
|
|
data() {
|
|
return {
|
|
user: null,
|
|
activeWallet: null,
|
|
balance: 0,
|
|
showForm: false,
|
|
walletName: '',
|
|
LNBITS_DENOMINATION: LNBITS_DENOMINATION
|
|
}
|
|
},
|
|
computed: {
|
|
wallets() {
|
|
const bal = this.balance
|
|
return this.user.wallets.map(obj => {
|
|
obj.live_fsat =
|
|
bal.length && bal[0] === obj.id
|
|
? LNbits.utils.formatSat(bal[1])
|
|
: obj.fsat
|
|
return obj
|
|
})
|
|
}
|
|
},
|
|
methods: {
|
|
createWallet() {
|
|
LNbits.api.createWallet(this.user.wallets[0], this.walletName)
|
|
}
|
|
},
|
|
created() {
|
|
if (window.user) {
|
|
this.user = LNbits.map.user(window.user)
|
|
}
|
|
if (window.wallet) {
|
|
this.activeWallet = LNbits.map.wallet(window.wallet)
|
|
}
|
|
document.addEventListener('updateWalletBalance', this.updateWalletBalance)
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-extension-list', {
|
|
template: '#lnbits-extension-list',
|
|
data() {
|
|
return {
|
|
extensions: [],
|
|
user: null,
|
|
userExtensions: [],
|
|
searchTerm: ''
|
|
}
|
|
},
|
|
watch: {
|
|
searchTerm(term) {
|
|
this.userExtensions = this.updateUserExtensions(term)
|
|
}
|
|
},
|
|
methods: {
|
|
updateUserExtensions(filterBy) {
|
|
if (!this.user) return []
|
|
|
|
const path = window.location.pathname
|
|
const userExtensions = this.user.extensions
|
|
|
|
return this.extensions
|
|
.filter(o => {
|
|
return userExtensions.indexOf(o.code) !== -1
|
|
})
|
|
.filter(o => {
|
|
if (!filterBy) return true
|
|
return (
|
|
`${o.code} ${o.name} ${o.short_description} ${o.url}`
|
|
.toLocaleLowerCase()
|
|
.indexOf(filterBy.toLocaleLowerCase()) !== -1
|
|
)
|
|
})
|
|
.map(obj => {
|
|
obj.isActive = path.startsWith(obj.url)
|
|
return obj
|
|
})
|
|
}
|
|
},
|
|
async created() {
|
|
if (window.user) {
|
|
this.user = LNbits.map.user(window.user)
|
|
}
|
|
|
|
try {
|
|
const {data} = await LNbits.api.request('GET', '/api/v1/extension')
|
|
this.extensions = data
|
|
.map(data => {
|
|
return LNbits.map.extension(data)
|
|
})
|
|
.sort((a, b) => {
|
|
return a.name.localeCompare(b.name)
|
|
})
|
|
this.userExtensions = this.updateUserExtensions()
|
|
} catch (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-manage', {
|
|
template: '#lnbits-manage',
|
|
props: ['showAdmin', 'showNode', 'showExtensions', 'showUsers', 'showAudit'],
|
|
methods: {
|
|
isActive(path) {
|
|
return window.location.pathname === path
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
extensions: [],
|
|
user: null
|
|
}
|
|
},
|
|
created() {
|
|
if (window.user) {
|
|
this.user = LNbits.map.user(window.user)
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-payment-details', {
|
|
template: '#lnbits-payment-details',
|
|
props: ['payment'],
|
|
mixins: [window.windowMixin],
|
|
data() {
|
|
return {
|
|
LNBITS_DENOMINATION: LNBITS_DENOMINATION
|
|
}
|
|
},
|
|
computed: {
|
|
hasPreimage() {
|
|
return (
|
|
this.payment.preimage &&
|
|
this.payment.preimage !==
|
|
'0000000000000000000000000000000000000000000000000000000000000000'
|
|
)
|
|
},
|
|
hasExpiry() {
|
|
return !!this.payment.expiry
|
|
},
|
|
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]}))
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-lnurlpay-success-action', {
|
|
template: '#lnbits-lnurlpay-success-action',
|
|
props: ['payment', 'success_action'],
|
|
data() {
|
|
return {
|
|
decryptedValue: this.success_action.ciphertext
|
|
}
|
|
},
|
|
mounted() {
|
|
if (this.success_action.tag !== 'aes') return null
|
|
decryptLnurlPayAES(this.success_action, this.payment.preimage).then(
|
|
value => {
|
|
this.decryptedValue = value
|
|
}
|
|
)
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-qrcode', {
|
|
template: '#lnbits-qrcode',
|
|
mixins: [window.windowMixin],
|
|
components: {
|
|
QrcodeVue
|
|
},
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
options: Object
|
|
},
|
|
data() {
|
|
return {
|
|
custom: {
|
|
margin: 1,
|
|
width: 350,
|
|
size: 350,
|
|
logo: LNBITS_QR_LOGO
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
this.custom = {...this.custom, ...this.options}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-notifications-btn', {
|
|
template: '#lnbits-notifications-btn',
|
|
mixins: [window.windowMixin],
|
|
props: ['pubkey'],
|
|
data() {
|
|
return {
|
|
isSupported: false,
|
|
isSubscribed: false,
|
|
isPermissionGranted: false,
|
|
isPermissionDenied: false
|
|
}
|
|
},
|
|
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() {
|
|
// 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(console.log)
|
|
|
|
// create push subscription
|
|
navigator.serviceWorker.ready.then(registration => {
|
|
navigator.serviceWorker.getRegistration().then(registration => {
|
|
registration.pushManager
|
|
.getSubscription()
|
|
.then(subscription => {
|
|
if (
|
|
subscription === null ||
|
|
!this.isUserSubscribed(this.g.user.id)
|
|
) {
|
|
const applicationServerKey = this.urlB64ToUint8Array(
|
|
this.pubkey
|
|
)
|
|
const options = {applicationServerKey, userVisibleOnly: true}
|
|
|
|
registration.pushManager
|
|
.subscribe(options)
|
|
.then(subscription => {
|
|
LNbits.api
|
|
.request(
|
|
'POST',
|
|
'/api/v1/webpush',
|
|
this.g.user.wallets[0].adminkey,
|
|
{
|
|
subscription: JSON.stringify(subscription)
|
|
}
|
|
)
|
|
.then(response => {
|
|
this.saveUserSubscribed(response.data.user)
|
|
this.isSubscribed = true
|
|
})
|
|
.catch(LNbits.utils.notifyApiError)
|
|
})
|
|
}
|
|
})
|
|
.catch(console.log)
|
|
})
|
|
})
|
|
},
|
|
unsubscribe() {
|
|
navigator.serviceWorker.ready
|
|
.then(registration => {
|
|
registration.pushManager.getSubscription().then(subscription => {
|
|
if (subscription) {
|
|
LNbits.api
|
|
.request(
|
|
'DELETE',
|
|
'/api/v1/webpush?endpoint=' + btoa(subscription.endpoint),
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(() => {
|
|
this.removeUserSubscribed(this.g.user.id)
|
|
this.isSubscribed = false
|
|
})
|
|
.catch(LNbits.utils.notifyApiError)
|
|
}
|
|
})
|
|
})
|
|
.catch(console.log)
|
|
},
|
|
checkSupported() {
|
|
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
|
|
},
|
|
async updateSubscriptionStatus() {
|
|
await navigator.serviceWorker.ready
|
|
.then(registration => {
|
|
registration.pushManager.getSubscription().then(subscription => {
|
|
this.isSubscribed =
|
|
!!subscription && this.isUserSubscribed(this.g.user.id)
|
|
})
|
|
})
|
|
.catch(console.log)
|
|
}
|
|
},
|
|
created() {
|
|
this.isPermissionDenied = Notification.permission === 'denied'
|
|
|
|
if (this.checkSupported()) {
|
|
this.updateSubscriptionStatus()
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-dynamic-fields', {
|
|
template: '#lnbits-dynamic-fields',
|
|
mixins: [window.windowMixin],
|
|
props: ['options', 'modelValue'],
|
|
data() {
|
|
return {
|
|
formData: null,
|
|
rules: [val => !!val || 'Field is required']
|
|
}
|
|
},
|
|
methods: {
|
|
applyRules(required) {
|
|
return required ? this.rules : []
|
|
},
|
|
buildData(options, data = {}) {
|
|
return options.reduce((d, option) => {
|
|
if (option.options?.length) {
|
|
d[option.name] = this.buildData(option.options, data[option.name])
|
|
} else {
|
|
d[option.name] = data[option.name] ?? option.default
|
|
}
|
|
return d
|
|
}, {})
|
|
},
|
|
handleValueChanged() {
|
|
this.$emit('update:model-value', this.formData)
|
|
}
|
|
},
|
|
created() {
|
|
this.formData = this.buildData(this.options, this.modelValue)
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-dynamic-chips', {
|
|
template: '#lnbits-dynamic-chips',
|
|
mixins: [window.windowMixin],
|
|
props: ['modelValue'],
|
|
data() {
|
|
return {
|
|
chip: '',
|
|
chips: []
|
|
}
|
|
},
|
|
methods: {
|
|
addChip() {
|
|
if (!this.chip) return
|
|
this.chips.push(this.chip)
|
|
this.chip = ''
|
|
this.$emit('update:model-value', this.chips.join(','))
|
|
},
|
|
removeChip(index) {
|
|
this.chips.splice(index, 1)
|
|
this.$emit('update:model-value', this.chips.join(','))
|
|
}
|
|
},
|
|
created() {
|
|
if (typeof this.modelValue === 'string') {
|
|
this.chips = this.modelValue.split(',')
|
|
} else {
|
|
this.chips = [...this.modelValue]
|
|
}
|
|
}
|
|
})
|
|
|
|
window.app.component('lnbits-update-balance', {
|
|
template: '#lnbits-update-balance',
|
|
mixins: [window.windowMixin],
|
|
props: ['wallet_id', 'callback'],
|
|
computed: {
|
|
denomination() {
|
|
return LNBITS_DENOMINATION
|
|
},
|
|
admin() {
|
|
return user.super_user
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
credit: 0
|
|
}
|
|
},
|
|
methods: {
|
|
updateBalance(credit) {
|
|
LNbits.api
|
|
.updateBalance(credit, this.wallet_id)
|
|
.then(res => {
|
|
if (res.data.status !== 'Success') {
|
|
throw new Error(res.data)
|
|
}
|
|
this.callback({
|
|
success: true,
|
|
credit: parseInt(credit),
|
|
wallet_id: this.wallet_id
|
|
})
|
|
})
|
|
.then(_ => {
|
|
credit = parseInt(credit)
|
|
Quasar.Notify.create({
|
|
type: 'positive',
|
|
message: this.$t('wallet_topup_ok', {
|
|
amount: credit
|
|
}),
|
|
icon: null
|
|
})
|
|
return credit
|
|
})
|
|
.catch(LNbits.utils.notifyApiError)
|
|
}
|
|
}
|
|
})
|