Add image uploads to new post

This commit is contained in:
Jonathan Staab 2023-03-01 16:49:24 -06:00
parent f97d9f2171
commit 2f0317e8aa
13 changed files with 102 additions and 61 deletions

View File

@ -1,7 +1,7 @@
# Current
- [ ] Strip zero width spaces from compose
- [ ] Fix iOS
- [ ] Fix iOS/safari/firefox
- [ ] Make the note relays button modal make sense, one relay with no explanation is not good
# Image uploads
@ -28,6 +28,7 @@
# More
- [ ] Mute threads http://localhost:5173/nevent1qqsyz8x6r0cu7l6vwlcjhf8qhxyjtdykvuervkc3t3mfggse4qtwt0gpyfmhxue69uhkummnw3ezumrfvfjhyarpwdc8y6tddaexg6t4d5hxxmmdnhxvea
- [ ] Add webtorrent support
- https://coracle.social/nevent1qqsxgxcsq5vevy4wdty5z5v88nhwp2fc5qgl0ws5rmamn6z72hwv3qcpyfmhxue69uhkummnw3ez6an9wf5kv6t9vsh8wetvd3hhyer9wghxuet5qk6c9q
- [ ] Add coracle relay

View File

@ -3,72 +3,106 @@ import {get} from 'svelte/store'
import {error} from 'src/util/logger'
import {synced} from 'src/util/misc'
const method = synced('agent/keys/method')
const pubkey = synced('agent/keys/pubkey')
const privkey = synced('agent/keys/privkey')
const getExtension = () => (window as {nostr?: any}).nostr
const canSign = () => Boolean(getExtension() || get(privkey))
const canSign = () => ['privkey', 'extension'].includes(get(method))
const setPrivateKey = _privkey => {
privkey.set(_privkey)
pubkey.set(getPublicKey(_privkey))
}
// For backwards compatibility, if method isn't set but we're logged in, set it
setTimeout(() => {
method.update($method => {
if ($method) {
return $method
}
const setPublicKey = _pubkey => {
pubkey.set(_pubkey)
if (get(privkey)) {
return 'privkey'
}
if (get(pubkey)) {
return getExtension() ? 'extension' : 'pubkey'
}
return null
})
}, 100)
const login = ($method, key) => {
method.set($method)
if ($method === 'privkey') {
privkey.set(key)
pubkey.set(getPublicKey(key))
} else {
privkey.set(null)
pubkey.set(key)
}
}
const clear = () => {
method.set(null)
pubkey.set(null)
privkey.set(null)
}
const sign = async event => {
const ext = getExtension()
const key = get(privkey)
const sign = event => {
const $method = get(method)
event.pubkey = get(pubkey)
event.id = getEventHash(event)
if (key) {
if ($method === 'privkey') {
return Object.assign(event, {
sig: signEvent(event, get(privkey)),
})
} else if (ext) {
return await ext.signEvent(event)
} else {
throw new Error('Unable to sign event')
}
if ($method === 'extension') {
return getExtension().signEvent(event)
}
throw new Error(`Unable to sign event, method is ${$method}`)
}
const getCrypt = () => {
const $privkey = get(privkey)
const nostr = getExtension()
const $method = get(method)
if (!$privkey && !nostr) {
throw new Error('No encryption method available.')
if ($method === 'privkey') {
const $privkey = get(privkey)
return {
encrypt: (pubkey, message) => nip04.encrypt($privkey, pubkey, message),
decrypt: async (pubkey, message) => {
try {
return nip04.decrypt($privkey, pubkey, message)
} catch (e) {
error(e)
return `<Failed to decrypt message: ${e}>`
}
},
}
}
return {
encrypt: (pubkey, message) => {
return $privkey
? nip04.encrypt($privkey, pubkey, message)
: nostr.nip04.encrypt(pubkey, message)
},
decrypt: async (pubkey, message) => {
try {
return $privkey
? nip04.decrypt($privkey, pubkey, message)
: await nostr.nip04.decrypt(pubkey, message)
} catch (e) {
error(e)
if ($method === 'extension') {
return {
encrypt: (pubkey, message) => getExtension().nip04.encrypt(pubkey, message),
decrypt: async (pubkey, message) => {
try {
return await getExtension().nip04.decrypt(pubkey, message)
} catch (e) {
error(e)
return `<Failed to decrypt message: ${e}>`
}
},
return `<Failed to decrypt message: ${e}>`
}
},
}
}
throw new Error('No encryption method available.')
}
export default {
pubkey, privkey, canSign, setPrivateKey, setPublicKey, clear,
sign, getCrypt,
pubkey, privkey, canSign, login, clear, sign, getCrypt,
}

View File

@ -21,18 +21,14 @@ export const loadAppData = async pubkey => {
}
}
export const login = ({privkey, pubkey}: {privkey?: string, pubkey?: string}) => {
if (privkey) {
keys.setPrivateKey(privkey)
} else {
keys.setPublicKey(pubkey)
}
export const login = (method, key) => {
keys.login(method, key)
modal.set({type: 'login/connect', noEscape: true})
}
export const signup = privkey => {
keys.setPrivateKey(privkey)
keys.login('privkey', privkey)
navigate('/notes/follows')
}

View File

@ -24,7 +24,7 @@
{/if}
{#if size === '2xl'}
<div {...$$props} class={cx($$props.class, className, "p-4 pt-10 max-w-2xl")}>
<div {...$$props} class={cx($$props.class, className, "p-4 max-w-2xl")}>
<slot />
</div>
{/if}

View File

@ -12,6 +12,7 @@
export let icon
export let maxWidth = null
export let maxHeight = null
export let hideInput = false
let input, file, listener, quote
let loading = false
@ -55,9 +56,11 @@
</script>
<div class="flex gap-2">
{#if !hideInput}
<Input type="text" wrapperClass="flex-grow" bind:value={value} placeholder="https://">
<i slot="before" class={`fa fa-${icon}`} />
</Input>
{/if}
<Anchor type="button" on:click={() => { isOpen = true }}>
<i class="fa fa-upload" />
</Anchor>

View File

@ -17,7 +17,7 @@
<div
class="fixed top-0 bg-dark flex justify-between items-center text-white w-full p-4
border-b border-medium z-10"
border-b border-medium z-10 h-16"
>
<button class="lg:hidden fa fa-bars fa-2xl cursor-pointer" on:click={toggleMenu} />
<Anchor external type="unstyled" href="https://github.com/staab/coracle" class="flex items-center gap-2">

View File

@ -12,7 +12,7 @@
const {nostr} = window as any
if (nostr) {
login({pubkey: await nostr.getPublicKey()})
login('extension', await nostr.getPublicKey())
} else {
modal.set({type: 'login/privkey'})
}

View File

@ -16,7 +16,7 @@
if (!privkey?.match(/[a-z0-9]{64}/)) {
toast.show("error", "Sorry, but that's an invalid private key.")
} else {
login({privkey})
login('privkey', privkey)
}
}
</script>

View File

@ -15,7 +15,7 @@
if (!pubkey?.match(/[a-z0-9]{64}/)) {
toast.show("error", "Sorry, but that's an invalid public key.")
} else {
login({pubkey})
login('pubkey', pubkey)
}
}
</script>

View File

@ -8,6 +8,7 @@
import {displayPerson} from "src/util/nostr"
import Button from "src/partials/Button.svelte"
import Compose from "src/partials/Compose.svelte"
import ImageInput from "src/partials/ImageInput.svelte"
import Input from "src/partials/Input.svelte"
import RelayCardSimple from "src/views/relays/RelayCardSimple.svelte"
import Content from "src/partials/Content.svelte"
@ -21,6 +22,7 @@
export let pubkey = null
let image = null
let input = null
let relays = getUserWriteRelays()
let showSettings = false
@ -38,6 +40,12 @@
)
}
$: {
if (image) {
input.type('\n' + image)
}
}
const onSubmit = async () => {
const {content, mentions, topics} = input.parse()
@ -99,7 +107,10 @@
<Compose bind:this={input} {onSubmit} />
</div>
</div>
<Button type="submit" class="text-center">Send</Button>
<div class="flex gap-2">
<Button type="submit" class="text-center flex-grow">Send</Button>
<ImageInput bind:value={image} icon="image" hideInput />
</div>
<small
class="flex justify-end items-center gap-1 cursor-pointer"
on:click={() => { showSettings = true }}>

View File

@ -29,4 +29,5 @@
{/if}
</div>
</Content>
<NewNoteButton />

View File

@ -57,7 +57,7 @@
actions.push({onClick: openAdvanced, label: 'Advanced', icon: 'sliders'})
}
if (user.getPubkey() === pubkey) {
if (user.getPubkey() === pubkey && $canPublish) {
actions.push({onClick: () => navigate('/profile'), label: 'Edit', icon: 'edit'})
}
}

View File

@ -7,11 +7,11 @@
import user from "src/agent/user"
import {sampleRelays, getPubkeyWriteRelays} from "src/agent/relays"
import database from "src/agent/database"
import {routes, modal} from "src/app/ui"
import {routes} from "src/app/ui"
export let pubkey
const {petnamePubkeys} = user
const {petnamePubkeys, canPublish} = user
const getRelays = () => sampleRelays(getPubkeyWriteRelays(pubkey))
let following = false
@ -28,10 +28,6 @@
const unfollow = async () => {
user.removePetname(pubkey)
}
const share = () => {
modal.set({type: 'person/share', person})
}
</script>
<div class="flex flex-col gap-4 py-2 px-3 relative">
@ -54,9 +50,7 @@
{/if}
</div>
<div class="flex gap-2">
<Anchor class="tippy-close" type="button-circle" on:click={share}>
<i class="fa fa-share-nodes" />
</Anchor>
{#if $canPublish}
{#if following}
<Anchor type="button-circle" on:click={unfollow}>
<i class="fa fa-user-minus" />
@ -66,6 +60,7 @@
<i class="fa fa-user-plus" />
</Anchor>
{/if}
{/if}
</div>
</div>
<p>{@html renderContent(person?.kind0?.about || '')}</p>