forked from coracle/flotilla
Clean up drafts implementation (#164)
This commit is contained in:
@@ -24,28 +24,28 @@
|
|||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
import {canEnforceNip70} from "@app/core/commands"
|
import {canEnforceNip70} from "@app/core/commands"
|
||||||
|
|
||||||
type CalendarValues = {
|
type Values = {
|
||||||
d?: string
|
d: string
|
||||||
title: string
|
title: string
|
||||||
content: unknown
|
content: string | object
|
||||||
location: string
|
location: string
|
||||||
start: number | undefined
|
start?: number
|
||||||
end: number | undefined
|
end?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
h?: string
|
h?: string
|
||||||
header: Snippet
|
header: Snippet
|
||||||
initialValues?: CalendarValues
|
initialValues?: Values
|
||||||
}
|
}
|
||||||
|
|
||||||
let {url, h, header, initialValues}: Props = $props()
|
let {url, h, header, initialValues}: Props = $props()
|
||||||
|
|
||||||
const draftKey = new DraftKey<CalendarValues>(`calendar:${url}:${h ?? ""}`)
|
const draftKey = new DraftKey<Values>(`calendar:${url}:${h ?? ""}`)
|
||||||
const draft = draftKey.get()
|
|
||||||
if (!initialValues) {
|
if (!initialValues) {
|
||||||
initialValues = draft
|
initialValues = draftKey.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
@@ -83,9 +83,9 @@
|
|||||||
const ed = await editor
|
const ed = await editor
|
||||||
const content = ed.getText({blockSeparator: "\n"}).trim()
|
const content = ed.getText({blockSeparator: "\n"}).trim()
|
||||||
const tags = [
|
const tags = [
|
||||||
["d", initialValues?.d || randomId()],
|
["d", d],
|
||||||
["title", title],
|
["title", title],
|
||||||
["location", location || ""],
|
["location", location],
|
||||||
["start", start.toString()],
|
["start", start.toString()],
|
||||||
["end", end.toString()],
|
["end", end.toString()],
|
||||||
...daysBetween(start, end).map(D => ["D", D.toString()]),
|
...daysBetween(start, end).map(D => ["D", D.toString()]),
|
||||||
@@ -108,28 +108,22 @@
|
|||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
let editorContent = $state<unknown>(initialValues?.content ?? "")
|
const d = $state(initialValues?.d ?? randomId())
|
||||||
|
|
||||||
const onChange = (json: unknown) => {
|
|
||||||
editorContent = json
|
|
||||||
}
|
|
||||||
|
|
||||||
const editor = makeEditor({
|
|
||||||
url,
|
|
||||||
submit,
|
|
||||||
uploading,
|
|
||||||
onChange,
|
|
||||||
content: initialValues?.content ?? "",
|
|
||||||
})
|
|
||||||
|
|
||||||
let title = $state(initialValues?.title ?? "")
|
let title = $state(initialValues?.title ?? "")
|
||||||
let location = $state(initialValues?.location ?? "")
|
let location = $state(initialValues?.location ?? "")
|
||||||
let start: number | undefined = $state(initialValues?.start)
|
let start: number | undefined = $state(initialValues?.start)
|
||||||
let end: number | undefined = $state(initialValues?.end)
|
let end: number | undefined = $state(initialValues?.end)
|
||||||
let endDirty = $state(Boolean(initialValues?.end))
|
let endDirty = $state(Boolean(initialValues?.end))
|
||||||
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = makeEditor({url, submit, uploading, onChange, content})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
draftKey.set({d: initialValues?.d, title, location, start, end, content: editorContent})
|
draftKey.set({d, title, location, start, end, content})
|
||||||
})
|
})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
const {pubkeys, info}: Props = $props()
|
const {pubkeys, info}: Props = $props()
|
||||||
|
|
||||||
const chat = deriveChat(pubkeys)
|
const chat = deriveChat(pubkeys)
|
||||||
const draftKey = new DraftKey<{content?: unknown}>(`dm:${$chat?.id}`)
|
const draftKey = new DraftKey<{content?: string | object}>(`dm:${$chat?.id}`)
|
||||||
const others = remove($pubkey!, pubkeys)
|
const others = remove($pubkey!, pubkeys)
|
||||||
const missingRelayLists = $derived(others.filter(pk => !$messagingRelayListsByPubkey.has(pk)))
|
const missingRelayLists = $derived(others.filter(pk => !$messagingRelayListsByPubkey.has(pk)))
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@
|
|||||||
{onSubmit}
|
{onSubmit}
|
||||||
{onEscape}
|
{onEscape}
|
||||||
{onEditPrevious}
|
{onEditPrevious}
|
||||||
content={eventToEdit?.content}
|
initialValues={eventToEdit}
|
||||||
draftKey={eventToEdit ? undefined : draftKey}
|
draftKey={eventToEdit ? undefined : draftKey}
|
||||||
disabled={Boolean(missingRelayLists.length)} />
|
disabled={Boolean(missingRelayLists.length)} />
|
||||||
{/key}
|
{/key}
|
||||||
|
|||||||
@@ -12,18 +12,31 @@
|
|||||||
import {makeEditor} from "@app/editor"
|
import {makeEditor} from "@app/editor"
|
||||||
import {type DraftKey} from "@app/util/drafts"
|
import {type DraftKey} from "@app/util/drafts"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
content?: string | object
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
content?: string
|
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
draftKey?: DraftKey<{content?: unknown}>
|
draftKey?: DraftKey<Values>
|
||||||
onEscape?: () => void
|
onEscape?: () => void
|
||||||
onEditPrevious?: () => void
|
onEditPrevious?: () => void
|
||||||
onSubmit: (event: EventContent) => void
|
onSubmit: (event: EventContent) => void
|
||||||
|
initialValues?: Values
|
||||||
}
|
}
|
||||||
|
|
||||||
const {content, disabled = false, draftKey, onEscape, onEditPrevious, onSubmit}: Props = $props()
|
let {
|
||||||
|
initialValues,
|
||||||
|
disabled = false,
|
||||||
|
draftKey,
|
||||||
|
onEscape,
|
||||||
|
onEditPrevious,
|
||||||
|
onSubmit,
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
const draft = draftKey?.get()
|
if (!initialValues) {
|
||||||
|
initialValues = draftKey?.get()
|
||||||
|
}
|
||||||
|
|
||||||
const autofocus = !isMobile && !disabled
|
const autofocus = !isMobile && !disabled
|
||||||
|
|
||||||
@@ -67,13 +80,14 @@
|
|||||||
ed.chain().clearContent().run()
|
ed.chain().clearContent().run()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (json: unknown) => {
|
let content = $state(initialValues?.content ?? "")
|
||||||
draftKey?.set({content: json})
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
}
|
}
|
||||||
|
|
||||||
const editor = makeEditor({
|
const editor = makeEditor({
|
||||||
content: content ?? (draft?.content as string | object | undefined),
|
content,
|
||||||
autofocus,
|
|
||||||
submit,
|
submit,
|
||||||
uploading,
|
uploading,
|
||||||
onChange,
|
onChange,
|
||||||
@@ -81,6 +95,10 @@
|
|||||||
encryptFiles: true,
|
encryptFiles: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
draftKey?.set({content})
|
||||||
|
})
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const ed = await editor
|
const ed = await editor
|
||||||
ed.view.dom.addEventListener("keydown", handleKeyDown)
|
ed.view.dom.addEventListener("keydown", handleKeyDown)
|
||||||
@@ -105,7 +123,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
<div class={editorClass} aria-disabled={disabled}>
|
<div class={editorClass} aria-disabled={disabled}>
|
||||||
<EditorContent {editor} />
|
<EditorContent {autofocus} {editor} />
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
|
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
|
||||||
|
|||||||
@@ -23,40 +23,30 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import {canEnforceNip70, uploadFile} from "@app/core/commands"
|
import {canEnforceNip70, uploadFile} from "@app/core/commands"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
d: string
|
||||||
|
title: string
|
||||||
|
content: string | object
|
||||||
|
price: number
|
||||||
|
currency: string
|
||||||
|
images: (string | File)[]
|
||||||
|
status: string
|
||||||
|
topics: string[]
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
h?: string
|
h?: string
|
||||||
header: Snippet
|
header: Snippet
|
||||||
initialValues?: {
|
initialValues?: Values
|
||||||
d?: string
|
|
||||||
title?: string
|
|
||||||
content?: string
|
|
||||||
price?: number
|
|
||||||
currency?: string
|
|
||||||
images?: (string | File)[]
|
|
||||||
status?: string
|
|
||||||
topics?: string[]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let {url, h, header, initialValues}: Props = $props()
|
let {url, h, header, initialValues}: Props = $props()
|
||||||
|
|
||||||
type ClassifiedDraft = {
|
const draftKey = new DraftKey<Values>(`classified:${url}:${h ?? ""}`)
|
||||||
editorContent?: unknown
|
|
||||||
d?: string
|
|
||||||
title?: string
|
|
||||||
content?: string
|
|
||||||
price?: number
|
|
||||||
currency?: string
|
|
||||||
images?: (string | File)[]
|
|
||||||
status?: string
|
|
||||||
topics?: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const draftKey = new DraftKey<ClassifiedDraft>(`classified:${url}:${h ?? ""}`)
|
|
||||||
const draft = draftKey.get()
|
|
||||||
if (!initialValues) {
|
if (!initialValues) {
|
||||||
initialValues = draft
|
initialValues = draftKey.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
@@ -85,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tags = [
|
const tags = [
|
||||||
["d", initialValues?.d || randomId()],
|
["d", d],
|
||||||
["title", title],
|
["title", title],
|
||||||
["summary", content],
|
["summary", content],
|
||||||
["price", String(price), currency],
|
["price", String(price), currency],
|
||||||
@@ -136,27 +126,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialContent = initialValues?.content || ""
|
|
||||||
const onChange = (json: unknown) => {
|
|
||||||
draftKey.set({editorContent: json, title, price, currency, topics, status, images})
|
|
||||||
}
|
|
||||||
const editor = makeEditor({
|
|
||||||
url,
|
|
||||||
submit,
|
|
||||||
onChange,
|
|
||||||
content: draft?.editorContent ?? initialContent,
|
|
||||||
})
|
|
||||||
|
|
||||||
let loading = $state(false)
|
let loading = $state(false)
|
||||||
|
const d = $state(initialValues?.d ?? randomId())
|
||||||
let title = $state(initialValues?.title ?? "")
|
let title = $state(initialValues?.title ?? "")
|
||||||
let status = $state(initialValues?.status ?? "active")
|
let status = $state(initialValues?.status ?? "active")
|
||||||
let price = $state(Number(initialValues?.price ?? 0))
|
let price = $state(initialValues?.price ?? 0)
|
||||||
let currency = $state(initialValues?.currency ?? "SAT")
|
let currency = $state(initialValues?.currency ?? "SAT")
|
||||||
let images = $state<(string | File)[]>(initialValues?.images ?? [])
|
let images = $state(initialValues?.images ?? [])
|
||||||
let topics = $state(uniq(removeUndefined((initialValues?.topics ?? []).map(normalizeTopic))))
|
let topics = $state(uniq(removeUndefined(initialValues?.topics?.map(normalizeTopic) ?? [])))
|
||||||
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = makeEditor({url, submit, onChange, content})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
draftKey.set({...draftKey.get(), title, price, currency, topics, status, images})
|
draftKey.set({d, title, status, price, currency, images, topics, content})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,16 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
content?: string | object
|
||||||
|
}
|
||||||
|
|
||||||
const {url, event, onClose, onSubmit} = $props()
|
const {url, event, onClose, onSubmit} = $props()
|
||||||
|
const draftKey = new DraftKey<Values>(`reply:${event.id}`)
|
||||||
const draftKey = new DraftKey<{content?: unknown}>(`reply:${event.id}`)
|
const initialValues = draftKey.get()
|
||||||
const draft = draftKey.get()
|
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
|
|
||||||
const uploading = writable(false)
|
const uploading = writable(false)
|
||||||
|
const autofocus = !isMobile
|
||||||
|
|
||||||
const selectFiles = () => editor.then(ed => ed.commands.selectFiles())
|
const selectFiles = () => editor.then(ed => ed.commands.selectFiles())
|
||||||
|
|
||||||
@@ -46,19 +48,19 @@
|
|||||||
onSubmit(publishComment({event, content, tags, relays: [url]}))
|
onSubmit(publishComment({event, content, tags, relays: [url]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (json: unknown) => draftKey.set({content: json})
|
|
||||||
|
|
||||||
const editor = makeEditor({
|
|
||||||
url,
|
|
||||||
submit,
|
|
||||||
uploading,
|
|
||||||
autofocus: !isMobile,
|
|
||||||
content: draft?.content as string | object | undefined,
|
|
||||||
onChange,
|
|
||||||
})
|
|
||||||
|
|
||||||
let form: HTMLElement
|
let form: HTMLElement
|
||||||
let spacer: HTMLElement
|
let spacer: HTMLElement
|
||||||
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = makeEditor({url, submit, uploading, content, onChange})
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
draftKey.set({content})
|
||||||
|
})
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -86,7 +88,7 @@
|
|||||||
<div class="card2 mx-2 my-2 bg-alt shadow-md">
|
<div class="card2 mx-2 my-2 bg-alt shadow-md">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="note-editor flex-grow overflow-hidden">
|
<div class="note-editor flex-grow overflow-hidden">
|
||||||
<EditorContent {editor} />
|
<EditorContent {autofocus} {editor} />
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
data-tip="Add an image"
|
data-tip="Add an image"
|
||||||
|
|||||||
@@ -23,27 +23,24 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import {canEnforceNip70} from "@app/core/commands"
|
import {canEnforceNip70} from "@app/core/commands"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
title: string
|
||||||
|
content: string | object
|
||||||
|
amount: number
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
h?: string
|
h?: string
|
||||||
initialValues?: {
|
initialValues?: Values
|
||||||
content?: string
|
|
||||||
amount?: number
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let {url, h, initialValues}: Props = $props()
|
let {url, h, initialValues}: Props = $props()
|
||||||
|
|
||||||
type GoalDraft = {
|
const draftKey = new DraftKey<Values>(`goal:${url}:${h ?? ""}`)
|
||||||
editorContent?: unknown
|
|
||||||
content?: string
|
|
||||||
amount?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const draftKey = new DraftKey<GoalDraft>(`goal:${url}:${h ?? ""}`)
|
|
||||||
const draft = draftKey.get()
|
|
||||||
if (!initialValues) {
|
if (!initialValues) {
|
||||||
initialValues = draft
|
initialValues = draftKey.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
@@ -57,7 +54,7 @@
|
|||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if ($uploading) return
|
if ($uploading) return
|
||||||
|
|
||||||
if (!content) {
|
if (!title) {
|
||||||
return pushToast({
|
return pushToast({
|
||||||
theme: "error",
|
theme: "error",
|
||||||
message: "Please provide a title for your funding goal.",
|
message: "Please provide a title for your funding goal.",
|
||||||
@@ -65,9 +62,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ed = await editor
|
const ed = await editor
|
||||||
const summary = ed.getText({blockSeparator: "\n"}).trim()
|
const content = ed.getText({blockSeparator: "\n"}).trim()
|
||||||
|
|
||||||
if (!summary.trim()) {
|
if (!content.trim()) {
|
||||||
return pushToast({
|
return pushToast({
|
||||||
theme: "error",
|
theme: "error",
|
||||||
message: "Please provide details about your funding goal.",
|
message: "Please provide details about your funding goal.",
|
||||||
@@ -76,7 +73,7 @@
|
|||||||
|
|
||||||
const tags = [
|
const tags = [
|
||||||
...ed.storage.nostr.getEditorTags(),
|
...ed.storage.nostr.getEditorTags(),
|
||||||
["summary", summary],
|
["summary", content],
|
||||||
["amount", String(amount)],
|
["amount", String(amount)],
|
||||||
["relays", url],
|
["relays", url],
|
||||||
]
|
]
|
||||||
@@ -91,14 +88,20 @@
|
|||||||
|
|
||||||
publishThunk({
|
publishThunk({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
event: makeEvent(ZAP_GOAL, {content, tags}),
|
event: makeEvent(ZAP_GOAL, {content: title, tags}),
|
||||||
})
|
})
|
||||||
|
|
||||||
draftKey.clear()
|
draftKey.clear()
|
||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (json: unknown) => draftKey.update({editorContent: json})
|
let title = $state(initialValues?.title ?? "")
|
||||||
|
let amount = $state(initialValues?.amount ?? 1000)
|
||||||
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
|
}
|
||||||
|
|
||||||
const editor = makeEditor({
|
const editor = makeEditor({
|
||||||
url,
|
url,
|
||||||
@@ -106,14 +109,11 @@
|
|||||||
uploading,
|
uploading,
|
||||||
onChange,
|
onChange,
|
||||||
placeholder: "What's on your mind?",
|
placeholder: "What's on your mind?",
|
||||||
content: draft?.editorContent as string | object | undefined,
|
content,
|
||||||
})
|
})
|
||||||
|
|
||||||
let content = $state(initialValues?.content ?? "")
|
|
||||||
let amount = $state(initialValues?.amount ?? 1000)
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
draftKey.update({content, amount})
|
draftKey.update({title, content, amount})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
<!-- svelte-ignore a11y_autofocus -->
|
<!-- svelte-ignore a11y_autofocus -->
|
||||||
<input
|
<input
|
||||||
autofocus={!isMobile}
|
autofocus={!isMobile}
|
||||||
bind:value={content}
|
bind:value={title}
|
||||||
class="grow"
|
class="grow"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="What do funds go towards?" />
|
placeholder="What do funds go towards?" />
|
||||||
|
|||||||
@@ -25,16 +25,16 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import type {PollType} from "@app/util/polls"
|
import type {PollType} from "@app/util/polls"
|
||||||
|
|
||||||
type DraftOption = {
|
type Option = {
|
||||||
id: string
|
id: string
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type PollDraft = {
|
type Values = {
|
||||||
title?: string
|
title: string
|
||||||
pollType?: PollType
|
pollType: PollType
|
||||||
endsAt?: number
|
endsAt?: number
|
||||||
options?: DraftOption[]
|
options: Option[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -43,9 +43,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const {url, h}: Props = $props()
|
const {url, h}: Props = $props()
|
||||||
|
const draftKey = new DraftKey<Values>(`poll:${url}:${h ?? ""}`)
|
||||||
const draftKey = new DraftKey<PollDraft>(`poll:${url}:${h ?? ""}`)
|
const initialValues = draftKey.get()
|
||||||
const draft = draftKey.get()
|
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
|
|
||||||
@@ -144,16 +143,16 @@
|
|||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = $state(draft?.title ?? "")
|
let draggedOptionId = $state<string | undefined>()
|
||||||
let pollType = $state<PollType>(draft?.pollType ?? "singlechoice")
|
let title = $state(initialValues?.title ?? "")
|
||||||
let endsAt = $state<number | undefined>(draft?.endsAt)
|
let pollType = $state<PollType>(initialValues?.pollType ?? "singlechoice")
|
||||||
let options = $state<DraftOption[]>(
|
let endsAt = $state<number | undefined>(initialValues?.endsAt)
|
||||||
draft?.options ?? [
|
let options = $state<Option[]>(
|
||||||
|
initialValues?.options ?? [
|
||||||
{id: randomId(), value: "Yes"},
|
{id: randomId(), value: "Yes"},
|
||||||
{id: randomId(), value: "No"},
|
{id: randomId(), value: "No"},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
let draggedOptionId = $state<string | undefined>()
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
draftKey.set({title, pollType, endsAt, options})
|
draftKey.set({title, pollType, endsAt, options})
|
||||||
|
|||||||
@@ -15,21 +15,26 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import {onDestroy, onMount} from "svelte"
|
import {onDestroy, onMount} from "svelte"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
content?: string | object
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url?: string
|
url?: string
|
||||||
h?: string
|
h?: string
|
||||||
content?: string
|
|
||||||
onEscape?: () => void
|
onEscape?: () => void
|
||||||
onEditPrevious?: () => void
|
onEditPrevious?: () => void
|
||||||
onSubmit: (event: EventContent) => void
|
onSubmit: (event: EventContent) => void
|
||||||
|
initialValues?: Values
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url, h, content, onEscape, onEditPrevious, onSubmit}: Props = $props()
|
let {url, h, initialValues, onEscape, onEditPrevious, onSubmit}: Props = $props()
|
||||||
|
|
||||||
type ComposeDraft = {content?: unknown}
|
const draftKey = url || h ? new DraftKey<Values>(`room:${url ?? ""}:${h ?? ""}`) : undefined
|
||||||
|
|
||||||
const draftKey = url || h ? new DraftKey<ComposeDraft>(`room:${url ?? ""}:${h ?? ""}`) : undefined
|
if (!initialValues) {
|
||||||
const draft = draftKey?.get()
|
initialValues = draftKey?.get()
|
||||||
|
}
|
||||||
|
|
||||||
const autofocus = !isMobile
|
const autofocus = !isMobile
|
||||||
|
|
||||||
@@ -71,21 +76,25 @@
|
|||||||
ed.chain().clearContent().run()
|
ed.chain().clearContent().run()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (json: unknown) => {
|
let popover: Instance | undefined = $state()
|
||||||
draftKey?.set({content: json})
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
}
|
}
|
||||||
|
|
||||||
const editor = makeEditor({
|
const editor = makeEditor({
|
||||||
url,
|
url,
|
||||||
content: content ?? (draft?.content as string | object | undefined),
|
content,
|
||||||
autofocus,
|
|
||||||
submit,
|
submit,
|
||||||
uploading,
|
uploading,
|
||||||
onChange,
|
onChange,
|
||||||
aggressive: true,
|
aggressive: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
let popover: Instance | undefined = $state()
|
$effect(() => {
|
||||||
|
draftKey?.set({content})
|
||||||
|
})
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const ed = await editor
|
const ed = await editor
|
||||||
@@ -124,7 +133,7 @@
|
|||||||
</Tippy>
|
</Tippy>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-editor flex-grow overflow-hidden">
|
<div class="chat-editor flex-grow overflow-hidden">
|
||||||
<EditorContent {editor} />
|
<EditorContent {autofocus} {editor} />
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
|
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
|
||||||
|
|||||||
@@ -21,16 +21,19 @@
|
|||||||
import {DraftKey} from "@app/util/drafts"
|
import {DraftKey} from "@app/util/drafts"
|
||||||
import {canEnforceNip70} from "@app/core/commands"
|
import {canEnforceNip70} from "@app/core/commands"
|
||||||
|
|
||||||
|
type Values = {
|
||||||
|
content?: string | object
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
h?: string
|
h?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url, h}: Props = $props()
|
const {url, h}: Props = $props()
|
||||||
|
const draftKey = new DraftKey<Values>(`thread:${url}:${h ?? ""}`)
|
||||||
const draftKey = new DraftKey<{content?: unknown; title?: string}>(`thread:${url}:${h ?? ""}`)
|
const initialValues = draftKey.get()
|
||||||
const draft = draftKey.get()
|
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
|
|
||||||
const uploading = writable(false)
|
const uploading = writable(false)
|
||||||
@@ -78,7 +81,12 @@
|
|||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (json: unknown) => draftKey.update({content: json})
|
let title = $state(initialValues?.title ?? "")
|
||||||
|
let content = $state(initialValues?.content ?? "")
|
||||||
|
|
||||||
|
const onChange = (json: object) => {
|
||||||
|
content = json
|
||||||
|
}
|
||||||
|
|
||||||
const editor = makeEditor({
|
const editor = makeEditor({
|
||||||
url,
|
url,
|
||||||
@@ -86,13 +94,11 @@
|
|||||||
uploading,
|
uploading,
|
||||||
onChange,
|
onChange,
|
||||||
placeholder: "What's on your mind?",
|
placeholder: "What's on your mind?",
|
||||||
content: draft?.content as string | object | undefined,
|
content,
|
||||||
})
|
})
|
||||||
|
|
||||||
let title: string = $state(draft?.title ?? "")
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
draftKey.update({title})
|
draftKey.update({title, content})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
editor: Promise<Editor>
|
editor: Promise<Editor>
|
||||||
|
autofocus?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {editor}: Props = $props()
|
const {editor, autofocus}: Props = $props()
|
||||||
|
|
||||||
let element: HTMLElement
|
let element: HTMLElement
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
element?.append(ed.options.element)
|
element?.append(ed.options.element)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ed as any)._shouldAutofocus) {
|
if (autofocus) {
|
||||||
const hasContent = ed.getText().trim().length > 0
|
const hasContent = ed.getText().trim().length > 0
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {pushToast} from "@app/util/toast"
|
|||||||
export const makeEditor = async ({
|
export const makeEditor = async ({
|
||||||
encryptFiles = false,
|
encryptFiles = false,
|
||||||
aggressive = false,
|
aggressive = false,
|
||||||
autofocus = false,
|
|
||||||
charCount,
|
charCount,
|
||||||
content = "",
|
content = "",
|
||||||
onChange,
|
onChange,
|
||||||
@@ -37,10 +36,9 @@ export const makeEditor = async ({
|
|||||||
}: {
|
}: {
|
||||||
encryptFiles?: boolean
|
encryptFiles?: boolean
|
||||||
aggressive?: boolean
|
aggressive?: boolean
|
||||||
autofocus?: boolean
|
|
||||||
charCount?: Writable<number>
|
charCount?: Writable<number>
|
||||||
content?: string | object
|
content?: string | object
|
||||||
onChange?: (json: unknown) => void
|
onChange?: (json: object) => void
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
url?: string
|
url?: string
|
||||||
submit: () => void
|
submit: () => void
|
||||||
@@ -86,7 +84,6 @@ export const makeEditor = async ({
|
|||||||
|
|
||||||
const ed = new Editor({
|
const ed = new Editor({
|
||||||
content: typeof content === "string" ? escapeHtml(content) : content,
|
content: typeof content === "string" ? escapeHtml(content) : content,
|
||||||
autofocus: false,
|
|
||||||
editorProps,
|
editorProps,
|
||||||
element: document.createElement("div"),
|
element: document.createElement("div"),
|
||||||
extensions: [
|
extensions: [
|
||||||
@@ -148,7 +145,5 @@ export const makeEditor = async ({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
;(ed as any)._shouldAutofocus = autofocus
|
|
||||||
|
|
||||||
return ed
|
return ed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,7 +464,7 @@
|
|||||||
{onSubmit}
|
{onSubmit}
|
||||||
{onEscape}
|
{onEscape}
|
||||||
{onEditPrevious}
|
{onEditPrevious}
|
||||||
content={eventToEdit?.content}
|
initialValues={eventToEdit}
|
||||||
bind:this={compose} />
|
bind:this={compose} />
|
||||||
{/key}
|
{/key}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -352,7 +352,7 @@
|
|||||||
{onSubmit}
|
{onSubmit}
|
||||||
{onEscape}
|
{onEscape}
|
||||||
{onEditPrevious}
|
{onEditPrevious}
|
||||||
content={eventToEdit?.content}
|
initialValues={eventToEdit}
|
||||||
bind:this={compose} />
|
bind:this={compose} />
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user