Cleanup feeds

This commit is contained in:
Kieran 2023-01-01 10:44:38 +00:00
parent 1abb2905f0
commit 3910c0d67a
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
7 changed files with 67 additions and 50 deletions

View File

@ -1,10 +1,9 @@
import { useContext, useEffect } from "react";
import { useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import { System } from "..";
import Event from "../nostr/Event";
import EventKind from "../nostr/EventKind";
import { Subscriptions } from "../nostr/Subscriptions";
import { addNotifications, setFollows, setRelays } from "../state/Login";
import useSubscription from "./Subscription";
/**
* Managed loading data for the current logged in user
@ -13,41 +12,41 @@ export default function useLoginFeed() {
const dispatch = useDispatch();
const pubKey = useSelector(s => s.login.publicKey);
useEffect(() => {
if (pubKey) {
let sub = new Subscriptions();
sub.Id = "login";
sub.Authors.add(pubKey);
sub.Kinds.add(EventKind.ContactList);
let notifications = new Subscriptions();
notifications.Kinds.add(EventKind.TextNote);
notifications.Kinds.add(EventKind.Reaction);
notifications.PTags.add(pubKey);
sub.AddSubscription(notifications);
sub.OnEvent = (e) => {
let ev = Event.FromObject(e);
switch (ev.Kind) {
case EventKind.ContactList: {
if (ev.Content !== "") {
let relays = JSON.parse(ev.Content);
dispatch(setRelays(relays));
}
let pTags = ev.Tags.filter(a => a.Key === "p").map(a => a.PubKey);
dispatch(setFollows(pTags));
break;
}
default: {
dispatch(addNotifications(ev.ToObject()));
break;
}
}
}
System.AddSubscription(sub);
return () => System.RemoveSubscription(sub.Id);
const sub = useMemo(() => {
if(pubKey === null) {
return null;
}
let sub = new Subscriptions();
sub.Id = `login:${sub.Id}`;
sub.Authors.add(pubKey);
sub.Kinds.add(EventKind.ContactList);
let notifications = new Subscriptions();
notifications.Kinds.add(EventKind.TextNote);
notifications.Kinds.add(EventKind.Reaction);
notifications.PTags.add(pubKey);
notifications.Limit = 100;
sub.AddSubscription(notifications);
return sub;
}, [pubKey]);
return {};
const { notes } = useSubscription(sub, { leaveOpen: true });
useEffect(() => {
let metadatas = notes.filter(a => a.kind === EventKind.ContactList);
let others = notes.filter(a => a.kind !== EventKind.ContactList);
for(let md of metadatas) {
if (md.content !== "") {
let relays = JSON.parse(md.content);
dispatch(setRelays(relays));
}
let pTags = md.tags.filter(a => a[0] === "p").map(a => a[1]);
dispatch(setFollows(pTags));
}
dispatch(addNotifications(others));
}, [notes]);
}

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useReducer, useState } from "react";
import { useEffect, useReducer } from "react";
import { System } from "..";
import { Subscriptions } from "../nostr/Subscriptions";
@ -45,8 +45,10 @@ export default function useSubscription(sub, opt) {
};
}
console.debug("Adding sub: ", sub.ToObject());
System.AddSubscription(sub);
return () => {
console.debug("Adding sub: ", sub.ToObject());
System.RemoveSubscription(sub.Id);
};
}

View File

@ -6,7 +6,7 @@ import useSubscription from "./Subscription";
export default function useThreadFeed(id) {
const sub = useMemo(() => {
const thisSub = new Subscriptions();
thisSub.Id = "thread";
thisSub.Id = `thread:${thisSub.Id}`;
thisSub.Ids.add(id);
// get replies to this event
@ -26,7 +26,7 @@ export default function useThreadFeed(id) {
if (thisNote) {
let otherSubs = new Subscriptions();
otherSubs.Id = "thread-related";
otherSubs.Id = `thread-related:${otherSubs.Id}`;
for (let e of thisNote.tags.filter(a => a[0] === "e")) {
otherSubs.Ids.add(e[1]);
}

View File

@ -1,19 +1,23 @@
import { useCallback, useMemo } from "react";
import { useMemo } from "react";
import EventKind from "../nostr/EventKind";
import { Subscriptions } from "../nostr/Subscriptions";
import useSubscription from "./Subscription";
export default function useTimelineFeed(pubKeys) {
const sub = useMemo(() => {
if (pubKeys.length === 0) {
if (!Array.isArray(pubKeys)) {
pubKeys = [pubKeys];
}
if (!pubKeys || pubKeys.length === 0) {
return null;
}
let sub = new Subscriptions();
sub.Id = "timeline";
sub.Id = `timeline:${sub.Id}`;
sub.Authors = new Set(pubKeys);
sub.Kinds.add(EventKind.TextNote);
sub.Limit = 10;
sub.Limit = 20;
return sub;
}, [pubKeys]);

View File

@ -31,6 +31,11 @@ export default function LoginPage() {
}
}
async function makeRandomKey() {
let newKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
dispatch(setPrivateKey(newKey))
}
async function doNip07Login() {
let pubKey = await window.nostr.getPublicKey();
dispatch(setNip07PubKey(pubKey));
@ -64,7 +69,10 @@ export default function LoginPage() {
<p>Enter your private key:</p>
<div className="flex">
<input type="text" placeholder="Private key" className="f-grow" onChange={e => setKey(e.target.value)} />
</div>
<div className="tabs">
<div className="btn" onClick={(e) => doLogin()}>Login</div>
<div className="btn" onClick={() => makeRandomKey()}>Generate Key</div>
</div>
{altLogins()}
</>

View File

@ -1,5 +1,5 @@
import "./ProfilePage.css";
import { useEffect, useRef, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { bech32 } from "bech32";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -21,7 +21,7 @@ export default function ProfilePage() {
const id = params.id;
const user = useProfile(id);
const publisher = useEventPublisher();
const { notes } = useTimelineFeed([id]);
const { notes } = useTimelineFeed(id);
const loginPubKey = useSelector(s => s.login.publicKey);
const isMe = loginPubKey === id;
const qrRef = useRef();
@ -34,7 +34,7 @@ export default function ProfilePage() {
const [lud16, setLud16] = useState("");
const [showLnQr, setShowLnQr] = useState(false);
useEffect(() => {
useMemo(() => {
if (user) {
setName(user.name ?? "");
setPicture(user.picture ?? Nostrich);
@ -45,7 +45,7 @@ export default function ProfilePage() {
}
}, [user]);
useEffect(() => {
useMemo(() => {
// some clients incorrectly set this to LNURL service, patch this
if (lud16.toLowerCase().startsWith("lnurl")) {
let decoded = bech32.decode(lud16, 1000);
@ -62,7 +62,7 @@ export default function ProfilePage() {
}
}, [lud16]);
useEffect(() => {
useMemo(() => {
if (qrRef.current && showLnQr) {
let qr = new QRCodeStyling({
data: {lud16},

View File

@ -71,7 +71,11 @@ const LoginSlice = createSlice({
state.nip07 = true;
},
setRelays: (state, action) => {
state.relays = action.payload;
// filter out non-websocket urls
let filtered = Object.entries(action.payload)
.filter(a => a[0].startsWith("ws://") || a[0].startsWith("wss://"));
state.relays = Object.fromEntries(filtered);
},
setFollows: (state, action) => {
state.follows = action.payload;