mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 16:31:04 +00:00
Add support for nostr.build and NIP 98 Auth
This commit is contained in:
parent
969acdd654
commit
581e4df423
@ -209,11 +209,16 @@
|
||||
}
|
||||
|
||||
export const write = text => {
|
||||
contenteditable.getInput().focus()
|
||||
const input = contenteditable.getInput()
|
||||
|
||||
input.focus()
|
||||
|
||||
const selection = window.getSelection()
|
||||
const textNode = document.createTextNode(text)
|
||||
const target = last(input.childNodes) as unknown as Node
|
||||
const offset = target instanceof Text ? target.wholeText.length : target.childNodes.length
|
||||
|
||||
selection.collapse(target, offset)
|
||||
selection.getRangeAt(0).insertNode(textNode)
|
||||
selection.collapse(textNode, text.length)
|
||||
|
||||
|
@ -84,7 +84,9 @@
|
||||
}
|
||||
|
||||
const setWordCount = throttle(300, () => {
|
||||
wordCount = compose.parse().match(/\s+/g)?.length || 0
|
||||
if (compose) {
|
||||
wordCount = compose.parse().match(/\s+/g)?.length || 0
|
||||
}
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
|
@ -173,6 +173,9 @@ export class Builder {
|
||||
|
||||
createLabel = (payload: EventOpts) => buildEvent(1985, payload)
|
||||
|
||||
createNip98AuthHeader = (tags: string[][]) =>
|
||||
`Nostr ${btoa(JSON.stringify(buildEvent(27235, {tags})))}`
|
||||
|
||||
initialize(engine: Engine) {
|
||||
this.engine = engine
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
<script lang="ts">
|
||||
import {identity, pick} from "ramda"
|
||||
import {identity} from "ramda"
|
||||
import {Fetch, filterVals} from "hurdak"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import {listenForFile, stripExifData, blobToFile} from "src/util/html"
|
||||
import {Settings} from "src/app/engine"
|
||||
import {Builder} from "src/app/engine"
|
||||
|
||||
export let icon = null
|
||||
export let value = null
|
||||
@ -15,9 +16,10 @@
|
||||
export let maxHeight = null
|
||||
export let onChange = null
|
||||
|
||||
let input, listener, quote
|
||||
const url = "https://nostr.build/api/v2/upload/files"
|
||||
|
||||
let input, listener, loading
|
||||
let files = []
|
||||
let loading = false
|
||||
let isOpen = false
|
||||
|
||||
$: {
|
||||
@ -26,45 +28,48 @@
|
||||
if (inputFiles) {
|
||||
const opts = filterVals(identity, {maxWidth, maxHeight})
|
||||
|
||||
files = await Promise.all(
|
||||
inputFiles.map(async f => blobToFile(await stripExifData(f, opts)))
|
||||
)
|
||||
loading = true
|
||||
|
||||
quote = await Fetch.postJson(Settings.dufflepud("upload/quote"), {
|
||||
uploads: files.map(pick(["size"])),
|
||||
})
|
||||
try {
|
||||
files = await Promise.all(
|
||||
inputFiles.map(async f => blobToFile(await stripExifData(f, opts)))
|
||||
)
|
||||
|
||||
const body = new FormData()
|
||||
|
||||
for (const file of files) {
|
||||
body.append("file[]", file)
|
||||
}
|
||||
|
||||
const result = await Fetch.fetchJson(url, {
|
||||
body,
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: Builder.createNip98AuthHeader([
|
||||
["u", url],
|
||||
["method", "POST"],
|
||||
]),
|
||||
},
|
||||
})
|
||||
|
||||
// Legacy weirdness
|
||||
for (const {url} of result.data) {
|
||||
value = url
|
||||
onChange?.(url)
|
||||
}
|
||||
} finally {
|
||||
isOpen = false
|
||||
loading = false
|
||||
}
|
||||
} else {
|
||||
files = []
|
||||
quote = null
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const accept = async () => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
quote.uploads.map(async ({id}, idx) => {
|
||||
const {url} = await Fetch.uploadFile(Settings.dufflepud(`upload/${id}`), files[idx])
|
||||
|
||||
value = url
|
||||
onChange?.(url)
|
||||
})
|
||||
)
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
|
||||
files = []
|
||||
quote = null
|
||||
isOpen = false
|
||||
}
|
||||
|
||||
const decline = () => {
|
||||
files = []
|
||||
quote = null
|
||||
isOpen = false
|
||||
}
|
||||
</script>
|
||||
@ -89,24 +94,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if quote}
|
||||
{#if isOpen}
|
||||
<Modal mini onEscape={decline}>
|
||||
<Content>
|
||||
<h1 class="staatliches text-2xl">Confirm File Upload</h1>
|
||||
<p>Please accept the following terms:</p>
|
||||
<p>{quote.terms}</p>
|
||||
<div class="flex gap-2">
|
||||
<Anchor theme="button" on:click={decline} {loading}>Decline</Anchor>
|
||||
<Anchor theme="button-accent" on:click={accept} {loading}>Accept</Anchor>
|
||||
</div>
|
||||
</Content>
|
||||
</Modal>
|
||||
{:else if isOpen}
|
||||
<Modal mini onEscape={decline}>
|
||||
<Content>
|
||||
<h1 class="staatliches text-2xl">Upload a File</h1>
|
||||
<p>Click below to select a file to upload.</p>
|
||||
<input multiple={multi} type="file" bind:this={input} />
|
||||
{#if loading}
|
||||
<Spinner delay={0}>Uploading your media...</Spinner>
|
||||
{:else}
|
||||
<h1 class="staatliches text-2xl">Upload a File</h1>
|
||||
<p>Click below to select a file to upload.</p>
|
||||
<input multiple={multi} type="file" bind:this={input} />
|
||||
{/if}
|
||||
</Content>
|
||||
</Modal>
|
||||
{/if}
|
||||
|
Loading…
Reference in New Issue
Block a user