-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathYiviQRCode.svelte
More file actions
132 lines (118 loc) · 3.49 KB
/
Copy pathYiviQRCode.svelte
File metadata and controls
132 lines (118 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<script lang="ts">
import '@privacybydesign/yivi-css'
import { onMount } from 'svelte'
interface props {
mode?: 'qr' | 'deeplink'
id?: string
responsive?: boolean
}
let {
mode = 'qr',
id = 'crypt-irma-qr',
responsive = false,
}: props = $props()
let qrLoaded = $state(false)
let containerEl: HTMLDivElement
onMount(() => {
let autoClicked = false
const observer = new MutationObserver(() => {
// Check for QR canvas (Yivi renders QR codes as canvas elements)
if (containerEl.querySelector('canvas')) {
qrLoaded = true
observer.disconnect()
return
}
// On mobile, YiviWeb shows a button instead of a QR code.
// Handle based on mode:
if (!autoClicked) {
if (mode === 'deeplink') {
// Deep link mode: auto-click the app button to open Yivi
const buttonLink = containerEl.querySelector<HTMLElement>(
'.yivi-web-button-link'
)
if (buttonLink) {
autoClicked = true
buttonLink.click()
}
} else {
// QR mode: auto-click "show QR" to force QR rendering
const chooseQR = containerEl.querySelector<HTMLElement>(
'[data-yivi-glue-transition="chooseQR"]'
)
if (chooseQR) {
autoClicked = true
chooseQR.click()
}
}
}
})
observer.observe(containerEl, { childList: true, subtree: true })
return () => observer.disconnect()
})
</script>
<div {id} class="yivi-qr-container" class:responsive bind:this={containerEl}>
{#if !qrLoaded}
<svg class="spinner" viewBox="0 0 24 24" width="32" height="32">
<circle
class="spinner-circle"
cx="12"
cy="12"
r="10"
fill="none"
stroke="currentColor"
stroke-width="3"
></circle>
</svg>
{/if}
</div>
<style>
.yivi-qr-container {
width: 330px;
height: 330px;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background: white;
border: 1px solid var(--pg-strong-background);
border-radius: var(--pg-border-radius-sm);
padding: 4px;
}
.yivi-qr-container.responsive {
width: 100%;
max-width: 330px;
aspect-ratio: 1 / 1;
height: auto;
min-height: 200px;
}
.yivi-qr-container.responsive :global(canvas),
.yivi-qr-container.responsive :global(svg) {
width: 100% !important;
height: auto !important;
}
.spinner {
animation: spin 1s linear infinite;
color: var(--pg-text-secondary);
}
.spinner-circle {
stroke-dasharray: 60;
stroke-dashoffset: 0;
animation: dash 1.5s ease-in-out infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dashoffset: 60;
}
50% {
stroke-dashoffset: 15;
}
100% {
stroke-dashoffset: 60;
}
}
</style>