From 256d76dbca4e09629a695e100c57a7b2aa4e1180 Mon Sep 17 00:00:00 2001 From: zmeyer44 Date: Mon, 16 Oct 2023 16:46:47 -0400 Subject: [PATCH] adding new post page and button on home page --- app/(app)/_layout/components/AuthActions.tsx | 5 +- app/(app)/app/_sections/FeaturedLists.tsx | 2 - app/(app)/app/page.tsx | 11 +- app/(app)/article/new/layout.tsx | 9 ++ app/(app)/article/new/page.tsx | 23 +++ components/LongForm/Editor.tsx | 14 +- components/LongForm/ToolBar.tsx | 149 +++++++++++++++++++ components/LongForm/index.tsx | 17 ++- containers/Article/Editor.tsx | 69 +++++++++ lib/hooks/useAutoSizeTextArea.ts | 3 +- 10 files changed, 288 insertions(+), 14 deletions(-) create mode 100644 app/(app)/article/new/layout.tsx create mode 100644 app/(app)/article/new/page.tsx create mode 100644 components/LongForm/ToolBar.tsx create mode 100644 containers/Article/Editor.tsx diff --git a/app/(app)/_layout/components/AuthActions.tsx b/app/(app)/_layout/components/AuthActions.tsx index 7fee570..5b2e51b 100644 --- a/app/(app)/_layout/components/AuthActions.tsx +++ b/app/(app)/_layout/components/AuthActions.tsx @@ -36,11 +36,12 @@ const LoginModal = dynamic(() => import("@/components/Modals/Login"), { export default function AuthActions() { const modal = useModal(); const { currentUser, logout, attemptLogin } = useCurrentUser(); + const { ndk } = useNDK(); useEffect(() => { - if (!currentUser) { + if (ndk && !currentUser) { void attemptLogin(); } - }, []); + }, [ndk]); if (currentUser) { return ( <> diff --git a/app/(app)/app/_sections/FeaturedLists.tsx b/app/(app)/app/_sections/FeaturedLists.tsx index c01287f..8ff52f4 100644 --- a/app/(app)/app/_sections/FeaturedLists.tsx +++ b/app/(app)/app/_sections/FeaturedLists.tsx @@ -27,7 +27,6 @@ import { getTagValues, getTagsValues } from "@/lib/nostr/utils"; import { NOTABLE_ACCOUNTS } from "@/constants"; import { type NDKKind } from "@nostr-dev-kit/ndk"; import { uniqBy } from "ramda"; -import useProfile from "@/lib/hooks/useProfile"; import ListCard from "@/components/ListCard"; export default function FeaturedLists() { @@ -66,7 +65,6 @@ export default function FeaturedLists() {
Featured Lists - {processedEvents.length}
+ + ); } diff --git a/app/(app)/article/new/layout.tsx b/app/(app)/article/new/layout.tsx new file mode 100644 index 0000000..571bb0e --- /dev/null +++ b/app/(app)/article/new/layout.tsx @@ -0,0 +1,9 @@ +import { ReactElement, ReactNode } from "react"; + +export default function ModalLayout(props: { children: ReactElement }) { + return ( +
+ {props.children} +
+ ); +} diff --git a/app/(app)/article/new/page.tsx b/app/(app)/article/new/page.tsx new file mode 100644 index 0000000..8294519 --- /dev/null +++ b/app/(app)/article/new/page.tsx @@ -0,0 +1,23 @@ +"use client"; +import { useEffect } from "react"; +import Editor_ from "@/containers/Article/Editor"; +import Editor from "@/components/LongForm/Editor"; +import { useNDK } from "@nostr-dev-kit/ndk-react"; +import { nip19 } from "nostr-tools"; +import Spinner from "@/components/spinner"; +import useEvents from "@/lib/hooks/useEvents"; + +export default function EditorPage({ + params: { key }, +}: { + params: { + key: string; + }; +}) { + return ( +
+ {/* */} + +
+ ); +} diff --git a/components/LongForm/Editor.tsx b/components/LongForm/Editor.tsx index 2635c09..1040444 100644 --- a/components/LongForm/Editor.tsx +++ b/components/LongForm/Editor.tsx @@ -7,16 +7,24 @@ import "@blocknote/core/style.css"; interface EditorProps { editable?: boolean; + onContentChange: (text: string) => void; } -const Editor = ({ editable }: EditorProps) => { +const Editor = ({ editable, onContentChange }: EditorProps) => { const { resolvedTheme } = useTheme(); - const [content, setContent] = useState(""); const editor: BlockNoteEditor = useBlockNote({ editable, onEditorContentChange: (editor) => { - setContent(JSON.stringify(editor.topLevelBlocks, null, 2)); + // Converts the editor's contents from Block objects to Markdown and + // saves them. + const saveBlocksAsMarkdown = async () => { + const markdown: string = await editor.blocksToMarkdown( + editor.topLevelBlocks, + ); + onContentChange(markdown); + }; + saveBlocksAsMarkdown(); }, }); diff --git a/components/LongForm/ToolBar.tsx b/components/LongForm/ToolBar.tsx new file mode 100644 index 0000000..aca9ffb --- /dev/null +++ b/components/LongForm/ToolBar.tsx @@ -0,0 +1,149 @@ +"use client"; + +import { useRef, useState } from "react"; + +import { Button } from "@/components/ui/button"; + +import { Textarea } from "../ui/textarea"; +import useAutosizeTextArea from "@/lib/hooks/useAutoSizeTextArea"; +import { HiOutlinePhoto } from "react-icons/hi2"; +import { cn } from "@/lib/utils"; + +interface ToolbarProps { + initialData?: { + title?: string; + summary?: string; + image?: string; + }; + preview?: boolean; + onSubmit: ({ + title, + summary, + image, + }: { + title: string; + summary: string; + image?: string; + }) => void; +} + +export const Toolbar = ({ initialData, preview, onSubmit }: ToolbarProps) => { + const [loading, setLoading] = useState(false); + const [title, setTitle] = useState(initialData?.title ?? ""); + const [summary, setSummary] = useState(initialData?.summary ?? ""); + const [image, setImage] = useState(initialData?.image); + const titleRef = useRef(null); + const summaryRef = useRef(null); + useAutosizeTextArea(titleRef.current, title); + useAutosizeTextArea(summaryRef.current, summary); + const [isEditingTitle, setIsEditingTitle] = useState(false); + const [isEditingSummary, setIsEditingSummary] = useState(false); + const [value, setValue] = useState(initialData?.title); + + const update = () => { + console.log("Update"); + }; + + const enableInput = (type: "title" | "summary") => { + if (preview) return; + if (type === "title") { + setIsEditingTitle(true); + setTimeout(() => { + titleRef.current?.focus(); + }, 0); + } else { + summaryRef.current?.focus(); + setIsEditingSummary(true); + setTimeout(() => { + summaryRef.current?.focus(); + }, 0); + } + }; + + const disableInput = () => { + setIsEditingTitle(false); + setIsEditingSummary(false); + }; + + const handleSubmit = async () => { + try { + setLoading(true); + await onSubmit({ title, summary, image }); + setLoading(false); + } catch (err) { + console.log("Error", err); + } + }; + + const onKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Enter") { + event.preventDefault(); + disableInput(); + } + }; + + return ( +
+
+
+ {!initialData?.image && !preview && ( + + )} +
+ +
+ {isEditingTitle && !preview ? ( +