mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 00:10:52 +00:00
Add support for QR codes
This commit is contained in:
parent
3d06e7e0b9
commit
3bc99e816d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
*.pem
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
BIN
package-lock.json
generated
BIN
package-lock.json
generated
Binary file not shown.
@ -23,7 +23,8 @@
|
||||
"svelte": "^3.52.0",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^3.2.3"
|
||||
"vite": "^3.2.3",
|
||||
"vite-plugin-mkcert": "^1.13.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bugsnag/js": "^7.18.0",
|
||||
@ -39,6 +40,7 @@
|
||||
"localforage-memoryStorageDriver": "^0.9.2",
|
||||
"nostr-tools": "^1.2.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"qr-scanner": "^1.4.2",
|
||||
"qrcode": "^1.5.1",
|
||||
"ramda": "^0.28.0",
|
||||
"svelte-check": "^3.0.3",
|
||||
|
@ -105,7 +105,7 @@ const processRoomEvents = async events => {
|
||||
const content = tryJson(() => pick(roomAttrs, JSON.parse(e.content))) as Record<string, any>
|
||||
const roomId = e.kind === 40 ? e.id : Tags.from(e).type("e").values().first()
|
||||
|
||||
if (!roomId) {
|
||||
if (!roomId || !content) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -151,6 +151,7 @@ const processMessages = async events => {
|
||||
// Routes
|
||||
|
||||
const getWeight = type => {
|
||||
if (type === 'nip05') return 1
|
||||
if (type === 'kind:10001') return 1
|
||||
if (type === 'kind:3') return 0.8
|
||||
if (type === 'kind:2') return 0.5
|
||||
@ -262,13 +263,12 @@ const verifyNip05 = (pubkey, as) =>
|
||||
database.people.patch({...person, verified_as: as})
|
||||
|
||||
if (result.relays?.length > 0) {
|
||||
console.log('===== NIP05 VERIFICATION RELAYS', result.relays)
|
||||
// database.routes.bulkPut(
|
||||
// createMap('id', result.relays.flatMap(url =>[
|
||||
// calculateRoute(pubkey, url, 'nip05', 'write', now()),
|
||||
// calculateRoute(pubkey, url, 'nip05', 'read', now()),
|
||||
// ]))
|
||||
// )
|
||||
database.routes.bulkPut(
|
||||
createMap('id', result.relays.filter(isRelay).flatMap(url =>[
|
||||
calculateRoute(pubkey, url, 'nip05', 'write', now()),
|
||||
calculateRoute(pubkey, url, 'nip05', 'read', now()),
|
||||
]))
|
||||
)
|
||||
}
|
||||
}
|
||||
}, noop)
|
||||
|
@ -2,7 +2,6 @@
|
||||
import {objOf} from 'ramda'
|
||||
import {onMount} from 'svelte'
|
||||
import {nip19} from 'nostr-tools'
|
||||
import {navigate} from 'svelte-routing'
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import NoteDetail from 'src/views/NoteDetail.svelte'
|
||||
import Person from 'src/routes/Person.svelte'
|
||||
@ -16,7 +15,7 @@
|
||||
({type, data} = nip19.decode(entity) as {type: string, data: any})
|
||||
relays = (data.relays || []).map(objOf('url'))
|
||||
} catch (e) {
|
||||
navigate('/')
|
||||
// pass
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@ -33,5 +32,9 @@
|
||||
<Person npub={nip19.npubEncode(data.pubkey)} {relays} activeTab="notes" />
|
||||
{:else if type === "npub"}
|
||||
<Person npub={entity} activeTab="notes" />
|
||||
{:else}
|
||||
<Content size="lg" class="text-center">
|
||||
<div>Sorry, we weren't able to find {entity}.</div>
|
||||
</Content>
|
||||
{/if}
|
||||
|
||||
|
@ -146,7 +146,7 @@
|
||||
{/if}
|
||||
{/if}
|
||||
<Anchor type="button-circle" on:click={share}>
|
||||
<i class="fa fa-qrcode" />
|
||||
<i class="fa fa-share-nodes" />
|
||||
</Anchor>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,26 +1,20 @@
|
||||
<script>
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import {navigate} from 'svelte-routing'
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import Tabs from 'src/partials/Tabs.svelte'
|
||||
import SearchPeople from 'src/views/SearchPeople.svelte'
|
||||
import SearchNotes from 'src/views/SearchNotes.svelte'
|
||||
import Scan from 'src/views/Scan.svelte'
|
||||
|
||||
export let activeTab
|
||||
|
||||
let q = ''
|
||||
|
||||
// const setActiveTab = tab => navigate(`/search/${tab}`)
|
||||
const setActiveTab = tab => navigate(`/search/${tab}`)
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
<!--
|
||||
<Tabs tabs={['people', 'notes']} {activeTab} {setActiveTab} />
|
||||
-->
|
||||
<Input bind:value={q} placeholder="Search for people">
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
<Tabs tabs={['people', 'advanced']} {activeTab} {setActiveTab} />
|
||||
{#if activeTab === 'people'}
|
||||
<SearchPeople {q} />
|
||||
{:else if activeTab === 'notes'}
|
||||
<SearchNotes {q} />
|
||||
<SearchPeople />
|
||||
{:else if activeTab === 'advanced'}
|
||||
<Scan />
|
||||
{/if}
|
||||
</Content>
|
||||
|
@ -28,4 +28,7 @@
|
||||
<Input value={nprofile}>
|
||||
<button slot="after" class="fa fa-copy" on:click={copyKey} />
|
||||
</Input>
|
||||
<div class="text-center text-light">
|
||||
Copy or scan from a nostr app to share this profile.
|
||||
</div>
|
||||
</Content>
|
||||
|
79
src/views/Scan.svelte
Normal file
79
src/views/Scan.svelte
Normal file
@ -0,0 +1,79 @@
|
||||
<script lang="ts">
|
||||
import QrScanner from 'qr-scanner'
|
||||
import {onDestroy} from 'svelte'
|
||||
import {navigate} from 'svelte-routing'
|
||||
import {waitFor} from 'hurdak/lib/hurdak'
|
||||
import Content from 'src/partials/Content.svelte'
|
||||
import Input from 'src/partials/Input.svelte'
|
||||
import Anchor from 'src/partials/Anchor.svelte'
|
||||
import Spinner from 'src/partials/Spinner.svelte'
|
||||
|
||||
let mode = 'input', video, ready, value, scanner
|
||||
|
||||
const onDecode = result => {
|
||||
console.log(result)
|
||||
goToEntity(result.data)
|
||||
}
|
||||
|
||||
const goToEntity = entity => {
|
||||
navigate(`/${entity}`)
|
||||
}
|
||||
|
||||
const setMode = async newMode => {
|
||||
mode = newMode
|
||||
|
||||
if (newMode === 'scan') {
|
||||
await waitFor(() => video)
|
||||
|
||||
scanner = new QrScanner(video, onDecode, {
|
||||
returnDetailedScanResult: true,
|
||||
})
|
||||
|
||||
await scanner.start()
|
||||
|
||||
ready = true
|
||||
} else if (scanner) {
|
||||
ready = false
|
||||
await scanner.stop()
|
||||
await scanner.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(async () => {
|
||||
if (scanner) {
|
||||
await scanner.stop()
|
||||
await scanner.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
{#if mode === 'input'}
|
||||
<div class="flex gap-2">
|
||||
<Input placeholder="nprofile..." bind:value={value} wrapperClass="flex-grow" />
|
||||
<Anchor type="button" on:click={() => goToEntity(value)}>
|
||||
<i class="fa fa-arrow-right" />
|
||||
</Anchor>
|
||||
<Anchor type="button" on:click={() => setMode('scan')}>
|
||||
<i class="fa fa-camera" />
|
||||
</Anchor>
|
||||
</div>
|
||||
<div class="text-center text-light">
|
||||
Enter any nostr identifier (npub, nevent, nprofile or note), or click on the
|
||||
camera icon to scan with your device's camera instead.
|
||||
</div>
|
||||
{:else}
|
||||
{#if !ready}
|
||||
<Spinner>
|
||||
Loading your camera...
|
||||
</Spinner>
|
||||
{/if}
|
||||
<video bind:this={video} />
|
||||
{#if ready}
|
||||
<Anchor type="unstyled" class="flex gap-2 items-center" on:click={() => setMode('input')}>
|
||||
<i class="fa fa-arrow-left" />
|
||||
<span class="underline">Go back</span>
|
||||
</Anchor>
|
||||
{/if}
|
||||
{/if}
|
||||
</Content>
|
@ -1,3 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let q
|
||||
</script>
|
@ -1,11 +1,11 @@
|
||||
<script>
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
||||
import {user} from 'src/agent/helpers'
|
||||
import database from 'src/agent/database'
|
||||
|
||||
export let q
|
||||
|
||||
let q
|
||||
let search
|
||||
|
||||
database.people.iter({'name:!nil': null}).then(people => {
|
||||
@ -13,6 +13,10 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<Input bind:value={q} placeholder="Search for people">
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
|
||||
{#each (search ? search(q) : []).slice(0, 30) as person (person.pubkey)}
|
||||
{#if person.pubkey !== $user.pubkey}
|
||||
<PersonInfo {person} />
|
||||
|
@ -1,10 +1,14 @@
|
||||
import * as path from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import mkcert from 'vite-plugin-mkcert'
|
||||
import sveltePreprocess from 'svelte-preprocess'
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
https: false,
|
||||
},
|
||||
build: {
|
||||
sourcemap: true,
|
||||
},
|
||||
@ -14,6 +18,7 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
mkcert(),
|
||||
nodePolyfills({
|
||||
protocolImports: true,
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user