Add QR code scanning functionality with new QRScanner component
- Introduced a new QRScanner component to facilitate QR code scanning within the application. - Integrated QR code scanning capabilities into the SendDialog.vue, allowing users to scan QR codes for payment destinations. - Updated package.json and package-lock.json to include the qr-scanner library for QR code processing. - Enhanced user experience by providing visual feedback and error handling during the scanning process. These changes improve the payment workflow by enabling users to easily scan QR codes for transactions. Enhance QR code interaction in ReceiveDialog.vue - Updated the QR code display to include a clickable area that allows users to copy the invoice directly to the clipboard. - Added a descriptive message below the QR code to inform users about the copy functionality, improving usability and accessibility. These changes enhance the user experience by making it easier to interact with the QR code for invoice management. Fix QR scanner loading state condition and remove unused video element reference - Updated the loading state condition in qr-scanner.vue to check for camera permission correctly. - Removed the unused videoElement reference in useQRScanner.ts to clean up the code. These changes improve the functionality and clarity of the QR scanner component.
This commit is contained in:
parent
ef818baed6
commit
a9c07f6af3
6 changed files with 311 additions and 10 deletions
|
|
@ -286,12 +286,17 @@ function formatExpiry(seconds: number): string {
|
|||
<div v-if="isLoadingQR" class="w-48 h-48 sm:w-64 sm:h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<Loader2 class="h-6 w-6 sm:h-8 sm:w-8 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
<div v-else-if="qrCode" class="bg-white p-2 sm:p-4 rounded-lg">
|
||||
<img
|
||||
:src="qrCode"
|
||||
alt="Lightning Invoice QR Code"
|
||||
class="w-48 h-48 sm:w-64 sm:h-64"
|
||||
/>
|
||||
<div v-else-if="qrCode" class="text-center">
|
||||
<div class="bg-white p-2 sm:p-4 rounded-lg cursor-pointer hover:bg-gray-50 transition-colors" @click="copyToClipboard(createdInvoice.payment_request || createdInvoice.bolt11, 'qr')">
|
||||
<img
|
||||
:src="qrCode"
|
||||
alt="Lightning Invoice QR Code"
|
||||
class="w-48 h-48 sm:w-64 sm:h-64"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground mt-2">
|
||||
Click QR code to copy invoice
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="w-48 h-48 sm:w-64 sm:h-64 flex items-center justify-center bg-muted rounded-lg">
|
||||
<QrCode class="h-8 w-8 sm:h-12 sm:w-12 text-muted-foreground opacity-50" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
|
@ -8,8 +8,9 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
|
|||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { Send, AlertCircle, Loader2 } from 'lucide-vue-next'
|
||||
import { Send, AlertCircle, Loader2, ScanLine } from 'lucide-vue-next'
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
|
||||
import QRScanner from '@/components/ui/qr-scanner.vue'
|
||||
|
||||
interface Props {
|
||||
open: boolean
|
||||
|
|
@ -43,11 +44,12 @@ const form = useForm({
|
|||
}
|
||||
})
|
||||
|
||||
const { resetForm, values, meta } = form
|
||||
const { resetForm, values, meta, setFieldValue } = form
|
||||
const isFormValid = computed(() => meta.value.valid)
|
||||
|
||||
// State
|
||||
const isSending = computed(() => walletService?.isSendingPayment?.value || false)
|
||||
const showScanner = ref(false)
|
||||
const error = computed(() => walletService?.error?.value)
|
||||
|
||||
// Methods
|
||||
|
|
@ -71,6 +73,23 @@ const onSubmit = form.handleSubmit(async (formValues) => {
|
|||
function closeDialog() {
|
||||
emit('update:open', false)
|
||||
resetForm()
|
||||
showScanner.value = false
|
||||
}
|
||||
|
||||
// QR Scanner functions
|
||||
function openScanner() {
|
||||
showScanner.value = true
|
||||
}
|
||||
|
||||
function closeScanner() {
|
||||
showScanner.value = false
|
||||
}
|
||||
|
||||
function handleScanResult(result: string) {
|
||||
// Set the scanned result in the destination field
|
||||
setFieldValue('destination', result)
|
||||
closeScanner()
|
||||
toastService?.success('QR code scanned successfully!')
|
||||
}
|
||||
|
||||
// Determine destination type helper text
|
||||
|
|
@ -103,7 +122,19 @@ const destinationType = computed(() => {
|
|||
<form @submit="onSubmit" class="space-y-4">
|
||||
<FormField v-slot="{ componentField }" name="destination">
|
||||
<FormItem>
|
||||
<FormLabel>Destination *</FormLabel>
|
||||
<div class="flex items-center justify-between">
|
||||
<FormLabel>Destination *</FormLabel>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@click="openScanner"
|
||||
class="h-7 px-2 text-xs"
|
||||
>
|
||||
<ScanLine class="w-3 h-3 mr-1" />
|
||||
Scan QR
|
||||
</Button>
|
||||
</div>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder="Lightning invoice, LNURL, or Lightning address (user@domain.com)"
|
||||
|
|
@ -170,4 +201,24 @@ const destinationType = computed(() => {
|
|||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<!-- QR Scanner Dialog -->
|
||||
<Dialog :open="showScanner" @update:open="showScanner = $event">
|
||||
<DialogContent class="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle class="flex items-center gap-2">
|
||||
<ScanLine class="h-5 w-5" />
|
||||
Scan QR Code
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Point your camera at a Lightning invoice QR code
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<QRScanner
|
||||
@result="handleScanResult"
|
||||
@close="closeScanner"
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue