diff --git a/components/Pages/PublicationMetadata.tsx b/components/Pages/PublicationMetadata.tsx index 6621f688..84b4c14a 100644 --- a/components/Pages/PublicationMetadata.tsx +++ b/components/Pages/PublicationMetadata.tsx @@ -1,14 +1,8 @@ import Link from "next/link"; import { useLeafletPublicationData } from "components/PageSWRDataProvider"; -import { AsyncValueInput, Input } from "components/Input"; -import { useEffect, useState } from "react"; -import { useDebouncedEffect } from "src/hooks/useDebouncedEffect"; -import { updateLeafletDraftMetadata } from "actions/publications/updateLeafletDraftMetadata"; +import { useRef } from "react"; import { useReplicache } from "src/replicache"; -import { - AsyncValueAutosizeTextarea, - AutosizeTextarea, -} from "components/utils/AutosizeTextarea"; +import { AsyncValueAutosizeTextarea } from "components/utils/AutosizeTextarea"; import { Separator } from "components/Layout"; import { AtUri } from "@atproto/syntax"; import { PubLeafletDocument } from "lexicons/api"; @@ -30,8 +24,6 @@ export const PublicationMetadata = ({ let description = useSubscribe(rep, (tx) => tx.get("publication_description"), ); - let { permissions } = useEntitySetContext(); - let record = pub?.documents?.data as PubLeafletDocument.Record | null; let publishedAt = record?.publishedAt; @@ -58,27 +50,25 @@ export const PublicationMetadata = ({ Editor - { + onChange={async (newTitle) => { await rep?.mutate.updatePublicationDraft({ - title: e.currentTarget.value, + title: newTitle, description, }); }} placeholder="Untitled" /> - { + onChange={async (newDescription) => { await rep?.mutate.updatePublicationDraft({ - description: e.currentTarget.value, title, + description: newDescription, }); }} /> @@ -103,6 +93,77 @@ export const PublicationMetadata = ({ ); }; +export const TextField = ({ + value, + onChange, + className, + placeholder, +}: { + value: string; + onChange: (v: string) => Promise; + className: string; + placeholder: string; +}) => { + let { undoManager } = useReplicache(); + let actionTimeout = useRef(null); + let { permissions } = useEntitySetContext(); + let previousSelection = useRef(null); + let ref = useRef(null); + return ( + { + let start = e.currentTarget.selectionStart, + end = e.currentTarget.selectionEnd; + previousSelection.current = { start, end }; + }} + className={className} + value={value} + onBlur={async () => { + if (actionTimeout.current) { + undoManager.endGroup(); + window.clearTimeout(actionTimeout.current); + actionTimeout.current = null; + } + }} + onChange={async (e) => { + let newValue = e.currentTarget.value; + let oldValue = value; + let start = e.currentTarget.selectionStart, + end = e.currentTarget.selectionEnd; + await onChange(e.currentTarget.value); + + if (actionTimeout.current) { + window.clearTimeout(actionTimeout.current); + } else { + undoManager.startGroup(); + } + + actionTimeout.current = window.setTimeout(() => { + undoManager.endGroup(); + actionTimeout.current = null; + }, 200); + let previousStart = previousSelection.current?.start || null, + previousEnd = previousSelection.current?.end || null; + undoManager.add({ + redo: async () => { + await onChange(newValue); + ref.current?.setSelectionRange(start, end); + ref.current?.focus(); + }, + undo: async () => { + await onChange(oldValue); + ref.current?.setSelectionRange(previousStart, previousEnd); + ref.current?.focus(); + }, + }); + }} + placeholder={placeholder} + /> + ); +}; + export const PublicationMetadataPreview = () => { let { data: pub } = useLeafletPublicationData(); let record = pub?.documents?.data as PubLeafletDocument.Record | null;