This commit is contained in:
Kieran 2023-09-19 10:01:13 +01:00
parent 04239123bb
commit 4b2161369d
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
12 changed files with 42 additions and 65 deletions

View File

@ -3,16 +3,7 @@ import React, { useMemo, useState, ReactNode } from "react";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import { useInView } from "react-intersection-observer"; import { useInView } from "react-intersection-observer";
import { useIntl, FormattedMessage } from "react-intl"; import { useIntl, FormattedMessage } from "react-intl";
import { import { TaggedNostrEvent, HexKey, EventKind, NostrPrefix, Lists, EventExt, parseZap, NostrLink } from "@snort/system";
TaggedNostrEvent,
HexKey,
EventKind,
NostrPrefix,
Lists,
EventExt,
parseZap,
NostrLink
} from "@snort/system";
import { System } from "index"; import { System } from "index";
import useEventPublisher from "Feed/EventPublisher"; import useEventPublisher from "Feed/EventPublisher";

View File

@ -12,19 +12,16 @@ export function useReactions(subId: string, ids: Array<NostrLink>, others?: (rb:
const aTags = ids.filter(a => a.type === NostrPrefix.Address); const aTags = ids.filter(a => a.type === NostrPrefix.Address);
if (aTags.length > 0 || eTags.length > 0) { if (aTags.length > 0 || eTags.length > 0) {
const f = rb.withFilter() const f = rb
.withFilter()
.kinds( .kinds(
pref.enableReactions pref.enableReactions
? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt] ? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt]
: [EventKind.ZapReceipt, EventKind.Repost], : [EventKind.ZapReceipt, EventKind.Repost],
); );
if(aTags.length > 0) { aTags.forEach(v => f.replyToLink(v));
f.tag("a", aTags.map(v => `${v.kind}:${v.author}:${v.id}`)); eTags.forEach(v => f.replyToLink(v));
}
if(eTags.length > 0) {
f.tag("e", eTags.map(v => v.id));
}
} }
others?.(rb); others?.(rb);
return rb.numFilters > 0 ? rb : null; return rb.numFilters > 0 ? rb : null;

View File

