diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index 7c398dd..69c91f4 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -9,6 +9,7 @@ android { apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" dependencies { + implementation project(':capacitor-mlkit-barcode-scanning') implementation project(':capacitor-app') implementation project(':capacitor-browser') implementation project(':capacitor-clipboard') @@ -16,7 +17,6 @@ dependencies { implementation project(':capacitor-haptics') implementation project(':capacitor-share') implementation project(':capacitor-toast') - implementation project(':mutinywallet-barcode-scanner') } diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 13433cf..4d547cd 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -2,6 +2,9 @@ include ':capacitor-android' project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@5.5.1_@capacitor+core@5.5.1/node_modules/@capacitor/android/capacitor') +include ':capacitor-mlkit-barcode-scanning' +project(':capacitor-mlkit-barcode-scanning').projectDir = new File('../node_modules/.pnpm/@capacitor-mlkit+barcode-scanning@5.3.0_@capacitor+core@5.5.1/node_modules/@capacitor-mlkit/barcode-scanning/android') + include ':capacitor-app' project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/app/android') @@ -22,6 +25,3 @@ project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capaci include ':capacitor-toast' project(':capacitor-toast').projectDir = new File('../node_modules/.pnpm/@capacitor+toast@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/toast/android') - -include ':mutinywallet-barcode-scanner' -project(':mutinywallet-barcode-scanner').projectDir = new File('../node_modules/.pnpm/@mutinywallet+barcode-scanner@5.0.0-beta.3_@capacitor+core@5.5.1/node_modules/@mutinywallet/barcode-scanner/android') diff --git a/capacitor.config.ts b/capacitor.config.ts index 5e283e9..ef03c3e 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -2,6 +2,7 @@ import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.mutinywallet.mutinywallet', + backgroundColor: "171717", appName: 'Mutiny Wallet', webDir: 'dist/public', server: { diff --git a/package.json b/package.json index 2e82bd8..7b8c5b7 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "workbox-window": "^6.6.0" }, "dependencies": { + "@capacitor-mlkit/barcode-scanning": "^5.3.0", "@capacitor/android": "^5.5.1", "@capacitor/app": "^5.0.6", "@capacitor/browser": "5.0.6", @@ -54,7 +55,6 @@ "@kobalte/core": "^0.9.8", "@kobalte/tailwindcss": "^0.5.0", "@modular-forms/solid": "^0.18.1", - "@mutinywallet/barcode-scanner": "5.0.0-beta.3", "@mutinywallet/mutiny-wasm": "0.4.28", "@mutinywallet/waila-wasm": "^0.2.4", "@solid-primitives/upload": "^0.0.111", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7c660e..92f6605 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@capacitor-mlkit/barcode-scanning': + specifier: ^5.3.0 + version: 5.3.0(@capacitor/core@5.5.1) '@capacitor/android': specifier: ^5.5.1 version: 5.5.1(@capacitor/core@5.5.1) @@ -44,9 +47,6 @@ importers: '@modular-forms/solid': specifier: ^0.18.1 version: 0.18.1(solid-js@1.8.5) - '@mutinywallet/barcode-scanner': - specifier: 5.0.0-beta.3 - version: 5.0.0-beta.3(@capacitor/core@5.5.1) '@mutinywallet/mutiny-wasm': specifier: 0.4.28 version: 0.4.28 @@ -2526,6 +2526,14 @@ packages: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + /@capacitor-mlkit/barcode-scanning@5.3.0(@capacitor/core@5.5.1): + resolution: {integrity: sha512-ML1nEzcvegeOTu3AxufWYwLmvxkkeKbToyTuMHmpFlIYn69qVdAzwGrN39Kh3+jUwZ4cLy7KTCf27/p6ShT8ag==} + peerDependencies: + '@capacitor/core': ^5.0.0 + dependencies: + '@capacitor/core': 5.5.1 + dev: false + /@capacitor/android@5.5.1(@capacitor/core@5.5.1): resolution: {integrity: sha512-WTnPnpaEvTtaEtTNRbh06Y1afF7A4plY/4uajAL0WW8tdR1FxieadF357yKGiAT6CudI/B+eOu6rxn6qWuphKg==} peerDependencies: @@ -3628,14 +3636,6 @@ packages: solid-js: 1.8.5 dev: false - /@mutinywallet/barcode-scanner@5.0.0-beta.3(@capacitor/core@5.5.1): - resolution: {integrity: sha512-UIR/OibIUoyMI3i691e/G97hr2gOXGZ0PX0WpuPWzuBLDCReKl6Uj+uEnrdrJjdkbN+oeXQ9mWuQrWJ6LSL1hQ==} - peerDependencies: - '@capacitor/core': ^5.0.0 - dependencies: - '@capacitor/core': 5.5.1 - dev: false - /@mutinywallet/mutiny-wasm@0.4.28: resolution: {integrity: sha512-7HD1+dUZv3ra00ugAg7BVg26uAEOwMHVTf59dx5PtUnpKb7lljjP0wSnhg3Oh2+336Tp7gvk5KVzt9xUY9QYIg==} dev: false diff --git a/src/components/Reader.tsx b/src/components/Reader.tsx index 8238195..1ded4ee 100644 --- a/src/components/Reader.tsx +++ b/src/components/Reader.tsx @@ -1,10 +1,10 @@ -import { Capacitor } from "@capacitor/core"; import { BarcodeFormat, + BarcodeScannedEvent, BarcodeScanner, - PermissionStates, - ScanResult -} from "@mutinywallet/barcode-scanner"; + PermissionStatus +} from "@capacitor-mlkit/barcode-scanning"; +import { Capacitor } from "@capacitor/core"; import QrScanner from "qr-scanner"; import { onCleanup, onMount } from "solid-js"; @@ -18,26 +18,34 @@ export function Scanner(props: { onResult: (result: string) => void }) { const startScan = async () => { // Check camera permission - const permissions: PermissionStates = + const permissions: PermissionStatus = await BarcodeScanner.checkPermissions(); if (permissions.camera === "granted") { - const callback = (result: ScanResult, err?: unknown) => { - if (err) { - console.error(err); - return; + await BarcodeScanner.startScan({ formats: [BarcodeFormat.QrCode] }); + + // The camera gets mounted behind everything so we need to make the background transparent + document.querySelector("html")?.classList.add("bg-transparent"); + + const listener = await BarcodeScanner.addListener( + "barcodeScanned", + // eslint-disable-next-line + async (result: BarcodeScannedEvent) => { + document + .querySelector("html") + ?.classList.remove("bg-transparent"); + + await BarcodeScanner.stopScan(); + await listener.remove(); + + // if the result has content + if (result && result.barcode) { + handleResult({ data: result.barcode.rawValue }); // pass the raw scanned content + } } - // if the result has content - if (result && result.content) { - handleResult({ data: result.content }); // pass the raw scanned content - } - }; - await BarcodeScanner.start( - { formats: [BarcodeFormat.QR_CODE] }, - callback ); } else if (permissions.camera === "prompt") { // Request permission if it has not been asked before - const requestedPermissions: PermissionStates = + const requestedPermissions: PermissionStatus = await BarcodeScanner.requestPermissions(); if (requestedPermissions.camera === "granted") { // If user grants permission, start the scan @@ -50,8 +58,11 @@ export function Scanner(props: { onResult: (result: string) => void }) { } }; - const stopScan = () => { - BarcodeScanner.stop(); + const stopScan = async () => { + // Restore the background first to minimize flicker + document.querySelector("html")?.classList.remove("bg-transparent"); + await BarcodeScanner.stopScan(); + await BarcodeScanner.removeAllListeners(); }; onMount(async () => { @@ -67,9 +78,9 @@ export function Scanner(props: { onResult: (result: string) => void }) { } }); - onCleanup(() => { + onCleanup(async () => { if (Capacitor.isNativePlatform()) { - stopScan(); + await stopScan(); } else { scanner?.destroy(); } diff --git a/src/components/layout/Button.tsx b/src/components/layout/Button.tsx index fbd076e..1a99724 100644 --- a/src/components/layout/Button.tsx +++ b/src/components/layout/Button.tsx @@ -35,7 +35,7 @@ export const Button: ParentComponent = (props) => { class="rounded-xl p-3 font-semibold transition disabled:bg-neutral-400/10 disabled:text-white/20 disabled:shadow-inner-button-disabled" classList={{ "bg-white text-black": local.intent === "active", - "bg-transparent text-white": + "bg-neutral-900 text-white": !local.intent || local.intent === "inactive", "border border-white hover:text-[#3B6CCC]": !local.intent || !!local.intent.match(/(active|inactive)/), diff --git a/src/root.css b/src/root.css index 41966a3..4b30ea3 100644 --- a/src/root.css +++ b/src/root.css @@ -4,14 +4,19 @@ body { @apply text-white; - overscroll-behavior-y: none; - min-height: 100.3%; + @apply min-h-[100dvh] overflow-y-scroll overscroll-y-none safe-top safe-bottom disable-scrollbars; } html { + /* Fixed stops it from stretchy overscrolling (more app-like) */ + @apply fixed inset-0 h-[100dvh] overflow-y-scroll overscroll-y-none disable-scrollbars; @apply bg-neutral-900; } +@media (prefers-color-scheme: light) { + /* we don't support this but I want the browser to know I care */ +} + #mutiny-logo { image-rendering: pixelated; } diff --git a/vite.config.ts b/vite.config.ts index a939b96..f7d45e4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -45,7 +45,7 @@ export default defineConfig({ "@solid-primitives/upload", "i18next", "i18next-browser-languagedetector", - "@mutinywallet/barcode-scanner", + "@capacitor-mlkit/barcode-scanner", "@nostr-dev-kit/ndk", "@capacitor/clipboard", "@capacitor/core",