bug: note reply always

closes #189
This commit is contained in:
Kieran 2023-02-05 12:32:34 +00:00
parent c0cf92ebf3
commit efa765ea84
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
3 changed files with 101 additions and 102 deletions

View File

@ -1,9 +1,7 @@
import "./NoteCreator.css";
import { useState } from "react";
import Attachment from "Icons/Attachment";
import Plus from "Icons/Plus";
import useEventPublisher from "Feed/EventPublisher";
import { openFile } from "Util";
import Textarea from "Element/Textarea";
@ -29,110 +27,107 @@ function NotePreview({ note }: NotePreviewProps) {
}
export interface NoteCreatorProps {
show: boolean
setShow: (s: boolean) => void
replyTo?: NEvent,
onSend?: Function,
autoFocus: boolean
show: boolean
setShow: (s: boolean) => void
replyTo?: NEvent,
onSend?: Function,
autoFocus: boolean
}
export function NoteCreator(props: NoteCreatorProps) {
const { show, setShow, replyTo, onSend, autoFocus } = props
const publisher = useEventPublisher();
const [note, setNote] = useState<string>();
const [error, setError] = useState<string>();
const [active, setActive] = useState<boolean>(false);
const uploader = useFileUpload();
const hasErrors = (error?.length ?? 0) > 0
const { show, setShow, replyTo, onSend, autoFocus } = props
const publisher = useEventPublisher();
const [note, setNote] = useState<string>();
const [error, setError] = useState<string>();
const [active, setActive] = useState<boolean>(false);
const uploader = useFileUpload();
const hasErrors = (error?.length ?? 0) > 0
async function sendNote() {
if (note) {
let ev = replyTo ? await publisher.reply(replyTo, note) : await publisher.note(note);
console.debug("Sending note: ", ev);
publisher.broadcast(ev);
setNote("");
setShow(false);
if (typeof onSend === "function") {
onSend();
}
setActive(false);
async function sendNote() {
if (note) {
let ev = replyTo ? await publisher.reply(replyTo, note) : await publisher.note(note);
console.debug("Sending note: ", ev);
publisher.broadcast(ev);
setNote("");
setShow(false);
if (typeof onSend === "function") {
onSend();
}
setActive(false);
}
}
async function attachFile() {
try {
let file = await openFile();
if (file) {
let rx = await uploader.upload(file, file.name);
if (rx.url) {
setNote(n => `${n ? `${n}\n` : ""}${rx.url}`);
} else if (rx?.error) {
setError(rx.error);
}
}
} catch (error: any) {
setError(error?.message)
}
}
async function attachFile() {
try {
let file = await openFile();
if (file) {
let rx = await uploader.upload(file, file.name);
if (rx.url) {
setNote(n => `${n ? `${n}\n` : ""}${rx.url}`);
} else if (rx?.error) {
setError(rx.error);
}
}
} catch (error: any) {
setError(error?.message)
}
function onChange(ev: any) {
const { value } = ev.target
setNote(value)
if (value) {
setActive(true)
} else {
setActive(false)
}
}
function onChange(ev: any) {
const { value } = ev.target
setNote(value)
if (value) {
setActive(true)
} else {
setActive(false)
}
}
function cancel(ev: any) {
setShow(false)
setNote("")
}
function cancel(ev: any) {
setShow(false)
setNote("")
}
function onSubmit(ev: React.MouseEvent<HTMLButtonElement>) {
ev.stopPropagation();
sendNote().catch(console.warn);
}
function onSubmit(ev: React.MouseEvent<HTMLButtonElement>) {
ev.stopPropagation();
sendNote().catch(console.warn);
}
return (
<>
<button className="note-create-button" type="button" onClick={() => setShow(!show)}>
<Plus />
</button>
{show && (
<Modal
className="note-creator-modal"
onClose={() => setShow(false)}
>
{replyTo && (
<NotePreview note={replyTo} />
)}
<div className={`flex note-creator ${replyTo ? 'note-reply' : ''}`}>
<div className="flex f-col mr10 f-grow">
<Textarea
autoFocus={autoFocus}
className={`textarea ${active ? "textarea--focused" : ""}`}
onChange={onChange}
value={note}
onFocus={() => setActive(true)}
/>
<button type="button" className="attachment" onClick={(e) => attachFile()}>
<Attachment />
</button>
</div>
{hasErrors && <span className="error">{error}</span>}
return (
<>
{show && (
<Modal
className="note-creator-modal"
onClose={() => setShow(false)}
>
{replyTo && (
<NotePreview note={replyTo} />
)}
<div className={`flex note-creator ${replyTo ? 'note-reply' : ''}`}>
<div className="flex f-col mr10 f-grow">
<Textarea
autoFocus={autoFocus}
className={`textarea ${active ? "textarea--focused" : ""}`}
onChange={onChange}
value={note}
onFocus={() => setActive(true)}
/>
<button type="button" className="attachment" onClick={(e) => attachFile()}>
<Attachment />
</button>
</div>
<div className="note-creator-actions">
<button className="secondary" type="button" onClick={cancel}>
Cancel
</button>
<button type="button" onClick={onSubmit}>
{replyTo ? 'Reply' : 'Send'}
</button>
</div>
</Modal>
)}
</>
);
{hasErrors && <span className="error">{error}</span>}
</div>
<div className="note-creator-actions">
<button className="secondary" type="button" onClick={cancel}>
Cancel
</button>
<button type="button" onClick={onSubmit}>
{replyTo ? 'Reply' : 'Send'}
</button>
</div>
</Modal>
)}
</>
);
}

View File

@ -1,5 +1,5 @@
import "./Layout.css";
import { useEffect } from "react"
import { useEffect, useState } from "react"
import { useDispatch, useSelector } from "react-redux";
import { Outlet, useNavigate } from "react-router-dom";
import Envelope from "Icons/Envelope";
@ -18,9 +18,12 @@ import useModeration from "Hooks/useModeration";
import { IndexedUDB, useDb } from "State/Users/Db";
import { db } from "Db";
import { bech32ToHex } from "Util";
import { NoteCreator } from "Element/NoteCreator";
import Plus from "Icons/Plus";
export default function Layout() {
const [show, setShow] = useState(false)
const dispatch = useDispatch();
const navigate = useNavigate();
const { loggedOut, publicKey, relays, notifications, readNotifications, dms, preferences, newUserKey } = useSelector((s: RootState) => s.login);
@ -174,8 +177,12 @@ export default function Layout() {
}
</div>
</header>
<Outlet />
<button className="note-create-button" type="button" onClick={() => setShow(!show)}>
<Plus />
</button>
<NoteCreator replyTo={undefined} autoFocus={true} show={show} setShow={setShow} />
</div>
)
}

View File

@ -4,7 +4,6 @@ import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { RootState } from "State/Store";
import { NoteCreator } from "Element/NoteCreator";
import Timeline from "Element/Timeline";
import { HexKey } from "Nostr";
import { TimelineSubject } from "Feed/TimelineFeed";
@ -16,7 +15,6 @@ const RootTab = {
};
export default function RootPage() {
const [show, setShow] = useState(false)
const [loggedOut, pubKey, follows] = useSelector<RootState, [boolean | undefined, HexKey | undefined, HexKey[]]>(s => [s.login.loggedOut, s.login.publicKey, s.login.follows]);
const [tab, setTab] = useState(RootTab.Posts);
@ -45,8 +43,7 @@ export default function RootPage() {
</div>
</div></> : null}
{followHints()}
<Timeline key={tab} subject={timelineSubect} postsOnly={tab === RootTab.Posts} method={"TIME_RANGE"} window={tab === RootTab.Global ? 60 : undefined}/>
<NoteCreator replyTo={undefined} autoFocus={true} show={show} setShow={setShow} />
<Timeline key={tab} subject={timelineSubect} postsOnly={tab === RootTab.Posts} method={"TIME_RANGE"} window={tab === RootTab.Global ? 60 : undefined} />
</>
);
}