|
1 | 1 | <script lang="ts">
|
2 |
| - import { goto } from "$app/navigation"; |
3 |
| - import { page } from "$app/state"; |
4 |
| - import { PUBLIC_PROVISIONER_URL } from "$env/static/public"; |
5 |
| - import AppNav from "$lib/fragments/AppNav/AppNav.svelte"; |
6 |
| - import type { GlobalState } from "$lib/global"; |
7 |
| - import { Drawer } from "$lib/ui"; |
8 |
| - import * as Button from "$lib/ui/Button"; |
9 |
| - import { QrCodeIcon } from "@hugeicons/core-free-icons"; |
10 |
| - import { HugeiconsIcon } from "@hugeicons/svelte"; |
11 |
| - import { |
12 |
| - Format, |
13 |
| - type PermissionState, |
14 |
| - type Scanned, |
15 |
| - cancel, |
16 |
| - checkPermissions, |
17 |
| - requestPermissions, |
18 |
| - scan, |
19 |
| - } from "@tauri-apps/plugin-barcode-scanner"; |
20 |
| - import axios from "axios"; |
21 |
| - import { getContext, onDestroy, onMount } from "svelte"; |
22 |
| - import type { SVGAttributes } from "svelte/elements"; |
23 |
| -
|
24 |
| - const globalState = getContext<() => GlobalState>("globalState")(); |
25 |
| - const pathProps: SVGAttributes<SVGPathElement> = { |
26 |
| - stroke: "white", |
27 |
| - "stroke-width": 7, |
28 |
| - "stroke-linecap": "round", |
29 |
| - "stroke-linejoin": "round", |
30 |
| - }; |
31 |
| -
|
32 |
| - let platform = $state(); |
33 |
| - let hostname = $state(); |
34 |
| - let session = $state(); |
35 |
| - let codeScannedDrawerOpen = $state(false); |
36 |
| - let loggedInDrawerOpen = $state(false); |
37 |
| - let scannedData: Scanned | undefined = $state(undefined); |
38 |
| - let scanning = false; |
39 |
| - let loading = false; |
40 |
| - let redirect = $state<string | null>(); |
41 |
| - let permissions_nullable: PermissionState | null; |
42 |
| -
|
43 |
| - async function startScan() { |
44 |
| - let permissions = await checkPermissions() |
45 |
| - .then((permissions) => { |
46 |
| - return permissions; |
47 |
| - }) |
48 |
| - .catch(() => { |
49 |
| - return null; |
50 |
| - }); |
51 |
| -
|
52 |
| - if (permissions === "prompt") { |
53 |
| - permissions = await requestPermissions(); |
54 |
| - } |
55 |
| -
|
56 |
| - permissions_nullable = permissions; |
57 |
| -
|
58 |
| - if (permissions === "granted") { |
59 |
| - const formats = [Format.QRCode]; |
60 |
| - const windowed = true; |
61 |
| - if (scanning) return; |
62 |
| - scanning = true; |
63 |
| - scan({ formats, windowed }) |
64 |
| - .then((res) => { |
65 |
| - scannedData = res; |
66 |
| - const url = new URL(res.content); |
67 |
| - platform = url.searchParams.get("platform"); |
68 |
| - const redirectUrl = new URL( |
69 |
| - url.searchParams.get("redirect") || "", |
70 |
| - ); |
71 |
| - redirect = url.searchParams.get("redirect"); |
72 |
| - session = url.searchParams.get("session"); |
73 |
| - hostname = redirectUrl.hostname; |
74 |
| - codeScannedDrawerOpen = true; |
75 |
| - }) |
76 |
| - .catch((error) => { |
77 |
| - console.error("Scan error:", error); |
78 |
| - }) |
79 |
| - .finally(() => { |
80 |
| - scanning = false; |
81 |
| - }); |
82 |
| - } |
83 |
| - } |
84 |
| -
|
85 |
| - async function handleAuth() { |
86 |
| - const vault = await globalState.vaultController.vault; |
87 |
| - if (!vault || !redirect) return; |
88 |
| - await axios.post(redirect, { ename: vault.ename, session }); |
89 |
| - codeScannedDrawerOpen = false; |
90 |
| - loggedInDrawerOpen = true; |
91 |
| - startScan(); |
| 2 | +import { goto } from "$app/navigation"; |
| 3 | +import { page } from "$app/state"; |
| 4 | +import { PUBLIC_PROVISIONER_URL } from "$env/static/public"; |
| 5 | +import AppNav from "$lib/fragments/AppNav/AppNav.svelte"; |
| 6 | +import type { GlobalState } from "$lib/global"; |
| 7 | +import { Drawer } from "$lib/ui"; |
| 8 | +import * as Button from "$lib/ui/Button"; |
| 9 | +import { QrCodeIcon } from "@hugeicons/core-free-icons"; |
| 10 | +import { HugeiconsIcon } from "@hugeicons/svelte"; |
| 11 | +import { |
| 12 | + Format, |
| 13 | + type PermissionState, |
| 14 | + type Scanned, |
| 15 | + cancel, |
| 16 | + checkPermissions, |
| 17 | + requestPermissions, |
| 18 | + scan, |
| 19 | +} from "@tauri-apps/plugin-barcode-scanner"; |
| 20 | +import axios from "axios"; |
| 21 | +import { getContext, onDestroy, onMount } from "svelte"; |
| 22 | +import type { SVGAttributes } from "svelte/elements"; |
| 23 | +
|
| 24 | +const globalState = getContext<() => GlobalState>("globalState")(); |
| 25 | +const pathProps: SVGAttributes<SVGPathElement> = { |
| 26 | + stroke: "white", |
| 27 | + "stroke-width": 7, |
| 28 | + "stroke-linecap": "round", |
| 29 | + "stroke-linejoin": "round", |
| 30 | +}; |
| 31 | +
|
| 32 | +let platform = $state(); |
| 33 | +let hostname = $state(); |
| 34 | +let session = $state(); |
| 35 | +let codeScannedDrawerOpen = $state(false); |
| 36 | +let loggedInDrawerOpen = $state(false); |
| 37 | +let scannedData: Scanned | undefined = $state(undefined); |
| 38 | +let scanning = false; |
| 39 | +let loading = false; |
| 40 | +let redirect = $state<string | null>(); |
| 41 | +let permissions_nullable: PermissionState | null; |
| 42 | +
|
| 43 | +async function startScan() { |
| 44 | + let permissions = await checkPermissions() |
| 45 | + .then((permissions) => { |
| 46 | + return permissions; |
| 47 | + }) |
| 48 | + .catch(() => { |
| 49 | + return null; |
| 50 | + }); |
| 51 | +
|
| 52 | + if (permissions === "prompt") { |
| 53 | + permissions = await requestPermissions(); |
92 | 54 | }
|
93 | 55 |
|
94 |
| - async function cancelScan() { |
95 |
| - await cancel(); |
96 |
| - scanning = false; |
97 |
| - } |
98 |
| -
|
99 |
| - onMount(async () => { |
100 |
| - const [_empty, ...rest] = page.url.search.split("?"); |
101 |
| - const methodAndParam = rest.join("?"); |
102 |
| - const [method, ...param] = methodAndParam.split("?"); |
103 |
| - const data = param.join("?"); |
104 |
| - const deeplinkMethodSpecifiers = ["auth"]; |
105 |
| - if (method && !deeplinkMethodSpecifiers.includes(method)) { |
106 |
| - console.error("Unknown method specifier"); |
107 |
| - } |
108 |
| - switch (method) { |
109 |
| - case "auth": { |
110 |
| - const params = new URLSearchParams(data); |
111 |
| - platform = params.get("platform"); |
112 |
| - session = params.get("session"); |
113 |
| - redirect = params.get("redirect"); |
114 |
| - if (!redirect || !platform || !session) { |
115 |
| - console.error("Bad deeplink!"); |
116 |
| - break; |
117 |
| - } |
118 |
| - hostname = new URL(redirect as string).hostname; |
| 56 | + permissions_nullable = permissions; |
| 57 | +
|
| 58 | + if (permissions === "granted") { |
| 59 | + const formats = [Format.QRCode]; |
| 60 | + const windowed = true; |
| 61 | + if (scanning) return; |
| 62 | + scanning = true; |
| 63 | + scan({ formats, windowed }) |
| 64 | + .then((res) => { |
| 65 | + scannedData = res; |
| 66 | + const url = new URL(res.content); |
| 67 | + platform = url.searchParams.get("platform"); |
| 68 | + const redirectUrl = new URL( |
| 69 | + url.searchParams.get("redirect") || "", |
| 70 | + ); |
| 71 | + redirect = url.searchParams.get("redirect"); |
| 72 | + session = url.searchParams.get("session"); |
| 73 | + hostname = redirectUrl.hostname; |
119 | 74 | codeScannedDrawerOpen = true;
|
| 75 | + }) |
| 76 | + .catch((error) => { |
| 77 | + console.error("Scan error:", error); |
| 78 | + }) |
| 79 | + .finally(() => { |
120 | 80 | scanning = false;
|
| 81 | + }); |
| 82 | + } |
| 83 | +} |
| 84 | +
|
| 85 | +async function handleAuth() { |
| 86 | + const vault = await globalState.vaultController.vault; |
| 87 | + if (!vault || !redirect) return; |
| 88 | + await axios.post(redirect, { ename: vault.ename, session }); |
| 89 | + codeScannedDrawerOpen = false; |
| 90 | + loggedInDrawerOpen = true; |
| 91 | + startScan(); |
| 92 | +} |
| 93 | +
|
| 94 | +async function cancelScan() { |
| 95 | + await cancel(); |
| 96 | + scanning = false; |
| 97 | +} |
| 98 | +
|
| 99 | +onMount(async () => { |
| 100 | + const [_empty, ...rest] = page.url.search.split("?"); |
| 101 | + const methodAndParam = rest.join("?"); |
| 102 | + const [method, ...param] = methodAndParam.split("?"); |
| 103 | + const data = param.join("?"); |
| 104 | + const deeplinkMethodSpecifiers = ["auth"]; |
| 105 | + if (method && !deeplinkMethodSpecifiers.includes(method)) { |
| 106 | + console.error("Unknown method specifier"); |
| 107 | + } |
| 108 | + switch (method) { |
| 109 | + case "auth": { |
| 110 | + const params = new URLSearchParams(data); |
| 111 | + platform = params.get("platform"); |
| 112 | + session = params.get("session"); |
| 113 | + redirect = params.get("redirect"); |
| 114 | + if (!redirect || !platform || !session) { |
| 115 | + console.error("Bad deeplink!"); |
121 | 116 | break;
|
122 | 117 | }
|
| 118 | + hostname = new URL(redirect as string).hostname; |
| 119 | + codeScannedDrawerOpen = true; |
| 120 | + scanning = false; |
| 121 | + break; |
123 | 122 | }
|
124 |
| - startScan(); |
125 |
| - }); |
| 123 | + } |
| 124 | + startScan(); |
| 125 | +}); |
126 | 126 |
|
127 |
| - onDestroy(async () => { |
128 |
| - await cancelScan(); |
129 |
| - }); |
| 127 | +onDestroy(async () => { |
| 128 | + await cancelScan(); |
| 129 | +}); |
130 | 130 | </script>
|
131 | 131 |
|
132 | 132 | <AppNav title="Scan QR Code" titleClasses="text-white" iconColor="white" />
|
|
0 commit comments