@ -14,13 +14,9 @@ export default function useThreadFeed(link: NostrLink) {
sub.withOptions({ sub.withOptions({
leaveOpen: true, leaveOpen: true,
}); });
sub.withFilter() sub.withFilter().kinds([EventKind.TextNote]).link(link);
.kinds([EventKind.TextNote])
.link(link);
if (allEvents.length > 0) { if (allEvents.length > 0) {
const f = sub const f = sub.withFilter().kinds([EventKind.TextNote]);
.withFilter()
.kinds([EventKind.TextNote]);
allEvents.forEach(x => f.replyToLink(x)); allEvents.forEach(x => f.replyToLink(x));
} }
return sub; return sub;
@ -31,10 +27,12 @@ export default function useThreadFeed(link: NostrLink) {
useEffect(() => { useEffect(() => {
if (store.data) { if (store.data) {
const mainNotes = store.data?.filter(a => a.kind === EventKind.TextNote || a.kind === EventKind.Polls) ?? []; const mainNotes = store.data?.filter(a => a.kind === EventKind.TextNote || a.kind === EventKind.Polls) ?? [];
const links = mainNotes.map(a => [ const links = mainNotes
NostrLink.fromEvent(a), .map(a => [
...a.tags.filter(a => a[0] === "e" || a[0] === "a").map(v => NostrLink.fromTag(v)) NostrLink.fromEvent(a),
]).flat(); ...a.tags.filter(a => a[0] === "e" || a[0] === "a").map(v => NostrLink.fromTag(v)),
])
.flat();
setAllEvents(links); setAllEvents(links);
} }
}, [store.data?.length]); }, [store.data?.length]);

View File

@ -1,12 +1,5 @@
import { unwrap } from "@snort/shared"; import { unwrap } from "@snort/shared";
import { import { EventExt, NostrLink, NostrPrefix, TaggedNostrEvent, u256, Thread as ThreadInfo } from "@snort/system";
EventExt,
NostrLink,
NostrPrefix,
TaggedNostrEvent,
u256,
Thread as ThreadInfo,
} from "@snort/system";
import useThreadFeed from "Feed/ThreadFeed"; import useThreadFeed from "Feed/ThreadFeed";
import { findTag } from "SnortUtils"; import { findTag } from "SnortUtils";
import { ReactNode, createContext, useMemo, useState } from "react"; import { ReactNode, createContext, useMemo, useState } from "react";
@ -56,7 +49,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink; chil
// Root is the parent of the current note or the current note if its a root note or the root of the thread // Root is the parent of the current note or the current note if its a root note or the root of the thread
const root = useMemo(() => { const root = useMemo(() => {
const currentNote = const currentNote =
feed.thread?.find( feed.thread?.find(
ne => ne =>
ne.id === currentId || ne.id === currentId ||
(link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author), (link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author),

View File

@ -25,8 +25,8 @@ import useLogin from "Hooks/useLogin";
type Cols = "notes" | "articles" | "media" | "streams" | "notifications"; type Cols = "notes" | "articles" | "media" | "streams" | "notifications";
interface DeckScope { interface DeckScope {
thread?: NostrLink, thread?: NostrLink;
setThread: (e?: NostrLink) => void setThread: (e?: NostrLink) => void;
} }
export const DeckContext = createContext<DeckScope | undefined>(undefined); export const DeckContext = createContext<DeckScope | undefined>(undefined);
@ -35,7 +35,7 @@ export function SnortDeckLayout() {
const login = useLogin(); const login = useLogin();
const navigate = useNavigate(); const navigate = useNavigate();
const [deckScope, setDeckScope] = useState<DeckScope>({ const [deckScope, setDeckScope] = useState<DeckScope>({
setThread: (e?: NostrLink) => setDeckScope(s => ({ ...s, thread: e })) setThread: (e?: NostrLink) => setDeckScope(s => ({ ...s, thread: e })),
}); });
useLoginFeed(); useLoginFeed();

View File

@ -1,14 +1,6 @@
import "./Notifications.css"; import "./Notifications.css";
import { useEffect, useMemo, useSyncExternalStore } from "react"; import { useEffect, useMemo, useSyncExternalStore } from "react";
import { import { EventExt, EventKind, NostrEvent, NostrLink, NostrPrefix, TaggedNostrEvent, parseZap } from "@snort/system";
EventExt,
EventKind,
NostrEvent,
NostrLink,
NostrPrefix,
TaggedNostrEvent,
parseZap,
} from "@snort/system";
import { unwrap } from "@snort/shared"; import { unwrap } from "@snort/shared";
import { useUserProfile } from "@snort/system-react"; import { useUserProfile } from "@snort/system-react";
import { useInView } from "react-intersection-observer"; import { useInView } from "react-intersection-observer";

View File

@ -142,9 +142,16 @@ export const NotesTab = () => {
<> <>
<FollowsHint /> <FollowsHint />
<TaskList /> <TaskList />
<TimelineFollows postsOnly={true} noteOnClick={deckContext ? (ev) => { <TimelineFollows
deckContext.setThread(NostrLink.fromEvent(ev)); postsOnly={true}
} : undefined} /> noteOnClick={
deckContext
? ev => {
deckContext.setThread(NostrLink.fromEvent(ev));
}
: undefined
}
/>
</> </>
); );
}; };

View File

@ -1,10 +1,5 @@
import { LNURL } from "@snort/shared"; import { LNURL } from "@snort/shared";
import { import { EventPublisher, NostrEvent, NostrLink, SystemInterface } from "@snort/system";
EventPublisher,
NostrEvent,
NostrLink,
SystemInterface
} from "@snort/system";
import { generateRandomKey } from "Login"; import { generateRandomKey } from "Login";
import { isHex } from "SnortUtils"; import { isHex } from "SnortUtils";
import { LNWallet, WalletInvoiceState } from "Wallet"; import { LNWallet, WalletInvoiceState } from "Wallet";
@ -203,7 +198,7 @@ export class Zapper {
return svc; return svc;
} }
} }
}catch { } catch {
// nothing // nothing
} }
} }

