add reposts

This commit is contained in:
smolgrrr 2023-12-03 20:48:50 +11:00
parent a525e4a3e0
commit d3d81578c2
7 changed files with 192 additions and 16 deletions

View File

@ -0,0 +1,85 @@
import {
CpuChipIcon
} from "@heroicons/react/24/outline";
import { useState, useEffect } from "react";
import { UnsignedEvent, Event as NostrEvent, nip19 } from "nostr-tools";
import { useSubmitForm } from "./handleSubmit";
import "./Form.css";
interface FormProps {
refEvent: NostrEvent;
}
const RepostNote = ({
refEvent
}: FormProps) => {
const [difficulty, setDifficulty] = useState(
localStorage.getItem("difficulty") || "21"
);
const [unsigned] = useState<UnsignedEvent>({
kind: 6,
tags: [
['e', refEvent.id, 'wss://relay.damus.io'],
['p', refEvent.pubkey]
],
content: JSON.stringify(refEvent),
created_at: Math.floor(Date.now() / 1000),
pubkey: "",
});
useEffect(() => {
const handleDifficultyChange = (event: Event) => {
const customEvent = event as CustomEvent;
const { difficulty } = customEvent.detail;
setDifficulty(difficulty);
};
window.addEventListener("difficultyChanged", handleDifficultyChange);
return () => {
window.removeEventListener("difficultyChanged", handleDifficultyChange);
};
}, []);
const { handleSubmit, doingWorkProp, doingWorkProgress } = useSubmitForm(unsigned, difficulty);
return (
<form
name="post"
method="post"
encType="multipart/form-data"
className=""
onSubmit={handleSubmit}
>
<div className="px-4 flex flex-col rounded-lg">
<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>
<button
type="submit"
className={`bg-black border h-9 inline-flex items-center justify-center px-4 rounded-lg text-white font-medium text-sm ${doingWorkProp ? 'cursor-not-allowed' : ''}`}
disabled={doingWorkProp}
>
Submit
</button>
</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>
{doingWorkProgress && <span>Current iteration {doingWorkProgress}</span>}
</div>
) : null}
<div id="postFormError" className="text-red-500" />
</form>
);
};
export default RepostNote;

View File

