mirror of
https://github.com/smolgrrr/TAO.git
synced 2024-09-20 09:21:25 +00:00
good enough
This commit is contained in:
parent
9c540eda8c
commit
940a891943
@ -5,7 +5,7 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { XCircleIcon } from "@heroicons/react/24/solid";
|
import { XCircleIcon } from "@heroicons/react/24/solid";
|
||||||
import { useState, useEffect, useMemo } from "react";
|
import { useState, useEffect, useMemo } from "react";
|
||||||
import { generatePrivateKey, getPublicKey, finishEvent, UnsignedEvent } from "nostr-tools";
|
import { generatePrivateKey, getPublicKey, finishEvent, UnsignedEvent, Event as NostrEvent, nip19 } from "nostr-tools";
|
||||||
import { publish } from "../../utils/relays";
|
import { publish } from "../../utils/relays";
|
||||||
import { renderMedia, attachFile } from "../../utils/FileUpload";
|
import { renderMedia, attachFile } from "../../utils/FileUpload";
|
||||||
|
|
||||||
@ -40,7 +40,20 @@ const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: strin
|
|||||||
return { startWork, messageFromWorker, doingWorkProgress };
|
return { startWork, messageFromWorker, doingWorkProgress };
|
||||||
};
|
};
|
||||||
|
|
||||||
const NewNoteCard: React.FC = () => {
|
interface FormProps {
|
||||||
|
refEvent?: NostrEvent;
|
||||||
|
tagType?: 'Reply' | 'Quote' | '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagMapping = {
|
||||||
|
'Reply': ['e', 'p'],
|
||||||
|
'Quote': ['q', 'p']
|
||||||
|
};
|
||||||
|
|
||||||
|
const NewNoteCard = ({
|
||||||
|
refEvent,
|
||||||
|
tagType
|
||||||
|
}: FormProps) => {
|
||||||
const [comment, setComment] = useState("");
|
const [comment, setComment] = useState("");
|
||||||
const [file, setFile] = useState("");
|
const [file, setFile] = useState("");
|
||||||
const [sk, setSk] = useState(generatePrivateKey());
|
const [sk, setSk] = useState(generatePrivateKey());
|
||||||
@ -65,6 +78,17 @@ const NewNoteCard: React.FC = () => {
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (refEvent && tagType && unsigned.tags.length === 0) {
|
||||||
|
const tags = tagMapping[tagType];
|
||||||
|
if (tags) {
|
||||||
|
tags.forEach(tag => unsigned.tags.push([tag, refEvent[tag === 'p' ? 'pubkey' : 'id']]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagType === 'Quote') {
|
||||||
|
setComment(comment + ' nostr:' + nip19.noteEncode(refEvent.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleDifficultyChange = (event: Event) => {
|
const handleDifficultyChange = (event: Event) => {
|
||||||
const customEvent = event as CustomEvent;
|
const customEvent = event as CustomEvent;
|
||||||
const { difficulty } = customEvent.detail;
|
const { difficulty } = customEvent.detail;
|
||||||
@ -79,15 +103,12 @@ const NewNoteCard: React.FC = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUnsigned(
|
setUnsigned(prevUnsigned => ({
|
||||||
{
|
...prevUnsigned,
|
||||||
kind: 1,
|
content: `${comment} ${file}`,
|
||||||
tags: [],
|
|
||||||
content: comment + " " + file,
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
pubkey: getPublicKey(sk),
|
pubkey: getPublicKey(sk),
|
||||||
}
|
}));
|
||||||
);
|
|
||||||
}, [comment, file]);
|
}, [comment, file]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -100,16 +121,12 @@ const NewNoteCard: React.FC = () => {
|
|||||||
setComment("");
|
setComment("");
|
||||||
setFile("");
|
setFile("");
|
||||||
setSk(generatePrivateKey());
|
setSk(generatePrivateKey());
|
||||||
setUnsigned(
|
setUnsigned(prevUnsigned => ({
|
||||||
{
|
...prevUnsigned,
|
||||||
kind: 1,
|
content: '',
|
||||||
tags: [],
|
|
||||||
content: "",
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
pubkey: getPublicKey(sk),
|
pubkey: getPublicKey(sk),
|
||||||
}
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setComment(error + " " + comment);
|
setComment(error + " " + comment);
|
||||||
}
|
}
|
||||||
|
@ -1,226 +0,0 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
|
||||||
import { useState, useMemo, useEffect } from "react";
|
|
||||||
import { ArrowUpTrayIcon, CpuChipIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
|
|
||||||
import { XCircleIcon } from '@heroicons/react/24/solid';
|
|
||||||
import { generatePrivateKey, getPublicKey, finishEvent, Event as NostrEvent } from 'nostr-tools';
|
|
||||||
import { publish } from '../../utils/relays';
|
|
||||||
import FileUpload from '../../utils/FileUpload';
|
|
||||||
import { nip19 } from 'nostr-tools';
|
|
||||||
import { renderMedia } from '../../utils/FileUpload';
|
|
||||||
|
|
||||||
|
|
||||||
const ThreadPost = ({ OPEvent, state, type }: { OPEvent: NostrEvent, state: Boolean, type: String }) => {
|
|
||||||
const { id } = useParams();
|
|
||||||
const [comment, setComment] = useState("");
|
|
||||||
const [file, setFile] = useState("");
|
|
||||||
const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || '21');
|
|
||||||
const [uploadingFile, setUploadingFile] = useState(false);
|
|
||||||
let decodeResult = nip19.decode(id as string);
|
|
||||||
|
|
||||||
const [sk, setSk] = useState(generatePrivateKey());
|
|
||||||
|
|
||||||
const [messageFromWorker, setMessageFromWorker] = useState(null);
|
|
||||||
const [doingWorkProp, setDoingWorkProp] = useState(false);
|
|
||||||
const [doingWorkProgress, setDoingWorkProgress] = useState(0);
|
|
||||||
|
|
||||||
// Initialize the worker outside of any effects
|
|
||||||
const numCores = navigator.hardwareConcurrency || 4;
|
|
||||||
|
|
||||||
const workers = useMemo(
|
|
||||||
() => Array(numCores).fill(null).map(() => new Worker(new URL("../../powWorker", import.meta.url))),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
workers.forEach((worker) => {
|
|
||||||
worker.onmessage = (event) => {
|
|
||||||
if (event.data.status === 'progress') {
|
|
||||||
console.log(`Worker progress: Checked ${event.data.currentNonce} nonces.`);
|
|
||||||
setDoingWorkProgress(event.data.currentNonce);
|
|
||||||
} else if (event.data.found) {
|
|
||||||
setMessageFromWorker(event.data.event);
|
|
||||||
// Terminate all workers once a solution is found
|
|
||||||
workers.forEach(w => w.terminate());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleDifficultyChange = (event: Event) => {
|
|
||||||
const customEvent = event as CustomEvent;
|
|
||||||
setDifficulty(customEvent.detail);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('difficultyChanged', handleDifficultyChange);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('difficultyChanged', handleDifficultyChange);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
event.preventDefault();
|
|
||||||
let id = decodeResult.data as string
|
|
||||||
|
|
||||||
workers.forEach((worker, index) => {
|
|
||||||
let tags = [];
|
|
||||||
let modifiedComment = comment + " " + file;
|
|
||||||
if (type === 'r') {
|
|
||||||
tags.push(["e", id as string])
|
|
||||||
tags.push(["p", OPEvent.pubkey])
|
|
||||||
} else if (type === 'q') {
|
|
||||||
tags.push(["q", id as string])
|
|
||||||
tags.push(["p", OPEvent.pubkey])
|
|
||||||
modifiedComment += ' nostr:' + nip19.noteEncode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
worker.postMessage({
|
|
||||||
unsigned: {
|
|
||||||
kind: 1,
|
|
||||||
tags,
|
|
||||||
content: modifiedComment,
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
|
||||||
pubkey: getPublicKey(sk),
|
|
||||||
},
|
|
||||||
difficulty,
|
|
||||||
nonceStart: index, // Each worker starts from its index
|
|
||||||
nonceStep: numCores // Each worker increments by the total number of workers
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
setComment(comment + " " + error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setDoingWorkProp(false)
|
|
||||||
if (messageFromWorker) {
|
|
||||||
try {
|
|
||||||
const signedEvent = finishEvent(messageFromWorker, sk);
|
|
||||||
publish(signedEvent);
|
|
||||||
|
|
||||||
setComment("");
|
|
||||||
setFile("");
|
|
||||||
setSk(generatePrivateKey())
|
|
||||||
setMessageFromWorker(null);
|
|
||||||
} catch (error) {
|
|
||||||
setComment(error + ' ' + comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [messageFromWorker]);
|
|
||||||
|
|
||||||
async function attachFile(file_input: File | null) {
|
|
||||||
setUploadingFile(true); // start loading
|
|
||||||
try {
|
|
||||||
if (file_input) {
|
|
||||||
const rx = await FileUpload(file_input);
|
|
||||||
setUploadingFile(false); // stop loading
|
|
||||||
if (rx.url) {
|
|
||||||
setFile(rx.url);
|
|
||||||
} else if (rx?.error) {
|
|
||||||
setFile(rx.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: unknown) {
|
|
||||||
setUploadingFile(false); // stop loading
|
|
||||||
if (error instanceof Error) {
|
|
||||||
setFile(error?.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{state && (
|
|
||||||
<form
|
|
||||||
name="post"
|
|
||||||
method="post"
|
|
||||||
encType="multipart/form-data"
|
|
||||||
className=""
|
|
||||||
onSubmit={(event) => {
|
|
||||||
handleSubmit(event);
|
|
||||||
setDoingWorkProp(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
|
|
||||||
<div id="togglePostFormLink" className="text-lg font-semibold">
|
|
||||||
{type === 'r' ? <span>Reply To Post</span> : <span>Quote Post</span>}
|
|
||||||
</div>
|
|
||||||
<div className="px-4 pt-4 flex flex-col bg-neutral-900 border border-neutral-800 rounded-lg">
|
|
||||||
<div>
|
|
||||||
<textarea
|
|
||||||
name="com"
|
|
||||||
wrap="soft"
|
|
||||||
className="shadow-lg w-full px-4 py-3 h-28 rounded-md outline-none focus:outline-none bg-neutral-800 border border-neutral-700 text-white placeholder:text-neutral-500"
|
|
||||||
placeholder='Shitpost here...'
|
|
||||||
value={comment}
|
|
||||||
onChange={(e) => setComment(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="relative">
|
|
||||||
{file !== "" && (
|
|
||||||
<button onClick={() => setFile("")}>
|
|
||||||
<XCircleIcon className="h-10 w-10 absolute shadow z-100 text-blue-500" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{renderMedia(file)}
|
|
||||||
</div>
|
|
||||||
<div className="h-14 flex items-center justify-between">
|
|
||||||
<div className="inline-flex items-center gap-2 bg-neutral-800 px-1.5 py-1 rounded-lg">
|
|
||||||
<div className="inline-flex items-center gap-1.5 text-neutral-300">
|
|
||||||
<CpuChipIcon className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
<p className="text-xs font-medium text-neutral-400">
|
|
||||||
{difficulty} PoW
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<ArrowUpTrayIcon
|
|
||||||
className="h-4 w-4 text-neutral-400 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);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{uploadingFile ? (
|
|
||||||
<div className="flex animate-spin text-sm text-gray-300">
|
|
||||||
<ArrowPathIcon className="h-4 w-4 ml-auto" />
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="h-9 inline-flex items-center justify-center px-4 bg-blue-500 hover:bg-blue-600 rounded-lg text-white font-medium text-sm"
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{doingWorkProp ? (
|
|
||||||
<div className="flex animate-pulse text-sm text-gray-300">
|
|
||||||
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
|
||||||
<span>Generating Proof-of-Work:</span>
|
|
||||||
<span>iteration {doingWorkProgress}</span>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</form>)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ThreadPost;
|
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState, useCallback } from "react";
|
||||||
import PostCard from "./Modals/Card";
|
import PostCard from "./Modals/Card";
|
||||||
import { uniqBy } from "../utils/utils"; // Assume getPow is a correct import now
|
import { uniqBy } from "../utils/otherUtils"; // Assume getPow is a correct import now
|
||||||
import { subGlobalFeed } from "../utils/subscriptions";
|
import { subGlobalFeed } from "../utils/subscriptions";
|
||||||
import { verifyPow } from "../utils/mine";
|
import { verifyPow } from "../utils/mine";
|
||||||
import { Event } from "nostr-tools";
|
import { Event } from "nostr-tools";
|
||||||
|
@ -2,12 +2,12 @@ import CardContainer from "./CardContainer";
|
|||||||
import { FolderIcon, CpuChipIcon } from "@heroicons/react/24/outline";
|
import { FolderIcon, CpuChipIcon } from "@heroicons/react/24/outline";
|
||||||
import { parseContent } from "../../utils/content";
|
import { parseContent } from "../../utils/content";
|
||||||
import { Event, nip19 } from "nostr-tools";
|
import { Event, nip19 } from "nostr-tools";
|
||||||
import { getMetadata } from "../../utils/utils";
|
import { getMetadata } from "../../utils/otherUtils";
|
||||||
import ContentPreview from "./CardModals/TextModal";
|
import ContentPreview from "./CardModals/TextModal";
|
||||||
import { renderMedia } from "../../utils/FileUpload";
|
import { renderMedia } from "../../utils/FileUpload";
|
||||||
import { getIconFromHash } from "../../utils/deterministicProfileIcon";
|
import { getIconFromHash } from "../../utils/deterministicProfileIcon";
|
||||||
import { verifyPow } from "../../utils/mine";
|
import { verifyPow } from "../../utils/mine";
|
||||||
import { uniqBy } from "../../utils/utils";
|
import { uniqBy } from "../../utils/otherUtils";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
const timeUnits = [
|
const timeUnits = [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { parseContent } from "../../../utils/content";
|
import { parseContent } from "../../../utils/content";
|
||||||
import { Event } from "nostr-tools";
|
import { Event } from "nostr-tools";
|
||||||
import { getMetadata, uniqBy } from "../../../utils/utils";
|
import { getMetadata, uniqBy } from "../../../utils/otherUtils";
|
||||||
import ContentPreview from "./TextModal";
|
import ContentPreview from "./TextModal";
|
||||||
import { renderMedia } from "../../../utils/FileUpload";
|
import { renderMedia } from "../../../utils/FileUpload";
|
||||||
|
|
||||||
|
@ -3,22 +3,21 @@ import { useState } from "react";
|
|||||||
import { Event, nip19 } from "nostr-tools"
|
import { Event, nip19 } from "nostr-tools"
|
||||||
import { subNote, subNotesOnce } from '../utils/subscriptions';
|
import { subNote, subNotesOnce } from '../utils/subscriptions';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { uniqBy } from '../utils/utils';
|
import { uniqBy } from '../utils/otherUtils';
|
||||||
import { DocumentTextIcon, FolderPlusIcon } from '@heroicons/react/24/outline';
|
import { DocumentTextIcon, FolderPlusIcon } from '@heroicons/react/24/outline';
|
||||||
import { getPow } from '../utils/mine';
|
import { getPow } from '../utils/mine';
|
||||||
import ThreadPost from './Forms/ThreadPost';
|
|
||||||
import PostCard from './Modals/Card';
|
import PostCard from './Modals/Card';
|
||||||
import Placeholder from './Modals/Placeholder';
|
import Placeholder from './Modals/Placeholder';
|
||||||
|
import NewNoteCard from './Forms/PostFormCard';
|
||||||
|
|
||||||
|
type PostType = "" | "Reply" | "Quote" | undefined;
|
||||||
const difficulty = 20
|
|
||||||
|
|
||||||
const Thread = () => {
|
const Thread = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [events, setEvents] = useState<Event[]>([]); // Initialize state
|
const [events, setEvents] = useState<Event[]>([]); // Initialize state
|
||||||
const [OPEvent, setOPEvent] = useState<Event>()
|
const [OPEvent, setOPEvent] = useState<Event>()
|
||||||
const [showForm, setShowForm] = useState(false);
|
const [showForm, setShowForm] = useState(false);
|
||||||
const [postType, setPostType] = useState("");
|
const [postType, setPostType] = useState<PostType>("");
|
||||||
const [hasRun, setHasRun] = useState(false);
|
const [hasRun, setHasRun] = useState(false);
|
||||||
const [preOPEvents, setPreOPEvents] = useState(['']);
|
const [preOPEvents, setPreOPEvents] = useState(['']);
|
||||||
const [sortByTime, setSortByTime] = useState(true);
|
const [sortByTime, setSortByTime] = useState(true);
|
||||||
@ -48,7 +47,12 @@ const Thread = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasRun && events.length > 0) {
|
if (!hasRun && events.length > 0) {
|
||||||
let OPEvent = events.find(e => e.id === hexID);
|
let OPEvent = uniqEvents[0];
|
||||||
|
setOPEvent(OPEvent);
|
||||||
|
|
||||||
|
if (OPEvent && OPEvent.id !== hexID) {
|
||||||
|
OPEvent = events.find(e => e.id === hexID) as Event;
|
||||||
|
}
|
||||||
|
|
||||||
if (OPEvent) {
|
if (OPEvent) {
|
||||||
setOPEvent(OPEvent);
|
setOPEvent(OPEvent);
|
||||||
@ -119,7 +123,7 @@ const Thread = () => {
|
|||||||
className="h-5 w-5 text-gray-200"
|
className="h-5 w-5 text-gray-200"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowForm(prevShowForm => !prevShowForm);
|
setShowForm(prevShowForm => !prevShowForm);
|
||||||
setPostType('r');
|
setPostType('Reply');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -127,13 +131,13 @@ const Thread = () => {
|
|||||||
className="h-5 w-5 text-gray-200"
|
className="h-5 w-5 text-gray-200"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowForm(prevShowForm => !prevShowForm);
|
setShowForm(prevShowForm => !prevShowForm);
|
||||||
setPostType('q');
|
setPostType('Quote');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full px-4 sm:px-0 sm:max-w-xl mx-auto my-2">
|
{(showForm && postType) && <div className="w-full px-4 sm:px-0 sm:max-w-xl mx-auto my-2">
|
||||||
<ThreadPost OPEvent={uniqEvents[0]} state={showForm} type={postType} />
|
<NewNoteCard refEvent={uniqEvents[0]} tagType={postType}/>
|
||||||
</div>
|
</div>}
|
||||||
<div className="flex items-center justify-center w-full py-4">
|
<div className="flex items-center justify-center w-full py-4">
|
||||||
<label htmlFor="toggleB" className="flex items-center cursor-pointer">
|
<label htmlFor="toggleB" className="flex items-center cursor-pointer">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
import {
|
|
||||||
type Event as NostrEvent,
|
|
||||||
generatePrivateKey,
|
|
||||||
getEventHash,
|
|
||||||
getPublicKey,
|
|
||||||
signEvent,
|
|
||||||
} from "nostr-tools";
|
|
||||||
|
|
||||||
export const handleThreadSubmit = async (comment: string, tags: []) => {
|
|
||||||
if (!comment) {
|
|
||||||
alert("no message provided");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newEvent: NostrEvent = {
|
|
||||||
id: 'null',
|
|
||||||
content: comment,
|
|
||||||
kind: 1,
|
|
||||||
tags,
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
|
||||||
pubkey: 'null',
|
|
||||||
sig: 'null',
|
|
||||||
};
|
|
||||||
|
|
||||||
let sk = generatePrivateKey();
|
|
||||||
|
|
||||||
newEvent.pubkey = getPublicKey(sk);
|
|
||||||
newEvent.id = getEventHash(newEvent);
|
|
||||||
newEvent.sig = signEvent(newEvent, sk);
|
|
||||||
|
|
||||||
return newEvent
|
|
||||||
};
|
|
@ -1,42 +0,0 @@
|
|||||||
import { useMemo, useEffect } from 'react';
|
|
||||||
|
|
||||||
interface Dispatch {
|
|
||||||
(arg: { type: string, payload?: any }): void
|
|
||||||
}
|
|
||||||
|
|
||||||
const useWorkers = (dispatch: Dispatch) => {
|
|
||||||
const numCores = navigator.hardwareConcurrency || 4;
|
|
||||||
|
|
||||||
const workers = useMemo(
|
|
||||||
() => Array(numCores).fill(null).map(() => new Worker(new URL("../../powWorker", import.meta.url))),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
workers.forEach((worker) => {
|
|
||||||
worker.onmessage = (event) => {
|
|
||||||
if (event.data.status === 'progress') {
|
|
||||||
dispatch({ type: 'SET_WORK_PROGRESS', payload: event.data.currentNonce });
|
|
||||||
} else if (event.data.found) {
|
|
||||||
dispatch({ type: 'SET_MESSAGE_FROM_WORKER', payload: event.data.event });
|
|
||||||
workers.forEach(w => w.terminate());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleDifficultyChange = (event: Event) => {
|
|
||||||
const customEvent = event as CustomEvent;
|
|
||||||
dispatch({ type: 'SET_DIFFICULTY', payload: customEvent.detail });
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('difficultyChanged', handleDifficultyChange);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('difficultyChanged', handleDifficultyChange);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return workers;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useWorkers;
|
|
Loading…
Reference in New Issue
Block a user