TAO/client/src/components/PostCard/NewThreadCard.tsx

142 lines
4.3 KiB
TypeScript
Raw Normal View History

2023-09-03 13:04:25 +00:00
import CardContainer from './CardContainer';
2023-09-15 15:56:25 +00:00
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
2023-10-29 03:09:46 +00:00
import { useState, useEffect, useMemo } from 'react';
2023-10-27 13:26:17 +00:00
import { generatePrivateKey, getPublicKey, finishEvent } from 'nostr-tools';
2023-09-15 07:06:37 +00:00
import { minePow } from '../../utils/mine';
2023-09-15 16:58:12 +00:00
import { publish } from '../../utils/relays';
2023-10-25 07:53:34 +00:00
import NostrImg from '../../utils/ImgUpload';
2023-10-26 09:46:48 +00:00
const difficulty = 20
2023-09-03 13:04:25 +00:00
2023-09-15 15:56:25 +00:00
const NewThreadCard: React.FC = () => {
const [comment, setComment] = useState("");
2023-10-25 07:53:34 +00:00
const [file, setFile] = useState("");
2023-10-29 03:09:46 +00:00
const [sk, setSk] = useState(generatePrivateKey());
const [messageFromWorker, setMessageFromWorker] = useState(null);
// Initialize the worker outside of any effects
const worker = useMemo(() => new Worker(new URL('../../powWorker', import.meta.url)), []);
useEffect(() => {
worker.onmessage = (event) => {
setMessageFromWorker(event.data);
};
}, []);
2023-10-25 07:53:34 +00:00
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
2023-10-29 03:09:46 +00:00
worker.postMessage({
unsigned: {
kind: 1,
tags: [],
content: comment + " " + file,
created_at: Math.floor(Date.now() / 1000),
pubkey: getPublicKey(sk),
},
difficulty
});
};
2023-10-29 03:09:46 +00:00
useEffect(() => {
if (messageFromWorker) {
try {
const signedEvent = finishEvent(messageFromWorker, sk);
publish(signedEvent);
setComment("");
setFile("");
setSk(generatePrivateKey())
return () => {
worker.terminate();
};
} catch (error) {
setComment(error + ' ' + comment);
}
}
2023-10-29 03:09:46 +00:00
}, [messageFromWorker]);
2023-10-25 07:53:34 +00:00
async function attachFile(file_input: File | null) {
try {
if (file_input) {
const rx = await NostrImg(file_input);
if (rx.url) {
setFile(rx.url);
} else if (rx?.error) {
setFile(rx.error);
}
}
} catch (error: unknown) {
if (error instanceof Error) {
setFile(error?.message);
}
}
}
2023-09-03 13:04:25 +00:00
return (
<>
<CardContainer>
2023-10-29 03:09:46 +00:00
{/* <p>Message from worker: {messageFromWorker}</p> */}
2023-10-25 07:53:34 +00:00
<form
name="post"
method="post"
encType="multipart/form-data"
className=""
onSubmit={handleSubmit}
>
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
<div id="togglePostFormLink" className="text-lg font-semibold">
Start a New Thread
</div>
<div>
<textarea
name="com"
wrap="soft"
className="w-full p-2 rounded bg-gradient-to-r from-blue-900 to-cyan-500 text-white border-none placeholder-blue-300"
placeholder='Shitpost here...'
value={comment}
onChange={(e) => setComment(e.target.value)}
/>
</div>
<div>
{file !== "" && (
<div className="file m-0.5">
<img
src={file}
loading="lazy"
/>
2023-09-14 13:44:13 +00:00
</div>
2023-10-25 07:53:34 +00:00
)}
</div>
<div className="flex justify-between items-center">
<div className="flex items-center">
<ArrowUpTrayIcon
className="h-6 w-6 text-white cursor-pointer"
onClick={() => document.getElementById('file_input')?.click()}
/>
<input
type="file"
name="file_input"
id="file_input"
style={{ display: 'none' }}
onChange={(e) => {
const file_input = e.target.files?.[0];
if (file_input) {
attachFile(file_input);
}
}}
2023-09-14 13:44:13 +00:00
/>
</div>
2023-10-25 07:53:34 +00:00
<span className="flex items-center"><CpuChipIcon className="h-6 w-6 text-white" />: {difficulty}</span>
<button type="submit" className="px-4 py-2 bg-gradient-to-r from-cyan-900 to-blue-500 rounded text-white font-semibold">
Submit
</button>
</div>
<div id="postFormError" className="text-red-500" />
</form>
2023-09-03 13:04:25 +00:00
</CardContainer>
</>
);
};
export default NewThreadCard;