UI improvements and add abt section

This commit is contained in:
smolgrrr 2023-10-31 22:12:07 +11:00
parent d87d1d62aa
commit 808a599e4c
8 changed files with 82 additions and 68 deletions

View File

@ -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>

View File

@ -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 (

View File

@ -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;

View File

@ -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>
); );
} }

View File

@ -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" />

View File

@ -92,10 +92,10 @@ const PostCard = ({ key, event, metadata, replyCount }: { key: string, event: Ev
</div> </div>
<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>
</> </>
); );

View File

@ -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>
); );

View File

@ -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" />