View File

@ -11,6 +11,9 @@
"+aZY2h": { "+aZY2h": {
"defaultMessage": "Zap Type" "defaultMessage": "Zap Type"
}, },
"+tShPg": {
"defaultMessage": "following"
},
"+vA//S": { "+vA//S": {
"defaultMessage": "Logins" "defaultMessage": "Logins"
}, },

View File

@ -3,6 +3,7 @@
"+PzQ9Y": "Payout Now", "+PzQ9Y": "Payout Now",
"+Vxixo": "Secret Group Chat", "+Vxixo": "Secret Group Chat",
"+aZY2h": "Zap Type", "+aZY2h": "Zap Type",
"+tShPg": "following",
"+vA//S": "Logins", "+vA//S": "Logins",
"+vIQlC": "Please make sure to save the following password in order to manage your handle in the future", "+vIQlC": "Please make sure to save the following password in order to manage your handle in the future",
"+vVZ/G": "Connect", "+vVZ/G": "Connect",

View File

@ -8,11 +8,11 @@ export class NostrLink {
readonly id: string, readonly id: string,
readonly kind?: number, readonly kind?: number,
readonly author?: string, readonly author?: string,
readonly relays?: Array<string> readonly relays?: Array<string>,
) { } ) {}
encode(): string { encode(): string {
if(this.type === NostrPrefix.Note || this.type === NostrPrefix.PrivateKey || this.type === NostrPrefix.PublicKey) { if (this.type === NostrPrefix.Note || this.type === NostrPrefix.PrivateKey || this.type === NostrPrefix.PublicKey) {
return hexToBech32(this.type, this.id); return hexToBech32(this.type, this.id);
} else { } else {
return encodeTLV(this.type, this.id, this.relays, this.kind, this.author); return encodeTLV(this.type, this.id, this.relays, this.kind, this.author);
@ -39,12 +39,12 @@ export class NostrLink {
} else if (this.type === NostrPrefix.Event || this.type === NostrPrefix.Note) { } else if (this.type === NostrPrefix.Event || this.type === NostrPrefix.Note) {
return this.id === ev.id; return this.id === ev.id;
} }
return false; return false;
} }
static fromTag(tag: Array<string>) { static fromTag(tag: Array<string>) {
const relays = tag.length > 2 ? [tag[2]]: undefined; const relays = tag.length > 2 ? [tag[2]] : undefined;
switch (tag[0]) { switch (tag[0]) {
case "e": { case "e": {
return new NostrLink(NostrPrefix.Event, tag[1], undefined, undefined, relays); return new NostrLink(NostrPrefix.Event, tag[1], undefined, undefined, relays);

View File

@ -233,7 +233,7 @@ export class RequestFilterBuilder {
* Get event from link * Get event from link
*/ */
link(link: NostrLink) { link(link: NostrLink) {
if(link.type === NostrPrefix.Address) { if (link.type === NostrPrefix.Address) {
return this.tag("d", [link.id]) return this.tag("d", [link.id])
.kinds([unwrap(link.kind)]) .kinds([unwrap(link.kind)])
.authors([unwrap(link.author)]); .authors([unwrap(link.author)]);
@ -246,7 +246,7 @@ export class RequestFilterBuilder {
* Get replies to link with e/a tags * Get replies to link with e/a tags
*/ */
replyToLink(link: NostrLink) { replyToLink(link: NostrLink) {
if(link.type === NostrPrefix.Address) { if (link.type === NostrPrefix.Address) {
return this.tag("a", [`${link.kind}:${link.author}:${link.id}`]); return this.tag("a", [`${link.kind}:${link.author}:${link.id}`]);
} else { } else {
return this.tag("e", [link.id]); return this.tag("e", [link.id]);