feat: WoT filter
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import { EventKind, NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||
import { WorkerRelayInterface } from "@snort/worker-relay";
|
||||
import classNames from "classnames";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useInView } from "react-intersection-observer";
|
||||
@ -41,7 +42,7 @@ export function Note(props: NoteProps) {
|
||||
const { ref, inView } = useInView({ triggerOnce: true, rootMargin: "2000px" });
|
||||
const { ref: setSeenAtRef, inView: setSeenAtInView } = useInView({ rootMargin: "0px", threshold: 1 });
|
||||
const [showTranslation, setShowTranslation] = useState(true);
|
||||
const [translated, setTranslated] = useState<NoteTranslation>(translationCache.get(ev.id));
|
||||
const [translated, setTranslated] = useState<NoteTranslation | null>(translationCache.get(ev.id));
|
||||
const cachedSetTranslated = useCallback(
|
||||
(translation: NoteTranslation) => {
|
||||
translationCache.set(ev.id, translation);
|
||||
@ -54,7 +55,9 @@ export function Note(props: NoteProps) {
|
||||
let timeout: ReturnType<typeof setTimeout>;
|
||||
if (setSeenAtInView) {
|
||||
timeout = setTimeout(() => {
|
||||
Relay.setEventMetadata(ev.id, { seen_at: Math.round(Date.now() / 1000) });
|
||||
if (Relay instanceof WorkerRelayInterface) {
|
||||
Relay.setEventMetadata(ev.id, { seen_at: Math.round(Date.now() / 1000) });
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
return () => clearTimeout(timeout);
|
||||
|
@ -9,6 +9,7 @@ import { ReplyButton } from "@/Components/Event/Note/NoteFooter/ReplyButton";
|
||||
import { RepostButton } from "@/Components/Event/Note/NoteFooter/RepostButton";
|
||||
import ReactionsModal from "@/Components/Event/Note/ReactionsModal";
|
||||
import useLogin from "@/Hooks/useLogin";
|
||||
import useModeration from "@/Hooks/useModeration";
|
||||
import usePreferences from "@/Hooks/usePreferences";
|
||||
|
||||
export interface NoteFooterProps {
|
||||
@ -20,9 +21,13 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
const { ev } = props;
|
||||
const link = useMemo(() => NostrLink.fromEvent(ev), [ev.id]);
|
||||
const [showReactions, setShowReactions] = useState(false);
|
||||
const { isMuted } = useModeration();
|
||||
|
||||
const related = useReactions("reactions", link);
|
||||
const { replies, reactions, zaps, reposts } = useEventReactions(link, related);
|
||||
const { replies, reactions, zaps, reposts } = useEventReactions(
|
||||
link,
|
||||
related.filter(a => !isMuted(a.pubkey)),
|
||||
);
|
||||
const { positive } = reactions;
|
||||
|
||||
const readonly = useLogin(s => s.readonly);
|
||||
|
@ -1,21 +1,15 @@
|
||||
import "../EventComponent.css";
|
||||
|
||||
import ProfileImage from "@/Components/User/ProfileImage";
|
||||
import classNames from "classnames";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
interface NoteGhostProps {
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
link: string;
|
||||
}
|
||||
|
||||
export default function NoteGhost(props: NoteGhostProps) {
|
||||
const className = `note card ${props.className ?? ""}`;
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="header">
|
||||
<ProfileImage pubkey="" />
|
||||
</div>
|
||||
<div className="body">{props.children}</div>
|
||||
<div className="footer"></div>
|
||||
<div className={classNames("p bb", props.className)}>
|
||||
<FormattedMessage defaultMessage="Loading note: {id}" values={{ id: props.link }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -57,8 +57,6 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
|
||||
waitUntilInView={false}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <NoteGhost className={className}>Loading thread root.. ({thread.data?.length} notes loaded)</NoteGhost>;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,16 +73,18 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
|
||||
function renderCurrent() {
|
||||
if (thread.current) {
|
||||
const note = thread.data.find(n => n.id === thread.current);
|
||||
return (
|
||||
note && (
|
||||
if (note) {
|
||||
return (
|
||||
<Note
|
||||
data={note}
|
||||
options={{ showReactionsLink: true, showMediaSpotlight: true }}
|
||||
threadChains={thread.chains}
|
||||
onClick={navigateThread}
|
||||
/>
|
||||
)
|
||||
);
|
||||
);
|
||||
} else {
|
||||
return <NoteGhost link={thread.current} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +100,6 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
|
||||
|
||||
const parentText = formatMessage({
|
||||
defaultMessage: "Parent",
|
||||
id: "ADmfQT",
|
||||
description: "Link to parent note in thread",
|
||||
});
|
||||
|
||||
@ -134,10 +133,15 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
|
||||
{thread.root && renderRoot(thread.root)}
|
||||
{thread.root && renderChain(chainKey(thread.root))}
|
||||
{!thread.root && renderCurrent()}
|
||||
{!thread.root && !thread.current && (
|
||||
<NoteGhost>
|
||||
<FormattedMessage defaultMessage="Looking up thread..." />
|
||||
</NoteGhost>
|
||||
{thread.mutedData.length > 0 && (
|
||||
<div className="p br b mx-2 my-3 bg-gray-ultradark text-gray-light font-medium cursor-pointer">
|
||||
<FormattedMessage
|
||||
defaultMessage="{n} notes have been muted"
|
||||
values={{
|
||||
n: thread.mutedData.length,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
@ -1,15 +1,21 @@
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
|
||||
import { UserRelays } from "@/Cache";
|
||||
import useWoT from "@/Hooks/useWoT";
|
||||
import { getRelayName } from "@/Utils";
|
||||
|
||||
export function UserDebug({ pubkey }: { pubkey: string }) {
|
||||
const profile = useUserProfile(pubkey);
|
||||
const relays = UserRelays.getFromCache(pubkey);
|
||||
const wot = useWoT();
|
||||
|
||||
return (
|
||||
<div className="text-xs">
|
||||
<div className="flex flex-col overflow-wrap">
|
||||
<div className="flex justify-between gap-1">
|
||||
<div>WoT Distance:</div>
|
||||
<div>{wot.followDistance(pubkey)}</div>
|
||||
</div>
|
||||
{Object.entries(profile ?? {}).map(([k, v]) => {
|
||||
let vv = <div>{v}</div>;
|
||||
|
||||
|
Reference in New Issue
Block a user