mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Add image uploads to new post
This commit is contained in:
parent
f97d9f2171
commit
2f0317e8aa
@ -1,7 +1,7 @@
|
|||||||
# Current
|
# Current
|
||||||
|
|
||||||
- [ ] Strip zero width spaces from compose
|
- [ ] 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
|
- [ ] Make the note relays button modal make sense, one relay with no explanation is not good
|
||||||
|
|
||||||
# Image uploads
|
# Image uploads
|
||||||
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
# More
|
# More
|
||||||
|
|
||||||
|
- [ ] Mute threads http://localhost:5173/nevent1qqsyz8x6r0cu7l6vwlcjhf8qhxyjtdykvuervkc3t3mfggse4qtwt0gpyfmhxue69uhkummnw3ezumrfvfjhyarpwdc8y6tddaexg6t4d5hxxmmdnhxvea
|
||||||
- [ ] Add webtorrent support
|
- [ ] Add webtorrent support
|
||||||
- https://coracle.social/nevent1qqsxgxcsq5vevy4wdty5z5v88nhwp2fc5qgl0ws5rmamn6z72hwv3qcpyfmhxue69uhkummnw3ez6an9wf5kv6t9vsh8wetvd3hhyer9wghxuet5qk6c9q
|
- https://coracle.social/nevent1qqsxgxcsq5vevy4wdty5z5v88nhwp2fc5qgl0ws5rmamn6z72hwv3qcpyfmhxue69uhkummnw3ez6an9wf5kv6t9vsh8wetvd3hhyer9wghxuet5qk6c9q
|
||||||
- [ ] Add coracle relay
|
- [ ] Add coracle relay
|
||||||
|
@ -3,72 +3,106 @@ import {get} from 'svelte/store'
|
|||||||
import {error} from 'src/util/logger'
|
import {error} from 'src/util/logger'
|
||||||
import {synced} from 'src/util/misc'
|
import {synced} from 'src/util/misc'
|
||||||
|
|
||||||
|
const method = synced('agent/keys/method')
|
||||||
const pubkey = synced('agent/keys/pubkey')
|
const pubkey = synced('agent/keys/pubkey')
|
||||||
const privkey = synced('agent/keys/privkey')
|
const privkey = synced('agent/keys/privkey')
|
||||||
const getExtension = () => (window as {nostr?: any}).nostr
|
const getExtension = () => (window as {nostr?: any}).nostr
|
||||||
const canSign = () => Boolean(getExtension() || get(privkey))
|
const canSign = () => ['privkey', 'extension'].includes(get(method))
|
||||||
|
|
||||||
const setPrivateKey = _privkey => {
|
// For backwards compatibility, if method isn't set but we're logged in, set it
|
||||||
privkey.set(_privkey)
|
setTimeout(() => {
|
||||||
pubkey.set(getPublicKey(_privkey))
|
method.update($method => {
|
||||||
}
|
if ($method) {
|
||||||
|
return $method
|
||||||
|
}
|
||||||
|
|
||||||
const setPublicKey = _pubkey => {
|
if (get(privkey)) {
|
||||||
pubkey.set(_pubkey)
|
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 = () => {
|
const clear = () => {
|
||||||
|
method.set(null)
|
||||||
pubkey.set(null)
|
pubkey.set(null)
|
||||||
privkey.set(null)
|
privkey.set(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sign = async event => {
|
const sign = event => {
|
||||||
const ext = getExtension()
|
const $method = get(method)
|
||||||
const key = get(privkey)
|
|
||||||
|
|
||||||
event.pubkey = get(pubkey)
|
event.pubkey = get(pubkey)
|
||||||
event.id = getEventHash(event)
|
event.id = getEventHash(event)
|
||||||
|
|
||||||
if (key) {
|
if ($method === 'privkey') {
|
||||||
return Object.assign(event, {
|
return Object.assign(event, {
|
||||||
sig: signEvent(event, get(privkey)),
|
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 getCrypt = () => {
|
||||||
const $privkey = get(privkey)
|
const $method = get(method)
|
||||||
const nostr = getExtension()
|
|
||||||
|
|
||||||
if (!$privkey && !nostr) {
|
if ($method === 'privkey') {
|
||||||
throw new Error('No encryption method available.')
|
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 {
|
if ($method === 'extension') {
|
||||||
encrypt: (pubkey, message) => {
|
return {
|
||||||
return $privkey
|
encrypt: (pubkey, message) => getExtension().nip04.encrypt(pubkey, message),
|
||||||
? nip04.encrypt($privkey, pubkey, message)
|
decrypt: async (pubkey, message) => {
|
||||||
: nostr.nip04.encrypt(pubkey, message)
|
try {
|
||||||
},
|
return await getExtension().nip04.decrypt(pubkey, message)
|
||||||
decrypt: async (pubkey, message) => {
|
} catch (e) {
|
||||||
try {
|
error(e)
|
||||||
return $privkey
|
|
||||||
? nip04.decrypt($privkey, pubkey, message)
|
|
||||||
: await nostr.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 {
|
export default {
|
||||||
pubkey, privkey, canSign, setPrivateKey, setPublicKey, clear,
|
pubkey, privkey, canSign, login, clear, sign, getCrypt,
|
||||||
sign, getCrypt,
|
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,14 @@ export const loadAppData = async pubkey => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const login = ({privkey, pubkey}: {privkey?: string, pubkey?: string}) => {
|
export const login = (method, key) => {
|
||||||
if (privkey) {
|
keys.login(method, key)
|
||||||
keys.setPrivateKey(privkey)
|
|
||||||
} else {
|
|
||||||
keys.setPublicKey(pubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
modal.set({type: 'login/connect', noEscape: true})
|
modal.set({type: 'login/connect', noEscape: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const signup = privkey => {
|
export const signup = privkey => {
|
||||||
keys.setPrivateKey(privkey)
|
keys.login('privkey', privkey)
|
||||||
|
|
||||||
navigate('/notes/follows')
|
navigate('/notes/follows')
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if size === '2xl'}
|
{#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 />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
export let icon
|
export let icon
|
||||||
export let maxWidth = null
|
export let maxWidth = null
|
||||||
export let maxHeight = null
|
export let maxHeight = null
|
||||||
|
export let hideInput = false
|
||||||
|
|
||||||
let input, file, listener, quote
|
let input, file, listener, quote
|
||||||
let loading = false
|
let loading = false
|
||||||
@ -55,9 +56,11 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
|
{#if !hideInput}
|
||||||
<Input type="text" wrapperClass="flex-grow" bind:value={value} placeholder="https://">
|
<Input type="text" wrapperClass="flex-grow" bind:value={value} placeholder="https://">
|
||||||
<i slot="before" class={`fa fa-${icon}`} />
|
<i slot="before" class={`fa fa-${icon}`} />
|
||||||
</Input>
|
</Input>
|
||||||
|
{/if}
|
||||||
<Anchor type="button" on:click={() => { isOpen = true }}>
|
<Anchor type="button" on:click={() => { isOpen = true }}>
|
||||||
<i class="fa fa-upload" />
|
<i class="fa fa-upload" />
|
||||||
</Anchor>
|
</Anchor>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="fixed top-0 bg-dark flex justify-between items-center text-white w-full p-4
|
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} />
|
<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">
|
<Anchor external type="unstyled" href="https://github.com/staab/coracle" class="flex items-center gap-2">
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
const {nostr} = window as any
|
const {nostr} = window as any
|
||||||
|
|
||||||
if (nostr) {
|
if (nostr) {
|
||||||
login({pubkey: await nostr.getPublicKey()})
|
login('extension', await nostr.getPublicKey())
|
||||||
} else {
|
} else {
|
||||||
modal.set({type: 'login/privkey'})
|
modal.set({type: 'login/privkey'})
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
if (!privkey?.match(/[a-z0-9]{64}/)) {
|
if (!privkey?.match(/[a-z0-9]{64}/)) {
|
||||||
toast.show("error", "Sorry, but that's an invalid private key.")
|
toast.show("error", "Sorry, but that's an invalid private key.")
|
||||||
} else {
|
} else {
|
||||||
login({privkey})
|
login('privkey', privkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
if (!pubkey?.match(/[a-z0-9]{64}/)) {
|
if (!pubkey?.match(/[a-z0-9]{64}/)) {
|
||||||
toast.show("error", "Sorry, but that's an invalid public key.")
|
toast.show("error", "Sorry, but that's an invalid public key.")
|
||||||
} else {
|
} else {
|
||||||
login({pubkey})
|
login('pubkey', pubkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
import {displayPerson} from "src/util/nostr"
|
import {displayPerson} from "src/util/nostr"
|
||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Compose from "src/partials/Compose.svelte"
|
import Compose from "src/partials/Compose.svelte"
|
||||||
|
import ImageInput from "src/partials/ImageInput.svelte"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import RelayCardSimple from "src/views/relays/RelayCardSimple.svelte"
|
import RelayCardSimple from "src/views/relays/RelayCardSimple.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
@ -21,6 +22,7 @@
|
|||||||
|
|
||||||
export let pubkey = null
|
export let pubkey = null
|
||||||
|
|
||||||
|
let image = null
|
||||||
let input = null
|
let input = null
|
||||||
let relays = getUserWriteRelays()
|
let relays = getUserWriteRelays()
|
||||||
let showSettings = false
|
let showSettings = false
|
||||||
@ -38,6 +40,12 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (image) {
|
||||||
|
input.type('\n' + image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
const {content, mentions, topics} = input.parse()
|
const {content, mentions, topics} = input.parse()
|
||||||
|
|
||||||
@ -99,7 +107,10 @@
|
|||||||
<Compose bind:this={input} {onSubmit} />
|
<Compose bind:this={input} {onSubmit} />
|
||||||
</div>
|
</div>
|
||||||
</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
|
<small
|
||||||
class="flex justify-end items-center gap-1 cursor-pointer"
|
class="flex justify-end items-center gap-1 cursor-pointer"
|
||||||
on:click={() => { showSettings = true }}>
|
on:click={() => { showSettings = true }}>
|
||||||
|
@ -29,4 +29,5 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
<NewNoteButton />
|
<NewNoteButton />
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
actions.push({onClick: openAdvanced, label: 'Advanced', icon: 'sliders'})
|
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'})
|
actions.push({onClick: () => navigate('/profile'), label: 'Edit', icon: 'edit'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
import user from "src/agent/user"
|
import user from "src/agent/user"
|
||||||
import {sampleRelays, getPubkeyWriteRelays} from "src/agent/relays"
|
import {sampleRelays, getPubkeyWriteRelays} from "src/agent/relays"
|
||||||
import database from "src/agent/database"
|
import database from "src/agent/database"
|
||||||
import {routes, modal} from "src/app/ui"
|
import {routes} from "src/app/ui"
|
||||||
|
|
||||||
export let pubkey
|
export let pubkey
|
||||||
|
|
||||||
const {petnamePubkeys} = user
|
const {petnamePubkeys, canPublish} = user
|
||||||
const getRelays = () => sampleRelays(getPubkeyWriteRelays(pubkey))
|
const getRelays = () => sampleRelays(getPubkeyWriteRelays(pubkey))
|
||||||
|
|
||||||
let following = false
|
let following = false
|
||||||
@ -28,10 +28,6 @@
|
|||||||
const unfollow = async () => {
|
const unfollow = async () => {
|
||||||
user.removePetname(pubkey)
|
user.removePetname(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
const share = () => {
|
|
||||||
modal.set({type: 'person/share', person})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 py-2 px-3 relative">
|
<div class="flex flex-col gap-4 py-2 px-3 relative">
|
||||||
@ -54,9 +50,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<Anchor class="tippy-close" type="button-circle" on:click={share}>
|
{#if $canPublish}
|
||||||
<i class="fa fa-share-nodes" />
|
|
||||||
</Anchor>
|
|
||||||
{#if following}
|
{#if following}
|
||||||
<Anchor type="button-circle" on:click={unfollow}>
|
<Anchor type="button-circle" on:click={unfollow}>
|
||||||
<i class="fa fa-user-minus" />
|
<i class="fa fa-user-minus" />
|
||||||
@ -66,6 +60,7 @@
|
|||||||
<i class="fa fa-user-plus" />
|
<i class="fa fa-user-plus" />
|
||||||
</Anchor>
|
</Anchor>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>{@html renderContent(person?.kind0?.about || '')}</p>
|
<p>{@html renderContent(person?.kind0?.about || '')}</p>
|
||||||
|
Loading…
Reference in New Issue
Block a user