mirror of
https://github.com/smolgrrr/TAO.git
synced 2024-09-20 09:21:25 +00:00
UI improvements and add abt section
This commit is contained in:
parent
d87d1d62aa
commit
808a599e4c
@ -10,10 +10,11 @@ export default function Header() {
|
|||||||
<span className="font-bold">The Anon Operation</span>
|
<span className="font-bold">The Anon Operation</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<a href='/settings'>
|
||||||
<button className="ml-auto pr-4">
|
<button className="ml-auto pr-4">
|
||||||
<QuestionMarkCircleIcon className="h-6 w-6 text-transperant" />
|
<QuestionMarkCircleIcon className="h-6 w-6 text-transperant" />
|
||||||
</button>
|
</button>
|
||||||
<a href='/settings'>
|
|
||||||
<button className="">
|
<button className="">
|
||||||
<Cog6ToothIcon className="h-6 w-6 text-transperant" />
|
<Cog6ToothIcon className="h-6 w-6 text-transperant" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -18,7 +18,7 @@ const LinkModal = ({ url }: { url: string }) => {
|
|||||||
}, [url]);
|
}, [url]);
|
||||||
|
|
||||||
if (!linkPreview) {
|
if (!linkPreview) {
|
||||||
return <a className='hover:underline' href={url}>{url}</a>; // or some loading state
|
return <a className='hover:underline text-xs text-neutral-500' href={url}>{url}</a>; // or some loading state
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -6,59 +6,61 @@ import { nip19 } from "nostr-tools";
|
|||||||
import LinkModal from "./LinkPreview";
|
import LinkModal from "./LinkPreview";
|
||||||
|
|
||||||
const ContentPreview = ({ key, comment }: { key: string, comment: string }) => {
|
const ContentPreview = ({ key, comment }: { key: string, comment: string }) => {
|
||||||
const [finalComment, setFinalComment] = useState(comment)
|
const [finalComment, setFinalComment] = useState(comment)
|
||||||
const [quoteEvents, setQuoteEvents] = useState<Event[]>([]); // Initialize state
|
const [quoteEvents, setQuoteEvents] = useState<Event[]>([]); // Initialize state
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
const [url, setUrl] = useState('')
|
const [url, setUrl] = useState('')
|
||||||
|
|
||||||
// Define your callback function for subGlobalFeed
|
// Define your callback function for subGlobalFeed
|
||||||
const onEvent = (event: Event, relay: string) => {
|
const onEvent = (event: Event, relay: string) => {
|
||||||
setQuoteEvents((prevEvents) => [...prevEvents, event]);
|
setQuoteEvents((prevEvents) => [...prevEvents, event]);
|
||||||
};
|
};
|
||||||
|
|
||||||
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];
|
||||||
if (nostrQuoteID && nostrQuoteID.length > 0) {
|
if (nostrQuoteID && nostrQuoteID.length > 0) {
|
||||||
let id_to_hex = String(nip19.decode(nostrQuoteID as string).data);
|
let id_to_hex = String(nip19.decode(nostrQuoteID as string).data);
|
||||||
subNoteOnce(id_to_hex, onEvent);
|
subNoteOnce(id_to_hex, onEvent);
|
||||||
setFinalComment(finalComment.replace('nostr:'+nostrQuoteID, '').trim())
|
setFinalComment(finalComment.replace('nostr:' + nostrQuoteID, '').trim())
|
||||||
}
|
}
|
||||||
}, [comment, finalComment]);
|
}, [comment, finalComment]);
|
||||||
|
|
||||||
const getMetadataEvent = (event: Event) => {
|
const getMetadataEvent = (event: Event) => {
|
||||||
const metadataEvent = quoteEvents.find(e => e.pubkey === event.pubkey && e.kind === 0);
|
const metadataEvent = quoteEvents.find(e => e.pubkey === event.pubkey && e.kind === 0);
|
||||||
if (metadataEvent) {
|
if (metadataEvent) {
|
||||||
return metadataEvent;
|
return metadataEvent;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="mr-2 flex flex-col break-words">
|
|
||||||
{isExpanded ? finalComment : finalComment.slice(0, 240)}
|
|
||||||
{finalComment.length > 240 && (
|
|
||||||
<button className="text-gray-500" onClick={() => setIsExpanded(true)}>
|
|
||||||
... Read more
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{url !== '' && (
|
|
||||||
<LinkModal key={key} url={url} />
|
|
||||||
)}
|
|
||||||
{quoteEvents[0] && quoteEvents.length > 0 && (
|
|
||||||
<a href={`/thread/${nip19.noteEncode(quoteEvents[0].id)}`}>
|
|
||||||
<QuoteEmbed key={key} event={quoteEvents[0]} metadata={getMetadataEvent(quoteEvents[0])} />
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ContentPreview;
|
return (
|
||||||
|
<div className="mr-2 flex flex-col break-words text-sm">
|
||||||
|
{isExpanded ? finalComment : finalComment.slice(0, 240)}
|
||||||
|
{finalComment.length > 240 && (
|
||||||
|
<button
|
||||||
|
className="text-gray-500 text-sm text-neutral-500"
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
|
>
|
||||||
|
{isExpanded ? '...Read less' : '...Read more'}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{url !== '' && (
|
||||||
|
<LinkModal key={key} url={url} />
|
||||||
|
)}
|
||||||
|
{quoteEvents[0] && quoteEvents.length > 0 && (
|
||||||
|
<a href={`/thread/${nip19.noteEncode(quoteEvents[0].id)}`}>
|
||||||
|
<QuoteEmbed key={key} event={quoteEvents[0]} metadata={getMetadataEvent(quoteEvents[0])} />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContentPreview;
|
||||||
|
@ -3,7 +3,7 @@ import { PropsWithChildren } from 'react';
|
|||||||
export default function CardContainer({ children }: PropsWithChildren) {
|
export default function CardContainer({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<div className="card bg-gradient-to-r from-black to-neutral-950 shadow-lg shadow-black">
|
<div className="card bg-gradient-to-r from-black to-neutral-950 shadow-lg shadow-black">
|
||||||
<div className="card-body p-1">{children}</div>
|
<div className="card-body p-4">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -145,7 +145,7 @@ const NewThreadCard: React.FC = () => {
|
|||||||
{doingWorkProp ? (
|
{doingWorkProp ? (
|
||||||
<div className='flex animate-pulse text-sm text-gray-300'>
|
<div className='flex animate-pulse text-sm text-gray-300'>
|
||||||
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
||||||
<span>Working...</span>
|
<span>Generating Proof-of-Work...</span>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div id="postFormError" className="text-red-500" />
|
<div id="postFormError" className="text-red-500" />
|
||||||
|
@ -93,9 +93,9 @@ const PostCard = ({ key, event, metadata, replyCount }: { key: string, event: Ev
|
|||||||
<div className="mr-2 flex flex-col break-words">
|
<div className="mr-2 flex flex-col break-words">
|
||||||
<ContentPreview key={event.id} comment={comment} />
|
<ContentPreview key={event.id} comment={comment} />
|
||||||
</div>
|
</div>
|
||||||
{renderMedia(file)}
|
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
{renderMedia(file)}
|
||||||
</CardContainer>
|
</CardContainer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
// import {powEvent} from './system';
|
// import {powEvent} from './system';
|
||||||
// import {publish} from './relays';
|
// import {publish} from './relays';
|
||||||
import { addRelay } from '../utils/relays';
|
import { addRelay } from '../utils/relays';
|
||||||
|
import { CpuChipIcon } from '@heroicons/react/24/outline';
|
||||||
const Settings = () => {
|
const Settings = () => {
|
||||||
const [filterDifficulty, setFilterDifficulty] = useState(localStorage.getItem('filterDifficulty') || 21);
|
const [filterDifficulty, setFilterDifficulty] = useState(localStorage.getItem('filterDifficulty') || 21);
|
||||||
const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || 21);
|
const [difficulty, setDifficulty] = useState(localStorage.getItem('difficulty') || 21);
|
||||||
@ -20,9 +20,9 @@ const Settings = () => {
|
|||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// addRelay('wss://powrelay.xyz');
|
// addRelay('wss://powrelay.xyz');
|
||||||
// }, []);
|
// }, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settings-page bg-black text-white p-8">
|
<div className="settings-page bg-black text-white p-8">
|
||||||
@ -31,7 +31,9 @@ const Settings = () => {
|
|||||||
<div className="flex flex-wrap -mx-2 mb-4">
|
<div className="flex flex-wrap -mx-2 mb-4">
|
||||||
<div className="w-full md:w-1/3 px-2 mb-4 md:mb-0">
|
<div className="w-full md:w-1/3 px-2 mb-4 md:mb-0">
|
||||||
<label className="block mb-2" htmlFor="filterDifficulty">
|
<label className="block mb-2" htmlFor="filterDifficulty">
|
||||||
Filter Difficulty:
|
<span style={{ display: 'inline-flex', alignItems: 'center' }}>
|
||||||
|
Proof-of-Work Difficulty Filter {'('}<CpuChipIcon className="h-4 w-4" />{'>'}X to appear on feed{')'}:
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="filterDifficulty"
|
id="filterDifficulty"
|
||||||
@ -44,7 +46,9 @@ const Settings = () => {
|
|||||||
|
|
||||||
<div className="w-full md:w-1/3 px-2 mb-4 md:mb-0">
|
<div className="w-full md:w-1/3 px-2 mb-4 md:mb-0">
|
||||||
<label className="block mb-2" htmlFor="difficulty">
|
<label className="block mb-2" htmlFor="difficulty">
|
||||||
Post Difficulty:
|
<span style={{ display: 'inline-flex', alignItems: 'center' }}>
|
||||||
|
Post Difficulty {'('}<CpuChipIcon className="h-4 w-4" /> required to make post{')'}:
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="difficulty"
|
id="difficulty"
|
||||||
@ -61,13 +65,20 @@ const Settings = () => {
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className="settings-page py-10">
|
<div className="settings-page py-10">
|
||||||
<h1 className="text-lg font-semibold mb-4">About</h1>
|
<h1 className="text-lg font-semibold mb-4">About</h1>
|
||||||
<div className='flex'>
|
<div className="flex flex-col">
|
||||||
<a href='https://github.com/smolgrrr/TAO'>
|
<p>The Anon Operation (TAO) is an anonymous-first forum, built upon the <a className="underline" href="https://nostr.com/">NOSTR protocol</a>.</p>
|
||||||
<img src="https://img.shields.io/github/stars/smolgrrr/TAO.svg?style=social"/>
|
<br />
|
||||||
</a>
|
<p>TAO is built to facilitate unstoppable free speech on the internet.</p>
|
||||||
</div>
|
<p>-PWA to be widely accessible with distribution via URLS, and to side-step App Store gatekeeping</p>
|
||||||
|
<p>-Uses NOSTR as a censorship-resistant global "social" network</p>
|
||||||
|
<p>-Employs Proof-of-Work (PoW) as a spam prevention mechanism, as opposed to Captcha, moderation or other verification methods</p>
|
||||||
|
<br />
|
||||||
|
<a href="https://github.com/smolgrrr/TAO">
|
||||||
|
<img src="https://img.shields.io/github/stars/smolgrrr/TAO.svg?style=social" alt="Github Stars Badge" />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -173,7 +173,7 @@ const ThreadPost = ({ OPEvent, state, type }: { OPEvent: NostrEvent, state: Bool
|
|||||||
{doingWorkProp ? (
|
{doingWorkProp ? (
|
||||||
<div className='flex animate-pulse text-sm text-gray-300'>
|
<div className='flex animate-pulse text-sm text-gray-300'>
|
||||||
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
<CpuChipIcon className="h-4 w-4 ml-auto" />
|
||||||
<span>Working...</span>
|
<span>Generating Proof-of-Work...</span>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div id="postFormError" className="text-red-500" />
|
<div id="postFormError" className="text-red-500" />
|
||||||
|
Loading…
Reference in New Issue
Block a user