Move editor stuff to its own folder
This commit is contained in:
@@ -3,35 +3,25 @@
|
||||
import type {Readable} from "svelte/store"
|
||||
import {writable} from "svelte/store"
|
||||
import {createEditor, type Editor, EditorContent} from "svelte-tiptap"
|
||||
import {NProfileExtension, ImageExtension} from "nostr-editor"
|
||||
import {createEvent} from "@welshman/util"
|
||||
import {publishThunk, makeThunk} from "@welshman/app"
|
||||
import {findNodes} from "@lib/tiptap"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import {makeMention, makeIMeta} from "@app/commands"
|
||||
import {getChatEditorOptions, addFile} from "@app/editor"
|
||||
import {getEditorOptions, getEditorTags, addFile} from "@lib/editor"
|
||||
import {ROOM, MESSAGE, GENERAL} from "@app/state"
|
||||
import {getPubkeyHints} from "@app/commands"
|
||||
|
||||
export let url
|
||||
export let room = GENERAL
|
||||
|
||||
const uploading = writable(false)
|
||||
const loading = writable(false)
|
||||
|
||||
let editor: Readable<Editor>
|
||||
|
||||
const sendMessage = () => {
|
||||
const json = $editor.getJSON()
|
||||
const mentionTags = findNodes(NProfileExtension.name, json).map(m =>
|
||||
makeMention(m.attrs!.pubkey, m.attrs!.relays),
|
||||
)
|
||||
const imetaTags = findNodes(ImageExtension.name, json).map(({attrs: {src, sha256: x}}: any) =>
|
||||
makeIMeta(src, {x, ox: x}),
|
||||
)
|
||||
|
||||
const submit = () => {
|
||||
const event = createEvent(MESSAGE, {
|
||||
content: $editor.getText(),
|
||||
tags: [[ROOM, room], ...mentionTags, ...imetaTags],
|
||||
tags: [[ROOM, room], ...getEditorTags($editor)],
|
||||
})
|
||||
|
||||
publishThunk(makeThunk({event, relays: [url]}))
|
||||
@@ -40,7 +30,7 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
editor = createEditor(getChatEditorOptions({uploading, sendMessage}))
|
||||
editor = createEditor(getEditorOptions({submit, loading, getPubkeyHints, submitOnEnter: true}))
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -48,15 +38,15 @@
|
||||
class="shadow-top-xl relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100 p-2">
|
||||
<Button
|
||||
data-tip="Add an image"
|
||||
class="center h-10 w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200 tooltip"
|
||||
class="center tooltip h-10 w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200"
|
||||
on:click={() => addFile($editor)}>
|
||||
{#if $uploading}
|
||||
{#if $loading}
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
{:else}
|
||||
<Icon icon="gallery-send" />
|
||||
{/if}
|
||||
</Button>
|
||||
<div class="flex-grow overflow-hidden chat-editor">
|
||||
<div class="chat-editor flex-grow overflow-hidden">
|
||||
<EditorContent editor={$editor} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import {clip} from "@app/toast"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
export let selected: NodeViewProps["selected"]
|
||||
|
||||
const copy = () => clip(node.attrs.lnbc)
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class="inline">
|
||||
<Button on:click={copy} class={cx("link-content", {"link-content-selected": selected})}>
|
||||
<Icon icon="bolt" size={3} class="inline-block translate-y-px" />
|
||||
{node.attrs.lnbc.slice(0, 16)}...
|
||||
</Button>
|
||||
</NodeViewWrapper>
|
||||
@@ -1,24 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import {ellipsize} from "@welshman/lib"
|
||||
import {type TrustedEvent, fromNostrURI, Address} from "@welshman/util"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import {deriveEvent} from "@app/state"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
|
||||
const displayEvent = (e: TrustedEvent) =>
|
||||
e?.content.length > 1
|
||||
? ellipsize(e.content, 50)
|
||||
: fromNostrURI(nevent || naddr).slice(0, 16) + "..."
|
||||
|
||||
$: ({identifier, pubkey, kind, id, relays = [], nevent, naddr} = node.attrs)
|
||||
$: event = deriveEvent(id || new Address(kind, pubkey, identifier).toString(), relays)
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class="inline">
|
||||
<Link external href="https://njump.me/{node.attrs.nevent}" class="link-content">
|
||||
{displayEvent($event)}
|
||||
</Link>
|
||||
</NodeViewWrapper>
|
||||
@@ -1,14 +0,0 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
export let selected: NodeViewProps["selected"]
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class={cx("link-content inline", {"link-content-selected": selected})}>
|
||||
<Icon icon="paperclip" size={3} class="inline-block translate-y-px" />
|
||||
{node.attrs.file.name}
|
||||
</NodeViewWrapper>
|
||||
@@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import {displayUrl} from "@welshman/lib"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
export let selected: NodeViewProps["selected"]
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class="inline-block">
|
||||
<Link
|
||||
external
|
||||
href={node.attrs.url}
|
||||
class={cx("link-content", {"link-content-selected": selected})}>
|
||||
<Icon icon="link-round" size={3} class="inline-block" />
|
||||
{displayUrl(node.attrs.url)}
|
||||
</Link>
|
||||
</NodeViewWrapper>
|
||||
@@ -1,22 +0,0 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import {displayProfile} from "@welshman/util"
|
||||
import {deriveProfile} from "@welshman/app"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
export let selected: NodeViewProps["selected"]
|
||||
|
||||
$: profile = deriveProfile(node.attrs.pubkey, node.attrs.relays)
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class="inline">
|
||||
<Link
|
||||
external
|
||||
href="https://njump.me/{node.attrs.nprofile}"
|
||||
class={cx("link-content", {"link-content-selected": selected})}>
|
||||
@{displayProfile($profile)}
|
||||
</Link>
|
||||
</NodeViewWrapper>
|
||||
@@ -1,96 +0,0 @@
|
||||
<svelte:options accessors />
|
||||
|
||||
<script lang="ts">
|
||||
import {throttle} from "throttle-debounce"
|
||||
import {slide} from "svelte/transition"
|
||||
import {clamp} from "@welshman/lib"
|
||||
import {theme} from "@app/theme"
|
||||
|
||||
export let term
|
||||
export let search
|
||||
export let select
|
||||
export let component
|
||||
export let loading = false
|
||||
export let allowCreate = false
|
||||
|
||||
let index = 0
|
||||
let element: Element
|
||||
let items: string[] = []
|
||||
|
||||
$: populateItems(term)
|
||||
|
||||
const populateItems = throttle(300, term => {
|
||||
items = $search.searchValues(term).slice(0, 30)
|
||||
})
|
||||
|
||||
const setIndex = (newIndex: number, block: any) => {
|
||||
index = clamp([0, items.length - 1], newIndex)
|
||||
element.querySelector(`button:nth-child(${index})`)?.scrollIntoView({block})
|
||||
}
|
||||
|
||||
export const onKeyDown = (e: any) => {
|
||||
if (["Enter", "Tab"].includes(e.code)) {
|
||||
const value = items[index]
|
||||
|
||||
if (value) {
|
||||
select(value)
|
||||
return true
|
||||
} else if (term && allowCreate) {
|
||||
select(term)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (e.code === "Space" && term && allowCreate) {
|
||||
select(term)
|
||||
return true
|
||||
}
|
||||
|
||||
if (e.code === "ArrowUp") {
|
||||
setIndex(index - 1, "start")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if (e.code === "ArrowDown") {
|
||||
setIndex(index + 1, "start")
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if items.length > 0 || (term && allowCreate)}
|
||||
<div
|
||||
data-theme={$theme}
|
||||
bind:this={element}
|
||||
transition:slide|local={{duration: 100}}
|
||||
class="mt-2 max-h-[350px] overflow-y-auto overflow-x-hidden shadow-xl">
|
||||
{#if term && allowCreate}
|
||||
<button
|
||||
class="white-space-nowrap block w-full min-w-0 cursor-pointer overflow-x-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content"
|
||||
on:mousedown|preventDefault
|
||||
on:click|preventDefault={() => select(term)}>
|
||||
Use "<svelte:component this={component} value={term} />"
|
||||
</button>
|
||||
{/if}
|
||||
{#each items as value, i (value)}
|
||||
<button
|
||||
class="white-space-nowrap block w-full min-w-0 cursor-pointer overflow-x-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content"
|
||||
class:bg-primary={index === i}
|
||||
class:text-primary-content={index === i}
|
||||
on:mousedown|preventDefault
|
||||
on:click|preventDefault={() => select(value)}>
|
||||
<svelte:component this={component} {value} />
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{#if loading}
|
||||
<div transition:slide|local class="bg-tinted-700 flex gap-2 px-4 py-2 text-neutral-200">
|
||||
<div>
|
||||
<i class="fa fa-circle-notch fa-spin" />
|
||||
</div>
|
||||
Loading more options...
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -1,12 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type {NodeViewProps} from "@tiptap/core"
|
||||
import {NodeViewWrapper} from "svelte-tiptap"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
export let node: NodeViewProps["node"]
|
||||
</script>
|
||||
|
||||
<NodeViewWrapper class="link-content inline">
|
||||
<Icon icon="paperclip" size={3} class="inline-block translate-y-px" />
|
||||
{node.attrs.file.name}
|
||||
</NodeViewWrapper>
|
||||
@@ -15,19 +15,14 @@
|
||||
formatTimestampAsTime,
|
||||
} from "@welshman/app"
|
||||
import type {PublishStatusData} from "@welshman/app"
|
||||
import {
|
||||
REACTION,
|
||||
ZAP_RESPONSE,
|
||||
displayRelayUrl,
|
||||
getAncestorTags,
|
||||
} from "@welshman/util"
|
||||
import {REACTION, ZAP_RESPONSE, displayRelayUrl, getAncestorTags} from "@welshman/util"
|
||||
import {repository} from "@welshman/app"
|
||||
import {fly} from "@lib/transition"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import {REPLY, deriveEvent, displayReaction} from "@app/state"
|
||||
import {getChatViewOptions} from "@app/editor"
|
||||
import {getViewOptions} from "@lib/editor"
|
||||
|
||||
export let event: TrustedEvent
|
||||
export let showPubkey: boolean
|
||||
@@ -79,7 +74,7 @@
|
||||
!isPending && !isPublished && findStatus($ps, [PublishStatus.Failure, PublishStatus.Timeout])
|
||||
|
||||
onMount(() => {
|
||||
editor = createEditor(getChatViewOptions(event.content))
|
||||
editor = createEditor(getViewOptions(event))
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {deriveProfileDisplay} from "@welshman/app"
|
||||
|
||||
export let value
|
||||
|
||||
const display = deriveProfileDisplay(value)
|
||||
</script>
|
||||
|
||||
@{$display}
|
||||
@@ -1,17 +1,12 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {fromPairs} from "@welshman/lib"
|
||||
import {Tags, getAddress} from "@welshman/util"
|
||||
import {repository, pubkey, secondsToDate, getLocale, formatTimestamp, formatTimestampAsDate, deriveProfileDisplay} from "@welshman/app"
|
||||
import {getAddress} from "@welshman/util"
|
||||
import {secondsToDate, getLocale, formatTimestamp, formatTimestampAsDate} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
|
||||
export let event
|
||||
|
||||
const address = getAddress(event)
|
||||
const timeFmt = new Intl.DateTimeFormat(getLocale(), {timeStyle: "short"})
|
||||
const datetimeFmt = new Intl.DateTimeFormat(getLocale(), {dateStyle: "short", timeStyle: "short"})
|
||||
const profileDisplay = deriveProfileDisplay(event.pubkey)
|
||||
|
||||
$: meta = fromPairs(event.tags) as Record<string, string>
|
||||
$: end = parseInt(meta.end)
|
||||
@@ -23,7 +18,7 @@
|
||||
$: isSingleDay = startDateDisplay === endDateDisplay
|
||||
</script>
|
||||
|
||||
<div class="card2 flex justify-between items-center gap-2">
|
||||
<div class="card2 flex items-center justify-between gap-2">
|
||||
<span>{meta.title || meta.name}</span>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<Icon icon="clock-circle" size={4} />
|
||||
|
||||
@@ -3,29 +3,27 @@
|
||||
import type {Readable} from "svelte/store"
|
||||
import {writable} from "svelte/store"
|
||||
import {createEditor, type Editor, EditorContent} from "svelte-tiptap"
|
||||
import {NProfileExtension, ImageExtension} from "nostr-editor"
|
||||
import {randomId} from "@welshman/lib"
|
||||
import {createEvent, EVENT_DATE, EVENT_TIME} from "@welshman/util"
|
||||
import {publishThunk, makeThunk, dateToSeconds} from "@welshman/app"
|
||||
import {findNodes} from "@lib/tiptap"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
|
||||
import {makeMention, makeIMeta} from "@app/commands"
|
||||
import {getNoteEditorOptions, addFile, uploadFiles} from "@app/editor"
|
||||
import {pushModal, clearModal} from "@app/modal"
|
||||
import {getPubkeyHints} from "@app/commands"
|
||||
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
|
||||
import {clearModal} from "@app/modal"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
export let url
|
||||
|
||||
const submit = () => uploadFiles($editor)
|
||||
const startSubmit = () => uploadFiles($editor)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const uploading = writable(false)
|
||||
const loading = writable(false)
|
||||
|
||||
const sendMessage = () => {
|
||||
const submit = () => {
|
||||
if (!title) {
|
||||
return pushToast({
|
||||
theme: "error",
|
||||
@@ -40,15 +38,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
const json = $editor.getJSON()
|
||||
const kind = isAllDay ? EVENT_DATE : EVENT_TIME
|
||||
const mentionTags = findNodes(NProfileExtension.name, json).map(m =>
|
||||
makeMention(m.attrs!.pubkey, m.attrs!.relays),
|
||||
)
|
||||
const imetaTags = findNodes(ImageExtension.name, json).map(({attrs: {src, sha256: x}}: any) =>
|
||||
makeIMeta(src, {x, ox: x}),
|
||||
)
|
||||
|
||||
const event = createEvent(kind, {
|
||||
content: $editor.getText(),
|
||||
tags: [
|
||||
@@ -57,8 +47,7 @@
|
||||
["location", location],
|
||||
["start", dateToSeconds(start).toString()],
|
||||
["end", dateToSeconds(end).toString()],
|
||||
...mentionTags,
|
||||
...imetaTags,
|
||||
...getEditorTags($editor),
|
||||
],
|
||||
})
|
||||
|
||||
@@ -67,19 +56,18 @@
|
||||
}
|
||||
|
||||
let editor: Readable<Editor>
|
||||
let isAllDay = false
|
||||
let file: File
|
||||
const isAllDay = false
|
||||
let title = ""
|
||||
let location = ""
|
||||
let start: Date
|
||||
let end: Date
|
||||
|
||||
onMount(() => {
|
||||
editor = createEditor(getNoteEditorOptions({uploading, sendMessage}))
|
||||
editor = createEditor(getEditorOptions({submit, loading, getPubkeyHints}))
|
||||
})
|
||||
</script>
|
||||
|
||||
<form class="column gap-4" on:submit|preventDefault={submit}>
|
||||
<form class="column gap-4" on:submit|preventDefault={startSubmit}>
|
||||
<div class="py-2">
|
||||
<h1 class="heading">Create an Event</h1>
|
||||
<p class="text-center">Invite other group members to events online or in real life.</p>
|
||||
@@ -95,14 +83,11 @@
|
||||
<div
|
||||
slot="input"
|
||||
class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100">
|
||||
<div class="flex-grow overflow-hidden input-editor">
|
||||
<div class="input-editor flex-grow overflow-hidden">
|
||||
<EditorContent editor={$editor} />
|
||||
</div>
|
||||
<Button
|
||||
data-tip="Add an image"
|
||||
class="btn center tooltip"
|
||||
on:click={() => addFile($editor)}>
|
||||
{#if $uploading}
|
||||
<Button data-tip="Add an image" class="center btn tooltip" on:click={() => addFile($editor)}>
|
||||
{#if $loading}
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
{:else}
|
||||
<Icon icon="gallery-send" />
|
||||
@@ -134,9 +119,6 @@
|
||||
<Icon icon="alt-arrow-left" />
|
||||
Go back
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">
|
||||
Create Event
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">Create Event</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {onMount} from "svelte"
|
||||
import type {Readable} from "svelte/store"
|
||||
import {createEditor, type Editor, EditorContent} from "svelte-tiptap"
|
||||
import {displayPubkey} from '@welshman/util'
|
||||
import {displayPubkey} from "@welshman/util"
|
||||
import {deriveProfile, deriveProfileDisplay, formatTimestamp} from "@welshman/app"
|
||||
import Avatar from '@lib/components/Avatar.svelte'
|
||||
import {getChatViewOptions} from '@app/editor'
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import {getViewOptions} from "@lib/editor"
|
||||
|
||||
export let root
|
||||
export let replies
|
||||
@@ -17,13 +16,13 @@
|
||||
let editor: Readable<Editor>
|
||||
|
||||
onMount(() => {
|
||||
editor = createEditor(getChatViewOptions(root.content))
|
||||
editor = createEditor(getViewOptions(root.content))
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="card2 flex flex-col gap-2">
|
||||
<div class="flex justify-between items-center gap-2">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="flex gap-2">
|
||||
<div class="py-1">
|
||||
<Avatar src={$profile?.picture} size={10} />
|
||||
@@ -40,6 +39,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{#if replies.length > 0}
|
||||
Show {replies.length} {replies.length === 1 ? 'reply' : 'replies'}
|
||||
Show {replies.length} {replies.length === 1 ? "reply" : "replies"}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -3,44 +3,24 @@
|
||||
import type {Readable} from "svelte/store"
|
||||
import {writable} from "svelte/store"
|
||||
import {createEditor, type Editor, EditorContent} from "svelte-tiptap"
|
||||
import {NProfileExtension, ImageExtension} from "nostr-editor"
|
||||
import {randomId} from "@welshman/lib"
|
||||
import {createEvent, NOTE} from "@welshman/util"
|
||||
import {publishThunk, makeThunk, dateToSeconds} from "@welshman/app"
|
||||
import {findNodes} from "@lib/tiptap"
|
||||
import {publishThunk, makeThunk} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
|
||||
import {makeMention, makeIMeta} from "@app/commands"
|
||||
import {getNoteEditorOptions, addFile, uploadFiles} from "@app/editor"
|
||||
import {pushModal, clearModal} from "@app/modal"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {getPubkeyHints} from "@app/commands"
|
||||
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
|
||||
import {clearModal} from "@app/modal"
|
||||
|
||||
export let url
|
||||
|
||||
const submit = () => uploadFiles($editor)
|
||||
const startSubmit = () => uploadFiles($editor)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const uploading = writable(false)
|
||||
const loading = writable(false)
|
||||
|
||||
const sendMessage = () => {
|
||||
const json = $editor.getJSON()
|
||||
const mentionTags = findNodes(NProfileExtension.name, json).map(m =>
|
||||
makeMention(m.attrs!.pubkey, m.attrs!.relays),
|
||||
)
|
||||
const imetaTags = findNodes(ImageExtension.name, json).map(({attrs: {src, sha256: x}}: any) =>
|
||||
makeIMeta(src, {x, ox: x}),
|
||||
)
|
||||
|
||||
const event = createEvent(NOTE, {
|
||||
content: $editor.getText(),
|
||||
tags: [
|
||||
...mentionTags,
|
||||
...imetaTags,
|
||||
],
|
||||
})
|
||||
const submit = () => {
|
||||
const event = createEvent(NOTE, {content: $editor.getText(), tags: getEditorTags($editor)})
|
||||
|
||||
publishThunk(makeThunk({event, relays: [url]}))
|
||||
clearModal()
|
||||
@@ -49,24 +29,24 @@
|
||||
let editor: Readable<Editor>
|
||||
|
||||
onMount(() => {
|
||||
editor = createEditor(getNoteEditorOptions({uploading, sendMessage}))
|
||||
editor = createEditor(getEditorOptions({submit, loading, getPubkeyHints}))
|
||||
})
|
||||
</script>
|
||||
|
||||
<form class="column gap-4" on:submit|preventDefault={submit}>
|
||||
<form class="column gap-4" on:submit|preventDefault={startSubmit}>
|
||||
<div class="py-2">
|
||||
<h1 class="heading">Create a Thread</h1>
|
||||
<p class="text-center">Share your thoughts, or start a discussion.</p>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="flex-grow overflow-hidden note-editor">
|
||||
<div class="note-editor flex-grow overflow-hidden">
|
||||
<EditorContent editor={$editor} />
|
||||
</div>
|
||||
<Button
|
||||
data-tip="Add an image"
|
||||
class="tooltip tooltip-left absolute right-2 bottom-1"
|
||||
class="tooltip tooltip-left absolute bottom-1 right-2"
|
||||
on:click={() => addFile($editor)}>
|
||||
{#if $uploading}
|
||||
{#if $loading}
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
{:else}
|
||||
<Icon icon="paperclip" size={3} />
|
||||
@@ -78,9 +58,6 @@
|
||||
<Icon icon="alt-arrow-left" />
|
||||
Go back
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">
|
||||
Create Thread
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">Create Thread</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user