@ -45,8 +45,6 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => {
const { startWork, messageFromWorker, doingWorkProgress } = useWorkers(numCores, unsignedWithPubkey, difficulty, [unsignedWithPubkey]);
console.log(powServer[0])
useEffect(() => {
if (unsignedPoWEvent) {
setDoingWorkProp(false);

View File

@ -1,10 +1,11 @@
import { useEffect, useState, useCallback } from "react";
import PostCard from "./Modals/Card";
import PostCard from "./Modals/NoteCard";
import { uniqBy } from "../utils/otherUtils"; // Assume getPow is a correct import now
import { subGlobalFeed } from "../utils/subscriptions";
import { verifyPow } from "../utils/mine";
import { Event } from "nostr-tools";
import NewNoteCard from "./Forms/PostFormCard";
import RepostCard from "./Modals/RepostCard";
const DEFAULT_DIFFICULTY = 20;
@ -29,8 +30,8 @@ const Home = () => {
const postEvents = uniqEvents
.filter((event) =>
verifyPow(event) >= Number(filterDifficulty) &&
event.kind === 1 &&
!event.tags.some((tag) => tag[0] === "e")
event.kind !== 0 &&
(event.kind !== 1 || !event.tags.some((tag) => tag[0] === "e"))
)
const sortedEvents = [...postEvents].sort((a, b) =>
@ -49,6 +50,11 @@ const Home = () => {
return uniqEvents.filter((e) => e.tags.some((tag) => tag[0] === "e" && tag[1] === event.id)).length;
};
useEffect(() => {
const kind6Events = sortedEvents.filter(event => event.kind === 6);
console.log('Kind 6 events:', kind6Events);
}, [uniqEvents]);
// Render the component
return (
<main className="text-white mb-20">
@ -66,7 +72,7 @@ const Home = () => {
onChange={toggleSort}
/>
<div className="block bg-gray-600 w-8 h-4 rounded-full"></div>
<div className={`dot absolute left-1 top-0.5 bg-white w-3 h-3 rounded-full transition ${sortByTime ? 'transform translate-x-full bg-blue-400' : '' }`} ></div>
<div className={`dot absolute left-1 top-0.5 bg-white w-3 h-3 rounded-full transition ${sortByTime ? 'transform translate-x-full bg-blue-400' : ''}`} ></div>
</div>
<div className={`ml-2 text-neutral-500 text-sm ${sortByTime ? 'text-neutral-500' : ''}`}>
{sortByTime ? 'Time' : 'PoW'}
@ -75,12 +81,16 @@ const Home = () => {
</div>
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4 p-4">
{sortedEvents.map((event) => (
event.kind === 1 ?
<PostCard
key={event.id}
event={event}
metadata={getMetadataEvent(event)}
replyCount={countReplies(event)}
/>
:
<RepostCard
event={event}
/>
))}
</div>
</main>

View File

@ -0,0 +1,67 @@
import CardContainer from "./CardContainer";
import { CpuChipIcon, ArrowPathRoundedSquareIcon } from "@heroicons/react/24/outline";
import { parseContent } from "../../utils/content";
import { Event, nip19 } from "nostr-tools";
import { getMetadata } from "../../utils/otherUtils";
import ContentPreview from "./CardModals/TextModal";
import { renderMedia } from "../../utils/FileUpload";
import { getIconFromHash, timeAgo } from "../../utils/cardUtils";
import { verifyPow } from "../../utils/mine";
import { useNavigate } from 'react-router-dom';
interface RepostProps {
key?: string | number;
event: Event;
}
const RepostCard = ({
key,
event
}: RepostProps) => {
const repostedEvent = JSON.parse(event.content);
const { files } = parseContent(event);
const icon = getIconFromHash(event.pubkey);
const navigate = useNavigate();
const handleClick = () => {
navigate(`/thread/${nip19.noteEncode(event.id)}`);
};
return (
<div>
<div className="ml-1 flex text-sm text-neutral-600 gap-2.5">
Repost
@
<span className="inline-flex"><CpuChipIcon className="h-5 w-5" /> {verifyPow(event)}</span>
</div>
<div className="rounded-lg border border-neutral-700">
<div className="card break-inside-avoid h-min">
<div className="card-body">
<div className={`flex flex-col gap-2`}>
<div className={`flex flex-col break-words hover:cursor-pointer`} onClick={handleClick}>
<ContentPreview key={repostedEvent.id} eventdata={repostedEvent} />
</div>
{renderMedia(files)}
<div className={`flex justify-between items-center hover:cursor-pointer`} onClick={handleClick}>
<div className={`h-4 w-4 ${icon} rounded-full`} />
<div className="flex items-center ml-auto gap-2.5">
<div className="inline-flex text-xs text-neutral-600 gap-0.5">
<CpuChipIcon className="h-4 w-4" /> {verifyPow(repostedEvent)}
</div>
<span className="text-neutral-700">·</span>
<div className="text-xs font-semibold text-neutral-600">
{timeAgo(repostedEvent.created_at)}
</div>
</div>
</div>
</div>
</div></div>
</div>
</div>
);
};
export default RepostCard;

View File

@ -4,11 +4,12 @@ import { Event, nip19 } from "nostr-tools"
import { subNote, subNotesOnce } from '../utils/subscriptions';
import { useEffect } from 'react';
import { uniqBy } from '../utils/otherUtils';
import { DocumentTextIcon, FolderPlusIcon } from '@heroicons/react/24/outline';
import { DocumentTextIcon, FolderPlusIcon, DocumentDuplicateIcon } from '@heroicons/react/24/outline';
import { getPow } from '../utils/mine';
import PostCard from './Modals/Card';
import PostCard from './Modals/NoteCard';
import Placeholder from './Modals/Placeholder';
import NewNoteCard from './Forms/PostFormCard';
import RepostNote from './Forms/RepostNote';
type PostType = "" | "Reply" | "Quote" | undefined;
@ -17,6 +18,7 @@ const Thread = () => {
const [events, setEvents] = useState<Event[]>([]); // Initialize state
const [OPEvent, setOPEvent] = useState<Event>()
const [showForm, setShowForm] = useState(false);
const [showRepost, setShowRepost] = useState(false);
const [postType, setPostType] = useState<PostType>("");
const [hasRun, setHasRun] = useState(false);
const [preOPEvents, setPreOPEvents] = useState(['']);
@ -130,20 +132,34 @@ const Thread = () => {
onClick={() => {
setShowForm(prevShowForm => !prevShowForm);
setPostType('Reply');
setShowRepost(false)
}}
/>
<DocumentDuplicateIcon
className="h-5 w-5 text-gray-200 cursor-pointer"
onClick={() => {
setShowRepost(prevShowRepost => !prevShowRepost);
setShowForm(false);
}}
/>
<FolderPlusIcon
className="h-5 w-5 text-gray-200 cursor-pointer"
onClick={() => {
setShowForm(prevShowForm => !prevShowForm);
setPostType('Quote');
setShowRepost(false)
}}
/>
</div>
{(showForm && postType) && <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">
<span className='text-center'>{postType}-post</span>
<NewNoteCard refEvent={uniqEvents[0]} tagType={postType}/>
</div>}
{showRepost && <div className="w-full px-4 sm:px-0 sm:max-w-xl mx-auto my-2">
<span className='text-center'>Repost note</span>
<RepostNote refEvent={uniqEvents[0]}/>
</div>}
<div className="flex items-center justify-center w-full py-4">
<label htmlFor="toggleB" className="flex items-center cursor-pointer">
<div className="relative">

View File

@ -22,7 +22,7 @@ export const subGlobalFeed = (onEvent: SubCallback) => {
},
filter: {
...(prefix && { ids: ['0'.repeat(prefix)] }),
kinds: [1],
kinds: [1, 6],
since: Math.floor((Date.now() * 0.001) - (24 * 60 * 60)),
limit: 500,
},