52 lines
1.7 KiB
Vue
52 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|||
|
|
import { onMounted, ref } from 'vue';
|
||
|
|
import QRCode from 'qrcode';
|
||
|
|
import { connectNip46ViaQr } from '../lib/signer';
|
||
|
|
|
||
|
|
const emit = defineEmits<{
|
||
|
|
connected: [pubkey: string];
|
||
|
|
close: [];
|
||
|
|
}>();
|
||
|
|
|
||
|
|
const qrDataUrl = ref<string | null>(null);
|
||
|
|
const connecting = ref(true);
|
||
|
|
const error = ref<string | null>(null);
|
||
|
|
|
||
|
|
async function start(): Promise<void> {
|
||
|
|
connecting.value = true;
|
||
|
|
error.value = null;
|
||
|
|
qrDataUrl.value = null;
|
||
|
|
try {
|
||
|
|
const pubkey = await connectNip46ViaQr(async (uri) => {
|
||
|
|
qrDataUrl.value = await QRCode.toDataURL(uri, { margin: 1, width: 320 });
|
||
|
|
});
|
||
|
|
emit('connected', pubkey);
|
||
|
|
} catch (err) {
|
||
|
|
error.value = (err as Error).message;
|
||
|
|
} finally {
|
||
|
|
connecting.value = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(start);
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4">
|
||
|
|
<div class="card w-full max-w-sm space-y-4 text-center">
|
||
|
|
<h2 class="text-lg font-semibold text-white">Connect a remote signer</h2>
|
||
|
|
<p class="text-sm text-white/60">Scan this with Primal (or any NIP-46-compatible signer app) to sign in without a browser extension.</p>
|
||
|
|
|
||
|
|
<img v-if="qrDataUrl" :src="qrDataUrl" alt="Nostr Connect QR code" class="mx-auto rounded-lg" />
|
||
|
|
|
||
|
|
<p v-if="connecting && !error" class="text-xs text-white/50">Waiting for approval…</p>
|
||
|
|
<p v-if="error" class="text-sm text-red-400">{{ error }}</p>
|
||
|
|
|
||
|
|
<div class="flex gap-2">
|
||
|
|
<button type="button" class="btn-secondary flex-1" @click="emit('close')">Cancel</button>
|
||
|
|
<button v-if="error" type="button" class="btn-primary flex-1" @click="start">Retry</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|