diff --git a/client/package.json b/client/package.json index 57c3848..da73376 100644 --- a/client/package.json +++ b/client/package.json @@ -5,6 +5,7 @@ "dependencies": { "@emoji-mart/data": "^1.1.2", "@emoji-mart/react": "^1.1.1", + "@headlessui/react": "latest", "@heroicons/react": "^2.0.18", "@types/jest": "^27.5.2", "@types/node": "^17.0.45", diff --git a/client/src/components/Forms/PostFormCard.tsx b/client/src/components/Forms/PostFormCard.tsx index afc450f..dd504be 100644 --- a/client/src/components/Forms/PostFormCard.tsx +++ b/client/src/components/Forms/PostFormCard.tsx @@ -11,37 +11,7 @@ import { publish } from "../../utils/relays"; import { renderMedia, attachFile } from "../../utils/FileUpload"; import { EmojiPicker } from "./Emojis/emoji-picker"; import customEmojis from './custom_emojis.json'; - -const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: string, deps: any[]) => { - const [messageFromWorker, setMessageFromWorker] = useState(null); - const [doingWorkProgress, setDoingWorkProgress] = useState(0); - - const startWork = () => { - const workers = Array(numCores).fill(null).map(() => new Worker(new URL("../../powWorker", import.meta.url))); - - workers.forEach((worker, index) => { - 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()); - } - }; - - worker.postMessage({ - unsigned, - difficulty, - nonceStart: index, // Each worker starts from its index - nonceStep: numCores // Each worker increments by the total number of workers - }); - }); - }; - - return { startWork, messageFromWorker, doingWorkProgress }; -}; +import { useSubmitForm } from "./handleSubmit"; interface FormProps { refEvent?: NostrEvent; @@ -60,26 +30,18 @@ const NewNoteCard = ({ const ref = useRef(null); const [comment, setComment] = useState(""); const [file, setFile] = useState(""); - const [sk, setSk] = useState(generatePrivateKey()); const [unsigned, setUnsigned] = useState({ kind: 1, tags: [], content: "", created_at: Math.floor(Date.now() / 1000), - pubkey: getPublicKey(sk), + pubkey: "", }); const [difficulty, setDifficulty] = useState( localStorage.getItem("difficulty") || "21" ); const [fileSizeError, setFileSizeError] = useState(false); - const [uploadingFile, setUploadingFile] = useState(false); - const [doingWorkProp, setDoingWorkProp] = useState(false); - - // Initialize the worker outside of any effects - const numCores = navigator.hardwareConcurrency || 4; - - const { startWork, messageFromWorker, doingWorkProgress } = useWorkers(numCores, unsigned, difficulty, [unsigned]); useEffect(() => { if (refEvent && tagType && unsigned.tags.length === 0) { @@ -111,31 +73,21 @@ const NewNoteCard = ({ ...prevUnsigned, content: `${comment} ${file}`, created_at: Math.floor(Date.now() / 1000), - pubkey: getPublicKey(sk), })); }, [comment, file]); - useEffect(() => { - setDoingWorkProp(false); - if (messageFromWorker) { - try { - const signedEvent = finishEvent(messageFromWorker, sk); - publish(signedEvent); + const { handleSubmit: originalHandleSubmit, doingWorkProp, doingWorkProgress } = useSubmitForm(unsigned, difficulty); - setComment(""); - setFile(""); - setSk(generatePrivateKey()); - setUnsigned(prevUnsigned => ({ - ...prevUnsigned, - content: '', - created_at: Math.floor(Date.now() / 1000), - pubkey: getPublicKey(sk), - })); - } catch (error) { - setComment(error + " " + comment); - } - } - }, [messageFromWorker]); + const handleSubmit = async (event: React.FormEvent) => { + await originalHandleSubmit(event); + setComment(""); + setFile(""); + setUnsigned(prevUnsigned => ({ + ...prevUnsigned, + content: '', + created_at: Math.floor(Date.now() / 1000) + })); + }; //Emoji stuff const emojiRef = useRef(null); @@ -180,11 +132,7 @@ const NewNoteCard = ({ method="post" encType="multipart/form-data" className="" - onSubmit={(event) => { - event.preventDefault(); - startWork(); - setDoingWorkProp(true); - }} + onSubmit={handleSubmit} >
@@ -276,8 +224,8 @@ const NewNoteCard = ({ {doingWorkProp ? (
- Generating Proof-of-Work: - iteration {doingWorkProgress} + Generating Proof-of-Work. + {doingWorkProgress && Current iteration {doingWorkProgress}}
) : null}
diff --git a/client/src/components/Forms/handleSubmit.ts b/client/src/components/Forms/handleSubmit.ts new file mode 100644 index 0000000..7019741 --- /dev/null +++ b/client/src/components/Forms/handleSubmit.ts @@ -0,0 +1,98 @@ +import { useState, useEffect } from "react"; +import { generatePrivateKey, getPublicKey, finishEvent, UnsignedEvent } from "nostr-tools"; +import { publish } from "../../utils/relays"; + +const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: string, deps: any[]) => { + const [messageFromWorker, setMessageFromWorker] = useState(null); + const [doingWorkProgress, setDoingWorkProgress] = useState(0); + + const startWork = () => { + const workers = Array(numCores).fill(null).map(() => new Worker(new URL("../../powWorker", import.meta.url))); + + workers.forEach((worker, index) => { + 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()); + } + }; + + worker.postMessage({ + unsigned, + difficulty, + nonceStart: index, // Each worker starts from its index + nonceStep: numCores // Each worker increments by the total number of workers + }); + }); + }; + + return { startWork, messageFromWorker, doingWorkProgress }; +}; + +export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => { + const [doingWorkProp, setDoingWorkProp] = useState(false); + const [sk, setSk] = useState(generatePrivateKey()); + const unsignedWithPubkey = { ...unsigned, pubkey: getPublicKey(sk) }; + const powServer = useState(localStorage.getItem('powserver') || ''); + const [unsignedPoWEvent, setUnsignedPoWEvent] = useState() + + // Initialize the worker outside of any effects + const numCores = navigator.hardwareConcurrency || 4; + + const { startWork, messageFromWorker, doingWorkProgress } = useWorkers(numCores, unsignedWithPubkey, difficulty, [unsignedWithPubkey]); + + console.log(powServer[0]) + + useEffect(() => { + if (unsignedPoWEvent) { + setDoingWorkProp(false); + const signedEvent = finishEvent(unsignedPoWEvent, sk); + publish(signedEvent); + } + }, [unsignedPoWEvent]); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setDoingWorkProp(true); + console.log(powServer[0]) + if (powServer[0]) { + const inEventFormat = { ...unsignedWithPubkey, sig: "" }; + const powRequest = { + req_event: inEventFormat, + difficulty: difficulty + }; + + fetch(`${powServer[0]}/powgen`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(powRequest) + }) + .then(response => response.json()) + .then(data => { + console.log(data); + // handle the response data + setUnsignedPoWEvent(data.event) + }) + .catch(error => { + console.error('Error:', error); + }); + + } else { + startWork(); + } + }; + + useEffect(() => { + if (messageFromWorker) { + setUnsignedPoWEvent(messageFromWorker); + } + }, [messageFromWorker]); + + return { handleSubmit, doingWorkProp, doingWorkProgress }; +}; \ No newline at end of file diff --git a/client/src/components/Modals/CheckMobile/CheckMobile.tsx b/client/src/components/Modals/CheckMobile/CheckMobile.tsx index 4233ac5..1244d12 100644 --- a/client/src/components/Modals/CheckMobile/CheckMobile.tsx +++ b/client/src/components/Modals/CheckMobile/CheckMobile.tsx @@ -1,6 +1,8 @@ import React, { useState, useEffect } from 'react'; import { XMarkIcon } from "@heroicons/react/24/solid"; import { ArrowUpOnSquareIcon, PlusCircleIcon } from '@heroicons/react/24/outline'; +import { Dialog, Transition } from '@headlessui/react'; +import { Fragment } from 'react'; declare global { interface Navigator { @@ -44,7 +46,21 @@ const AddToHomeScreenPrompt: React.FC = () => { } return ( -
+ + setInMobileBrowser(false)} + > +
+ + +
Stay Wired @@ -65,8 +81,10 @@ const AddToHomeScreenPrompt: React.FC = () => { -
-
+
+
+ + ); }; diff --git a/client/src/components/Settings.tsx b/client/src/components/Settings.tsx index 9fc43e3..8a430de 100644 --- a/client/src/components/Settings.tsx +++ b/client/src/components/Settings.tsx @@ -1,25 +1,61 @@ -import React, { useEffect, useState } from 'react'; -// import {powEvent} from './system'; -// import {publish} from './relays'; -import { addRelay } from '../utils/relays'; +import React, { useState } from 'react'; import { CpuChipIcon } from '@heroicons/react/24/outline'; +type TestResponse = { + timeTaken: string; + hashrate: string; +}; + const Settings = () => { const [filterDifficulty, setFilterDifficulty] = useState(localStorage.getItem('filterDifficulty') || 20); const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || 21); + const [showAdvancedSettings, setShowAdvancedSettings] = useState(false); + const [powServer, setPowServer] = useState(localStorage.getItem('powserver') || ''); + const [testDiff, setTestDiff] = useState('21') + const [testResult, setTestResult] = useState() const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); localStorage.setItem('filterDifficulty', String(filterDifficulty)); localStorage.setItem('difficulty', String(difficulty)); + localStorage.setItem('powserver', String(powServer)); const eventData = { difficulty: String(difficulty), filterDifficulty: String(filterDifficulty), + powServer: String(powServer), }; const event = new CustomEvent('settingsChanged', { detail: eventData }); window.dispatchEvent(event); }; + console.log(powServer) + + const handleTest = () => { + setTestResult({ timeTaken: '...', hashrate: '...' }); + console.log(powServer[0]) + if (powServer[0]) { + const testRequest = { + Difficulty: testDiff + }; + + fetch(`${powServer}/test`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(testRequest) + }) + .then(response => response.json()) + .then(data => { + console.log(data); + // handle the response data + setTestResult(data) + }) + .catch(error => { + console.error('Error:', error); + }); + } + }; return (
@@ -56,7 +92,47 @@ const Settings = () => { />
- + {testResult && ( + Time: {testResult.timeTaken}s with a hashrate of {testResult.hashrate} + )} +
+ + )} + + @@ -76,7 +152,7 @@ const Settings = () => {
Found a bug? dm me: doot or smolgrrr@protonmail.com - +