forked from coracle/flotilla
Bring back blossom server auth, fix duplicate direct messages
This commit is contained in:
@@ -10,11 +10,10 @@
|
|||||||
import {makeEditor} from "@app/editor"
|
import {makeEditor} from "@app/editor"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url?: string
|
|
||||||
onSubmit: (event: EventContent) => void
|
onSubmit: (event: EventContent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const {onSubmit, url}: Props = $props()
|
const {onSubmit}: Props = $props()
|
||||||
|
|
||||||
const autofocus = !isMobile
|
const autofocus = !isMobile
|
||||||
|
|
||||||
@@ -39,11 +38,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const editor = makeEditor({
|
const editor = makeEditor({
|
||||||
url,
|
|
||||||
autofocus,
|
autofocus,
|
||||||
submit,
|
submit,
|
||||||
uploading,
|
uploading,
|
||||||
aggressive: true,
|
aggressive: true,
|
||||||
|
encryptFiles: true,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {ParsedEmojiValue} from "@welshman/content"
|
import type {ParsedEmojiValue} from "@welshman/content"
|
||||||
import {imgproxy} from "@app/core/state"
|
|
||||||
|
|
||||||
export let value: ParsedEmojiValue
|
export let value: ParsedEmojiValue
|
||||||
|
|
||||||
@@ -8,10 +7,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value.url}
|
{#if value.url}
|
||||||
<img
|
<img {alt} src={value.url} class="-mt-0.5 inline h-[1em] min-w-[1em] align-middle" />
|
||||||
{alt}
|
|
||||||
src={imgproxy(value.url, {w: 24, h: 24})}
|
|
||||||
class="-mt-0.5 inline h-[1em] min-w-[1em] align-middle" />
|
|
||||||
{:else}
|
{:else}
|
||||||
{alt}
|
{alt}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {ellipsize, displayUrl, postJson} from "@welshman/lib"
|
import {ellipsize, displayUrl, postJson} from "@welshman/lib"
|
||||||
import {dufflepud, imgproxy} from "@app/core/state"
|
import {dufflepud} from "@app/core/state"
|
||||||
import {preventDefault, stopPropagation} from "@lib/html"
|
import {preventDefault, stopPropagation} from "@lib/html"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
|
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<img
|
<img
|
||||||
alt="Link preview"
|
alt="Link preview"
|
||||||
onerror={onError}
|
onerror={onError}
|
||||||
src={imgproxy(preview.image)}
|
src={preview.image}
|
||||||
class="bg-alt max-h-72 rounded-t-box object-contain object-center" />
|
class="bg-alt max-h-72 rounded-t-box object-contain object-center" />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex flex-col gap-2 p-4">
|
<div class="flex flex-col gap-2 p-4">
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount, onDestroy} from "svelte"
|
import {onMount, onDestroy} from "svelte"
|
||||||
import {displayUrl} from "@welshman/lib"
|
import {displayUrl} from "@welshman/lib"
|
||||||
import {getTags, decryptFile, getTagValue, tagsFromIMeta} from "@welshman/util"
|
import {
|
||||||
|
getTags,
|
||||||
|
getBlob,
|
||||||
|
decryptFile,
|
||||||
|
getTagValue,
|
||||||
|
tagsFromIMeta,
|
||||||
|
makeBlossomAuthEvent,
|
||||||
|
} from "@welshman/util"
|
||||||
|
import {signer} from "@welshman/app"
|
||||||
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import {imgproxy} from "@app/core/state"
|
|
||||||
|
|
||||||
const {value, event, ...props} = $props()
|
const {value, event, ...props} = $props()
|
||||||
|
|
||||||
@@ -14,18 +21,34 @@
|
|||||||
.map(tagsFromIMeta)
|
.map(tagsFromIMeta)
|
||||||
.find(meta => getTagValue("url", meta) === url) || event.tags
|
.find(meta => getTagValue("url", meta) === url) || event.tags
|
||||||
|
|
||||||
|
const hash = getTagValue("x", meta)
|
||||||
const key = getTagValue("decryption-key", meta)
|
const key = getTagValue("decryption-key", meta)
|
||||||
const nonce = getTagValue("decryption-nonce", meta)
|
const nonce = getTagValue("decryption-nonce", meta)
|
||||||
const algorithm = getTagValue("encryption-algorithm", meta)
|
const algorithm = getTagValue("encryption-algorithm", meta)
|
||||||
|
|
||||||
const onError = () => {
|
const onError = async () => {
|
||||||
hasError = true
|
// If the image failed to load, try authenticating
|
||||||
|
if (hash && $signer) {
|
||||||
|
const server = new URL(url).origin
|
||||||
|
const template = makeBlossomAuthEvent({action: "get", server, hashes: [hash]})
|
||||||
|
const authEvent = await $signer.sign(template)
|
||||||
|
const res = await getBlob(server, hash, {authEvent})
|
||||||
|
|
||||||
|
if (res.status === 200) {
|
||||||
|
src = URL.createObjectURL(await res.blob())
|
||||||
|
} else {
|
||||||
|
hasError = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasError = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let hasError = $state(false)
|
let hasError = $state(false)
|
||||||
let src = $state(imgproxy(url))
|
let src = $state("")
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
// If we have an encryption algorithm, fetch and decrypt
|
||||||
if (algorithm === "aes-gcm" && key && nonce) {
|
if (algorithm === "aes-gcm" && key && nonce) {
|
||||||
const response = await fetch(url)
|
const response = await fetch(url)
|
||||||
|
|
||||||
@@ -35,6 +58,8 @@
|
|||||||
|
|
||||||
src = URL.createObjectURL(new Blob([decryptedData]))
|
src = URL.createObjectURL(new Blob([decryptedData]))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
src = url
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -48,6 +73,6 @@
|
|||||||
<Icon icon={LinkRound} size={3} class="inline-block" />
|
<Icon icon={LinkRound} size={3} class="inline-block" />
|
||||||
{displayUrl(url)}
|
{displayUrl(url)}
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else if src}
|
||||||
<img alt="" {src} onerror={onError} {...props} />
|
<img alt="" {src} onerror={onError} {...props} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
+5
-16
@@ -148,8 +148,6 @@ export const DEFAULT_PUBKEYS = import.meta.env.VITE_DEFAULT_PUBKEYS
|
|||||||
|
|
||||||
export const DUFFLEPUD_URL = "https://dufflepud.onrender.com"
|
export const DUFFLEPUD_URL = "https://dufflepud.onrender.com"
|
||||||
|
|
||||||
export const IMGPROXY_URL = "https://imgproxy.coracle.social"
|
|
||||||
|
|
||||||
export const NIP46_PERMS =
|
export const NIP46_PERMS =
|
||||||
"nip44_encrypt,nip44_decrypt," +
|
"nip44_encrypt,nip44_decrypt," +
|
||||||
[CLIENT_AUTH, AUTH_JOIN, MESSAGE, THREAD, COMMENT, ROOMS, WRAP, REACTION, ZAP_REQUEST]
|
[CLIENT_AUTH, AUTH_JOIN, MESSAGE, THREAD, COMMENT, ROOMS, WRAP, REACTION, ZAP_REQUEST]
|
||||||
@@ -180,20 +178,6 @@ export const colors = [
|
|||||||
|
|
||||||
export const dufflepud = (path: string) => DUFFLEPUD_URL + "/" + path
|
export const dufflepud = (path: string) => DUFFLEPUD_URL + "/" + path
|
||||||
|
|
||||||
export const imgproxy = (url: string, {w = 640, h = 1024} = {}) => {
|
|
||||||
if (!url || url.match("gif$")) {
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
url = url.split("?")[0]
|
|
||||||
|
|
||||||
try {
|
|
||||||
return url ? `${IMGPROXY_URL}/x/s:${w}:${h}/${btoa(url)}` : url
|
|
||||||
} catch (e) {
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const entityLink = (entity: string) => `https://coracle.social/${entity}`
|
export const entityLink = (entity: string) => `https://coracle.social/${entity}`
|
||||||
|
|
||||||
export const pubkeyLink = (pubkey: string, relays = Router.get().FromPubkeys([pubkey]).getUrls()) =>
|
export const pubkeyLink = (pubkey: string, relays = Router.get().FromPubkeys([pubkey]).getUrls()) =>
|
||||||
@@ -533,6 +517,11 @@ export const chats = derived(
|
|||||||
const messagesByChatId = new Map<string, TrustedEvent[]>()
|
const messagesByChatId = new Map<string, TrustedEvent[]>()
|
||||||
|
|
||||||
for (const message of $messages) {
|
for (const message of $messages) {
|
||||||
|
// Filter out messages we sent but aren't addressed to the user
|
||||||
|
if (!getPubkeyTagValues(message.wrap?.tags || []).includes($pubkey!)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const chatId = makeChatId(getPubkeyTagValues(message.tags).concat(message.pubkey))
|
const chatId = makeChatId(getPubkeyTagValues(message.tags).concat(message.pubkey))
|
||||||
|
|
||||||
pushToMapKey(messagesByChatId, chatId, message)
|
pushToMapKey(messagesByChatId, chatId, message)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {uploadFile} from "@app/core/commands"
|
|||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
|
|
||||||
export const makeEditor = async ({
|
export const makeEditor = async ({
|
||||||
|
encryptFiles = false,
|
||||||
aggressive = false,
|
aggressive = false,
|
||||||
autofocus = false,
|
autofocus = false,
|
||||||
charCount,
|
charCount,
|
||||||
@@ -21,6 +22,7 @@ export const makeEditor = async ({
|
|||||||
uploading,
|
uploading,
|
||||||
wordCount,
|
wordCount,
|
||||||
}: {
|
}: {
|
||||||
|
encryptFiles?: boolean
|
||||||
aggressive?: boolean
|
aggressive?: boolean
|
||||||
autofocus?: boolean
|
autofocus?: boolean
|
||||||
charCount?: Writable<number>
|
charCount?: Writable<number>
|
||||||
@@ -51,7 +53,8 @@ export const makeEditor = async ({
|
|||||||
},
|
},
|
||||||
fileUpload: {
|
fileUpload: {
|
||||||
config: {
|
config: {
|
||||||
upload: (attrs: FileAttributes) => uploadFile(attrs.file, {url, encrypt: true}),
|
upload: (attrs: FileAttributes) =>
|
||||||
|
uploadFile(attrs.file, {url, encrypt: encryptFiles}),
|
||||||
onDrop: () => uploading?.set(true),
|
onDrop: () => uploading?.set(true),
|
||||||
onComplete: () => uploading?.set(false),
|
onComplete: () => uploading?.set(false),
|
||||||
onUploadError(currentEditor, task) {
|
onUploadError(currentEditor, task) {
|
||||||
|
|||||||
Reference in New Issue
Block a user