mirror of
https://github.com/smolgrrr/TAO.git
synced 2024-09-20 01:11:25 +00:00
penis
This commit is contained in:
parent
1f00204ab6
commit
610256fbfa
@ -5,7 +5,6 @@ import Settings from './components/Settings';
|
|||||||
import SwipeableViews from 'react-swipeable-views';
|
import SwipeableViews from 'react-swipeable-views';
|
||||||
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
||||||
import Thread from './components/Thread/Thread';
|
import Thread from './components/Thread/Thread';
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [index, setIndex] = React.useState(1);
|
const [index, setIndex] = React.useState(1);
|
||||||
|
@ -8,6 +8,7 @@ import { uniqBy } from '../utils/utils';
|
|||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const [events, setEvents] = useState<Event[]>([]);
|
const [events, setEvents] = useState<Event[]>([]);
|
||||||
|
const [filterDifficulty, setFilterDifficulty] = useState(localStorage.getItem('filterDifficulty') || '12');
|
||||||
|
|
||||||
const onEvent = (event: Event) => {
|
const onEvent = (event: Event) => {
|
||||||
setEvents((prevEvents) => [...prevEvents, event]);
|
setEvents((prevEvents) => [...prevEvents, event]);
|
||||||
@ -16,15 +17,27 @@ const Home = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
subGlobalFeed(onEvent);
|
subGlobalFeed(onEvent);
|
||||||
// If you eventually need a cleanup function, put it here
|
// If you eventually need a cleanup function, put it here
|
||||||
|
|
||||||
|
const handleDifficultyChange = (event: any) => {
|
||||||
|
const customEvent = event as CustomEvent;
|
||||||
|
const { difficulty, filterDifficulty } = customEvent.detail;
|
||||||
|
setFilterDifficulty(filterDifficulty);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('difficultyChanged', handleDifficultyChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('difficultyChanged', handleDifficultyChange);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const uniqEvents = events.length > 0 ? uniqBy(events, "id") : [];
|
const uniqEvents = events.length > 0 ? uniqBy(events, "id") : [];
|
||||||
|
|
||||||
const filteredAndSortedEvents = uniqEvents
|
const filteredAndSortedEvents = uniqEvents
|
||||||
.filter(event =>
|
.filter(event =>
|
||||||
getPow(event.id) > 5 &&
|
getPow(event.id) > Math.ceil(Number(filterDifficulty)/4) &&
|
||||||
event.kind === 1 &&
|
event.kind === 1 &&
|
||||||
!event.tags.some(tag => tag[0] === 'p')
|
!event.tags.some(tag => tag[0] === 'e')
|
||||||
)
|
)
|
||||||
.sort((a, b) => (b.created_at as any) - (a.created_at as any));
|
.sort((a, b) => (b.created_at as any) - (a.created_at as any));
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@ const ContentPreview = ({ key, comment }: { key: string, comment: string }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// const findUrl = comment.match(/\bhttps?:\/\/\S+/gi);
|
const findUrl = comment.match(/\bhttps?:\/\/\S+/gi);
|
||||||
// if (findUrl && findUrl.length > 0) {
|
if (findUrl && findUrl.length > 0) {
|
||||||
// setUrl(findUrl[0])
|
setUrl(findUrl[0])
|
||||||
// setFinalComment(finalComment.replace(findUrl[0], '').trim())
|
setFinalComment(finalComment.replace(findUrl[0], '').trim())
|
||||||
// }
|
}
|
||||||
|
|
||||||
const match = comment.match(/\bnostr:([a-z0-9]+)/i);
|
const match = comment.match(/\bnostr:([a-z0-9]+)/i);
|
||||||
const nostrQuoteID = match && match[1];
|
const nostrQuoteID = match && match[1];
|
||||||
|
@ -2,59 +2,73 @@ import CardContainer from './CardContainer';
|
|||||||
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
|
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
|
||||||
import { useState, useEffect, useMemo } from 'react';
|
import { useState, useEffect, useMemo } from 'react';
|
||||||
import { generatePrivateKey, getPublicKey, finishEvent } from 'nostr-tools';
|
import { generatePrivateKey, getPublicKey, finishEvent } from 'nostr-tools';
|
||||||
import { minePow } from '../../utils/mine';
|
|
||||||
import { publish } from '../../utils/relays';
|
import { publish } from '../../utils/relays';
|
||||||
import NostrImg from '../../utils/ImgUpload';
|
import NostrImg from '../../utils/ImgUpload';
|
||||||
|
|
||||||
const difficulty = 20
|
|
||||||
|
|
||||||
const NewThreadCard: React.FC = () => {
|
const NewThreadCard: React.FC = () => {
|
||||||
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());
|
||||||
|
const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || '21');
|
||||||
|
|
||||||
|
|
||||||
const [messageFromWorker, setMessageFromWorker] = useState(null);
|
const [messageFromWorker, setMessageFromWorker] = useState(null);
|
||||||
// Initialize the worker outside of any effects
|
const [doingWorkProp, setDoingWorkProp] = useState(false);
|
||||||
|
// Initialize the worker outside of any effects
|
||||||
const worker = useMemo(() => new Worker(new URL('../../powWorker', import.meta.url)), []);
|
const worker = useMemo(() => new Worker(new URL('../../powWorker', import.meta.url)), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
worker.onmessage = (event) => {
|
worker.onmessage = (event) => {
|
||||||
setMessageFromWorker(event.data);
|
setMessageFromWorker(event.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDifficultyChange = (event: Event) => {
|
||||||
|
const customEvent = event as CustomEvent;
|
||||||
|
const { difficulty, filterDifficulty } = customEvent.detail;
|
||||||
|
setDifficulty(difficulty);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('difficultyChanged', handleDifficultyChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('difficultyChanged', handleDifficultyChange);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
worker.postMessage({
|
worker.postMessage({
|
||||||
unsigned: {
|
unsigned: {
|
||||||
kind: 1,
|
kind: 1,
|
||||||
tags: [],
|
tags: [],
|
||||||
content: comment + " " + file,
|
content: comment + " " + file,
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
pubkey: getPublicKey(sk),
|
pubkey: getPublicKey(sk),
|
||||||
},
|
},
|
||||||
difficulty
|
difficulty
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setDoingWorkProp(false)
|
||||||
if (messageFromWorker) {
|
if (messageFromWorker) {
|
||||||
try {
|
try {
|
||||||
const signedEvent = finishEvent(messageFromWorker, sk);
|
const signedEvent = finishEvent(messageFromWorker, sk);
|
||||||
publish(signedEvent);
|
publish(signedEvent);
|
||||||
|
|
||||||
setComment("");
|
setComment("");
|
||||||
setFile("");
|
setFile("");
|
||||||
setSk(generatePrivateKey())
|
setSk(generatePrivateKey());
|
||||||
|
setMessageFromWorker(null);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
worker.terminate();
|
worker.terminate();
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setComment(error + ' ' + comment);
|
setComment(error + ' ' + comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [messageFromWorker]);
|
}, [messageFromWorker]);
|
||||||
|
|
||||||
async function attachFile(file_input: File | null) {
|
async function attachFile(file_input: File | null) {
|
||||||
try {
|
try {
|
||||||
@ -76,13 +90,15 @@ const NewThreadCard: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CardContainer>
|
<CardContainer>
|
||||||
{/* <p>Message from worker: {messageFromWorker}</p> */}
|
|
||||||
<form
|
<form
|
||||||
name="post"
|
name="post"
|
||||||
method="post"
|
method="post"
|
||||||
encType="multipart/form-data"
|
encType="multipart/form-data"
|
||||||
className=""
|
className=""
|
||||||
onSubmit={handleSubmit}
|
onSubmit={(event) => {
|
||||||
|
handleSubmit(event);
|
||||||
|
setDoingWorkProp(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
|
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
|
||||||
<div id="togglePostFormLink" className="text-lg font-semibold">
|
<div id="togglePostFormLink" className="text-lg font-semibold">
|
||||||
@ -99,14 +115,14 @@ const NewThreadCard: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{file !== "" && (
|
{file !== "" && (
|
||||||
<div className="file m-0.5">
|
<div className="file m-0.5">
|
||||||
<img
|
<img
|
||||||
src={file}
|
src={file}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@ -132,6 +148,12 @@ const NewThreadCard: React.FC = () => {
|
|||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{doingWorkProp ? (
|
||||||
|
<div className='flex animate-pulse text-sm text-gray-300'>
|
||||||
|
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
||||||
|
<span>Working...</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div id="postFormError" className="text-red-500" />
|
<div id="postFormError" className="text-red-500" />
|
||||||
</form>
|
</form>
|
||||||
</CardContainer>
|
</CardContainer>
|
||||||
|
@ -10,6 +10,13 @@ const Settings = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
localStorage.setItem('filterDifficulty', String(filterDifficulty));
|
localStorage.setItem('filterDifficulty', String(filterDifficulty));
|
||||||
localStorage.setItem('difficulty', String(difficulty));
|
localStorage.setItem('difficulty', String(difficulty));
|
||||||
|
|
||||||
|
const eventData = {
|
||||||
|
difficulty: String(difficulty),
|
||||||
|
filterDifficulty: String(filterDifficulty),
|
||||||
|
};
|
||||||
|
const event = new CustomEvent('settingsChanged', { detail: eventData });
|
||||||
|
window.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,53 +1,94 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useState } from "react";
|
import { useState, useMemo, useEffect } from "react";
|
||||||
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
|
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
|
||||||
import { generatePrivateKey, getPublicKey, finishEvent } from 'nostr-tools';
|
import { generatePrivateKey, getPublicKey, finishEvent } from 'nostr-tools';
|
||||||
import { minePow } from '../../utils/mine';
|
|
||||||
import { publish } from '../../utils/relays';
|
import { publish } from '../../utils/relays';
|
||||||
import NostrImg from '../../utils/ImgUpload';
|
import NostrImg from '../../utils/ImgUpload';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
|
|
||||||
|
|
||||||
const difficulty = 25
|
|
||||||
|
|
||||||
const ThreadPost = ({ state, type }: { state: Boolean, type: String }) => {
|
const ThreadPost = ({ state, type }: { state: Boolean, type: String }) => {
|
||||||
const { id} = useParams();
|
const { id } = useParams();
|
||||||
const [comment, setComment] = useState("");
|
const [comment, setComment] = useState("");
|
||||||
const [file, setFile] = useState("");
|
const [file, setFile] = useState("");
|
||||||
|
const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || '21');
|
||||||
|
|
||||||
let decodeResult = nip19.decode(id as string);
|
let decodeResult = nip19.decode(id as string);
|
||||||
|
|
||||||
|
const [sk, setSk] = useState(generatePrivateKey());
|
||||||
|
|
||||||
|
const [messageFromWorker, setMessageFromWorker] = useState(null);
|
||||||
|
const [doingWorkProp, setDoingWorkProp] = useState(false);
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
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>) => {
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let sk = generatePrivateKey();
|
|
||||||
let id = decodeResult.data as string
|
let id = decodeResult.data as string
|
||||||
|
|
||||||
let tags = [];
|
let tags = [];
|
||||||
|
let modifiedComment = comment + " " + file;
|
||||||
if (type === 'r') {
|
if (type === 'r') {
|
||||||
tags.push(["e", id as string])
|
tags.push(["e", id as string])
|
||||||
} else if (type === 'q') {
|
} else if (type === 'q') {
|
||||||
tags.push(["q", id as string])
|
tags.push(["q", id as string])
|
||||||
setComment(comment + ' nostr:' + id)
|
modifiedComment += ' nostr:' + nip19.noteEncode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const event = minePow({
|
worker.postMessage({
|
||||||
kind: 1,
|
unsigned: {
|
||||||
tags,
|
kind: 1,
|
||||||
content: comment + " " + file,
|
tags,
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
content: modifiedComment,
|
||||||
pubkey: getPublicKey(sk),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
}, difficulty);
|
pubkey: getPublicKey(sk),
|
||||||
|
}, difficulty
|
||||||
const signedEvent = finishEvent(event, sk);
|
});
|
||||||
await publish(signedEvent);
|
|
||||||
console.log(signedEvent.id);
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setComment(comment + " " + error);
|
setComment(comment + " " + error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDoingWorkProp(false)
|
||||||
|
if (messageFromWorker) {
|
||||||
|
try {
|
||||||
|
const signedEvent = finishEvent(messageFromWorker, sk);
|
||||||
|
publish(signedEvent);
|
||||||
|
|
||||||
|
setComment("");
|
||||||
|
setFile("");
|
||||||
|
setSk(generatePrivateKey())
|
||||||
|
setMessageFromWorker(null);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
worker.terminate();
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
setComment(error + ' ' + comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [messageFromWorker]);
|
||||||
|
|
||||||
async function attachFile(file_input: File | null) {
|
async function attachFile(file_input: File | null) {
|
||||||
try {
|
try {
|
||||||
if (file_input) {
|
if (file_input) {
|
||||||
@ -74,7 +115,10 @@ const ThreadPost = ({ state, type }: { state: Boolean, type: String }) => {
|
|||||||
method="post"
|
method="post"
|
||||||
encType="multipart/form-data"
|
encType="multipart/form-data"
|
||||||
className=""
|
className=""
|
||||||
onSubmit={handleSubmit}
|
onSubmit={(event) => {
|
||||||
|
handleSubmit(event);
|
||||||
|
setDoingWorkProp(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
|
<input type="hidden" name="MAX_FILE_SIZE" defaultValue={4194304} />
|
||||||
<div id="togglePostFormLink" className="text-lg font-semibold">
|
<div id="togglePostFormLink" className="text-lg font-semibold">
|
||||||
@ -124,6 +168,12 @@ const ThreadPost = ({ state, type }: { state: Boolean, type: String }) => {
|
|||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{doingWorkProp ? (
|
||||||
|
<div className='flex animate-pulse text-sm text-gray-300'>
|
||||||
|
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
||||||
|
<span>Working...</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div id="postFormError" className="text-red-500" />
|
<div id="postFormError" className="text-red-500" />
|
||||||
</form>)}
|
</form>)}
|
||||||
</>
|
</>
|
||||||
|
32
client/src/utils/postNote.ts
Normal file
32
client/src/utils/postNote.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user