Skip to content

Commit

Permalink
client-web: added new following feed; performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
franzos committed Sep 1, 2023
1 parent 090c083 commit f778596
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 194 deletions.
55 changes: 11 additions & 44 deletions client-web/src/components/create-event-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,67 +55,35 @@ export const CreateEventForm = () => {
]
);

const [eventContent, setEventContent] = useState<string>("");
const [relayUrls, setRelayUrls] = useState<string[]>([]);
const publicKey = useRef<string | undefined>(undefined);

const toast = useToast();

const currentPubkey = useRef<string | undefined>(undefined);

useEffect(() => {
const loadUser = async () => {
if (
newEventName !== "NewShortTextNoteResponse"
// newEventName !== "NewQuoteRepost"
!publicKeyTags ||
newEventName !== "NewShortTextNoteResponse" ||
publicKeyTags[0][1] === publicKey.current
) {
return;
}

const publicKey = useNClient.getState().newEvent?.pubkey;
if (!publicKey) {
return;
}
if (currentPubkey.current === publicKey) {
return;
}
currentPubkey.current = publicKey;

const foundUsers: {
user: NUser;
relayUrls: string[];
}[] = [];
const foundRelayUrls = [];
if (publicKeyTags) {
publicKey.current = publicKeyTags[0][1] || undefined;
for (const tags of publicKeyTags) {
let relayUrl;
// let relayUrl;
/**
* Get the relay url from the tags [p, pubkey, relayUrl]
*/
if (tags.length === 2) {
relayUrl = tags[1];
foundRelayUrls.push(tags[1]);
}
const key = tags[0];
const record = await useNClient.getState().getUser(key);
if (record) {
foundUsers.push({
user: record.user,
relayUrls: record.relayUrls
? record.relayUrls
: relayUrl
? [relayUrl]
: [],
});
} else {
foundUsers.push({
user: new NUser({ pubkey: key }),
relayUrls: relayUrl ? [relayUrl] : [],
});
}
}
}
if (foundUsers.length > 0) {
setUsers(foundUsers);
}
if (foundRelayUrls.length > 0) {
setRelayUrls(foundRelayUrls);
}
Expand Down Expand Up @@ -163,7 +131,7 @@ export const CreateEventForm = () => {
return;
}

if (!newEvent.content) {
if (eventContent === "") {
setErrors(["Event content is required"]);
toast({
title: "Error",
Expand All @@ -176,6 +144,7 @@ export const CreateEventForm = () => {
}

try {
useNClient.getState().setNewEventContent(eventContent);
const evId = await useNClient.getState().signAndSendEvent({
event: newEvent,
relayUrls,
Expand Down Expand Up @@ -299,10 +268,8 @@ export const CreateEventForm = () => {
<Input
type="text"
as={eventKind === NEVENT_KIND.LONG_FORM_CONTENT ? Textarea : Input}
value={useNClient.getState().newEvent?.content || ""}
onChange={(e) =>
useNClient.getState().setNewEventContent(e.target.value)
}
value={eventContent}
onChange={(e) => setEventContent(e.target.value)}
placeholder="Enter event content"
/>
</FormControl>
Expand Down
8 changes: 4 additions & 4 deletions client-web/src/components/event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,10 @@ export function Event({
{reposts && (
<>
<Text>Reposts</Text>
{reposts.map((r) => {
{reposts.map((r, index) => {
const user = r.user ? r.user : { pubkey: r.event.pubkey };
return (
<Box key={`${r.event.id}_${user.pubkey}_reposts`}>
<Box key={`${index}_${r.event.id}_${user.pubkey}_reposts`}>
<UserIcon
user={user}
options={{
Expand All @@ -450,8 +450,8 @@ export function Event({
mentions && (
<>
<Text>Mentions</Text>
{mentions.map((u) => (
<Box key={`${event.id}_${u.pubkey}_mention`}>
{mentions.map((u, index) => (
<Box key={`${index}_${event.id}_${u.pubkey}_mention`}>
<UserIcon
user={u}
options={{
Expand Down
2 changes: 1 addition & 1 deletion client-web/src/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const MAX_EVENTS = 25;
export const MAX_EVENTS = 50;
export const DEFAULT_RELAYS = {
"wss://relay.shitforce.one": {
read: true,
Expand Down
7 changes: 7 additions & 0 deletions client-web/src/layouts/primary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import FormatListBulletedIcon from "mdi-react/FormatListBulletedIcon";
import AccountKeyIcon from "mdi-react/AccountKeyIcon";
import AccountMultipleIcon from "mdi-react/AccountMultipleIcon";
import TrayFullIcon from "mdi-react/TrayFullIcon";
import PlaylistStarIcon from "mdi-react/PlaylistStarIcon";
import AccountEditIcon from "mdi-react/AccountEditIcon";
import { ConnectModal } from "../components/connect-modal";

Expand Down Expand Up @@ -72,6 +73,12 @@ export function PrimaryLayout() {
leftIcon={<Icon as={AccountMultipleIcon} marginRight={1} />}
/> */}

<MenuItem
label="Following feed"
to="/following-feed"
leftIcon={<Icon as={PlaylistStarIcon} marginRight={1} />}
/>

<MenuItem
label="Following"
value={followingUsers.length}
Expand Down
2 changes: 2 additions & 0 deletions client-web/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { RelaysRoute } from "./routes/relays.tsx";
import { PublishingQueueRoute } from "./routes/queue.tsx";
import { UserMentionsRoute } from "./routes/mentions.tsx";
import { UserProfileRoute } from "./routes/user-profile.tsx";
import { FollowingFeedRoute } from "./routes/following-feed.tsx";
import "./index.css";

const init = async () => {
Expand All @@ -34,6 +35,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<Route path="/account" element={<AccountRoute />} />
<Route path="/profile" element={<UserProfileRoute />} />
<Route path="/following" element={<FollowingRoute />} />
<Route path="/following-feed" element={<FollowingFeedRoute />} />
<Route path="/mentions/:pubkey" element={<UserMentionsRoute />} />
<Route path="/subscriptions" element={<SubscriptionsRoute />} />
<Route path="/relays" element={<RelaysRoute />} />
Expand Down
80 changes: 80 additions & 0 deletions client-web/src/routes/following-feed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Heading, Box, Text, Grid } from "@chakra-ui/react";
import { NEVENT_KIND, NFilters } from "@nostr-ts/common";
import { useEffect } from "react";
import { useNClient } from "../state/client";
import { Events } from "../components/events";
import { MAX_EVENTS } from "../defaults";
import { CreateEventForm } from "../components/create-event-form";
import { User } from "../components/user";

export function FollowingFeedRoute() {
const [connected, eventsEqualOrMoreThanMax, followingUserIds] = useNClient(
(state) => [
state.connected,
state.events.length >= state.maxEvents,
state.followingUserIds,
]
);
const filters = new NFilters({
limit: MAX_EVENTS,
authors: followingUserIds,
kinds: [NEVENT_KIND.SHORT_TEXT_NOTE, NEVENT_KIND.LONG_FORM_CONTENT],
});

const view = `following-feed`;

const init = async () => {
if (!connected) return;

await useNClient.getState().setMaxEvents(MAX_EVENTS);
await useNClient.getState().clearEvents();
await useNClient.getState().setViewSubscription(view, filters);
};

/**
* Handle initial load
*/
useEffect(() => {
init();
}, []);

/**
* Remove subscription when we hit the limit
*/
useEffect(() => {
const remove = async () => {
if (!connected) return;
await useNClient.getState().removeViewSubscription(view);
};

if (eventsEqualOrMoreThanMax) {
remove();
}
}, [eventsEqualOrMoreThanMax]);

return (
<Grid templateColumns={["1fr", "2fr 1fr"]} gap={20}>
<Box maxHeight="80vh" overflowY="auto">
<Box>
{connected ? (
<Events
userComponent={User}
view={view}
filters={filters}
connected={connected}
/>
) : (
<Text>Not connected.</Text>
)}
</Box>
</Box>

<Box display="flex" flexDirection="column">
<Heading as="h2" size="md" marginBottom={4}>
Broadcast to the Network
</Heading>
<CreateEventForm />
</Box>
</Grid>
);
}
1 change: 1 addition & 0 deletions client-web/src/routes/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function ProfileRoute() {
// USER

if (!userRecord || userRecord.user.pubkey !== pubkey) {
await useNClient.getState().setMaxEvents(MAX_EVENTS);
await useNClient.getState().clearEvents();
await useNClient.getState().setViewSubscription(view, defaultFilters);

Expand Down
15 changes: 9 additions & 6 deletions client-web/src/routes/welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function WelcomeRoute() {
const init = async () => {
if (!connected || initDone.current) return;
initDone.current = true;
await useNClient.getState().setMaxEvents(MAX_EVENTS);
await useNClient.getState().clearEvents();
await useNClient.getState().setViewSubscription("welcome", defaultFilters);
};
Expand Down Expand Up @@ -60,12 +61,14 @@ export function WelcomeRoute() {
<Grid templateColumns={["1fr", "2fr 1fr"]} gap={20}>
<Box>
{connected ? (
<Events
userComponent={User}
view="welcome"
filters={defaultFilters}
connected={connected}
/>
<Box maxHeight="80vh" overflowY="auto">
<Events
userComponent={User}
view="welcome"
filters={defaultFilters}
connected={connected}
/>
</Box>
) : (
<Box maxWidth={600}>
<Heading size="lg">About Nostr</Heading>
Expand Down
Loading

0 comments on commit f778596

Please sign in to comment.